summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2022-12-14 10:29:45 -0500
committerpommicket <pommicket@gmail.com>2022-12-14 10:29:45 -0500
commit3f839f2ec08ffbb75bee391202e7e0d7432d97e0 (patch)
treedd069d2e87f2e52e00eb65abfbc9e52387996cb7
parentc83b409a0da900a099339a2e4fb023458c227fd3 (diff)
infinite mirrors, etc.
-rw-r--r--src/main.rs26
-rw-r--r--src/sdf.rs95
-rw-r--r--src/win.rs13
3 files changed, 55 insertions, 79 deletions
diff --git a/src/main.rs b/src/main.rs
index e5ad5cb..2594fdd 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,7 +1,7 @@
/*
@TODO:
-- fix rotation
- fullscreen key
+- mathematical analysis
- options for:
- max framerate
- mouse sensitivity
@@ -61,19 +61,11 @@ impl View {
}
fn try_main() -> Result<(), String> {
- use sdf::{R3ToR, RToR, R3ToR3, Constant};
+ use sdf::{Constant, R3ToR, R3ToR3, RToR};
let funciton = R3ToR::compose(
- R3ToR3::Sin(Constant::from(0.5))
- .compose(R3ToR3::Translate((
- Constant::Time(0.1, 0.0),
- Constant::F32(0.5),
- Constant::F32(0.7)
- ).into())),
- R3ToR::smooth_min(
- R3ToR::sphere_f32(1.2),
- R3ToR::cube_f32(1.0)
- ),
- RToR::Identity
+ R3ToR3::InfiniteMirrors(Constant::from(2.0)),
+ R3ToR::sphere_f32(0.2),
+ RToR::Identity,
);
let my_sdf = sdf::Sdf::from_function(funciton);
@@ -246,12 +238,8 @@ void main() {
if window.any_key_down(&[PageDown, NumPad3, N]) {
dl -= 1.0;
}
- let speed_multiplier = if window.is_shift_down() {
- 10.0
- } else {
- 1.0
- };
-
+ let speed_multiplier = if window.is_shift_down() { 10.0 } else { 1.0 };
+
let motion = Vec3::new(dx, dy, dz);
if let Some(motion) = motion.try_normalize(0.001) {
let move_speed = 4.0 * speed_multiplier;
diff --git a/src/sdf.rs b/src/sdf.rs
index e7c78b8..f79dc3a 100644
--- a/src/sdf.rs
+++ b/src/sdf.rs
@@ -1,13 +1,12 @@
#![allow(dead_code)] // @TODO @TEMPORARY
-use std::fmt::{self, Write, Display, Formatter};
+use std::fmt::{self, Display, Formatter, Write};
// we're only writing numbers and strings so write! should never fail.
macro_rules! write_str {
($( $arg:tt )*) => { write!($($arg)*).unwrap() }
}
-
/// these are constant across 3D space, not across time/user input/etc.
pub enum Constant {
F32(f32),
@@ -21,12 +20,12 @@ impl From<f32> for Constant {
}
}
-impl Constant {
- fn to_glsl(&self) -> String {
+impl Display for Constant {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
use Constant::*;
match self {
- F32(x) => format!("{x:.1}"),
- Time(x, y) => format!("({x:.1} * u_time + {y:.1})"),
+ F32(x) => write!(f, "{x:.1}"),
+ Time(x, y) => write!(f, "({x:.1} * u_time + {y:.1})"),
}
}
}
@@ -39,14 +38,10 @@ impl From<(Constant, Constant, Constant)> for Constant3 {
}
}
-impl Constant3 {
- fn to_glsl(&self) -> String {
- format!(
- "vec3({}, {}, {})",
- self.0.to_glsl(),
- self.1.to_glsl(),
- self.2.to_glsl()
- )
+impl Display for Constant3 {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ let Self(x, y, z) = self;
+ write!(f, "vec3({x}, {y}, {z})")
}
}
@@ -55,7 +50,7 @@ pub enum R3ToR3 {
Compose(Box<R3ToR3>, Box<R3ToR3>),
Translate(Constant3),
Sin(Constant),
- //@TODO InfiniteMirrors(f32)
+ InfiniteMirrors(Constant),
}
pub enum RToR {
@@ -101,15 +96,15 @@ impl R3ToR {
pub fn mix_f32(a: Self, b: Self, t: f32) -> Self {
Self::mix(a, b, t.into())
}
-
+
pub fn min(a: Self, b: Self) -> Self {
Self::Min(Box::new(a), Box::new(b))
}
-
+
pub fn smooth_min(a: Self, b: Self) -> Self {
Self::SmoothMin(Box::new(a), Box::new(b))
}
-
+
pub fn compose(pre: R3ToR3, f: Self, post: RToR) -> Self {
Self::Compose(Box::new(pre), Box::new(f), Box::new(post))
}
@@ -117,11 +112,11 @@ impl R3ToR {
#[derive(Clone, Copy)]
struct Variable {
- id: u32
+ id: u32,
}
impl Display for Variable {
- fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "v{}", self.id)
}
}
@@ -141,7 +136,7 @@ impl VarCounter {
}
fn next(&mut self) -> Variable {
- let ret = Variable { id: self.idx};
+ let ret = Variable { id: self.idx };
self.idx += 1;
ret
}
@@ -166,18 +161,13 @@ impl Function for RToR {
Identity => input,
Add(x) => {
let output = var.next();
- write_str!(
- code,
- "float {output} = {input} + {};\n",
- x.to_glsl()
- );
+ write_str!(code, "float {output} = {input} + {x};\n");
output
}
Compose(a, b) => {
let a_output = a.to_glsl(input, code, var);
- let b_output = b.to_glsl(a_output, code, var);
- b_output
- },
+ b.to_glsl(a_output, code, var)
+ }
}
}
}
@@ -190,29 +180,33 @@ impl Function for R3ToR3 {
Identity => input,
Translate(by) => {
let output = var.next();
- write_str!(
- code,
- "vec3 {output} = {input} + {};\n",
- by.to_glsl()
- );
+ write_str!(code, "vec3 {output} = {input} + {by};\n");
output
}
Sin(c) => {
// we shouldn't just do sin(c x), since that
// would multiply the derivative by c (which breaks the SDF if c > 1)
// so we'll do sin(c x) / c instead.
- let c = c.to_glsl();
let output = var.next();
+ write_str!(code, "vec3 {output} = sin({c} * {input}) * (1.0 / {c});\n");
+ output
+ }
+ InfiniteMirrors(c) => {
+ // similar to Sin(c), but uses mod instead
+ let q = var.next();
+ let r = var.next();
+ let output = var.next();
+ write_str!(code, "vec3 {q} = mod(floor({input} * {c}), 2.0);\n");
+ write_str!(code, "vec3 {r} = mod({input} * {c}, 1.0);\n");
write_str!(
code,
- "vec3 {output} = sin({c} * {input}) * (1.0 / {c});\n"
+ "vec3 {output} = (1.0 / {c}) * ({q} + {r} * (1.0 - 2 * {q}));\n"
);
output
- },
+ }
Compose(a, b) => {
let a_output = a.to_glsl(input, code, var);
- let b_output = b.to_glsl(a_output, code, var);
- b_output
+ b.to_glsl(a_output, code, var)
}
}
}
@@ -225,13 +219,11 @@ impl Function for R3ToR {
// thanks to https://iquilezles.org/articles/distfunctions/ for
// these SDFs.
Sphere(r) => {
- let r = r.to_glsl();
let output = var.next();
write_str!(code, "float {output} = length({input}) - {r};\n");
output
}
Cube(r) => {
- let r = r.to_glsl();
let q = var.next();
write_str!(code, "vec3 {q} = abs({input}) - {r};\n");
let output = var.next();
@@ -242,7 +234,6 @@ impl Function for R3ToR {
output
}
Mix(a, b, t) => {
- let t = t.to_glsl();
let a_output = a.to_glsl(input, code, var);
let b_output = b.to_glsl(input, code, var);
let output = var.next();
@@ -256,12 +247,9 @@ impl Function for R3ToR {
let a_output = a.to_glsl(input, code, var);
let b_output = b.to_glsl(input, code, var);
let output = var.next();
- write_str!(
- code,
- "float {output} = min({a_output}, {b_output});\n"
- );
+ write_str!(code, "float {output} = min({a_output}, {b_output});\n");
output
- },
+ }
SmoothMin(a, b) => {
let a_output = a.to_glsl(input, code, var);
let b_output = b.to_glsl(input, code, var);
@@ -275,13 +263,12 @@ impl Function for R3ToR {
"float {output} = sdf_smooth_min({a_output}, {b_output}, {k});\n"
);
output
- },
+ }
Compose(pre, f, post) => {
let pre_output = pre.to_glsl(input, code, var);
let f_output = f.to_glsl(pre_output, code, var);
- let post_output = post.to_glsl(f_output, code, var);
- post_output
- },
+ post.to_glsl(f_output, code, var)
+ }
}
}
}
@@ -300,13 +287,15 @@ impl Sdf {
/// appends some glsl code including a function `float sdf(vec3) { ... }`
pub fn to_glsl(&self, code: &mut String) {
- code.push_str("
+ code.push_str(
+ "
float sdf_smooth_min(float a, float b, float k) {
k = clamp(k, 0.0, 1.0);
float h = max(k-abs(a-b), 0.0)/k;
return min(a, b) - h*h*h*k*(1.0/6.0);
}
-");
+",
+ );
code.push_str("float sdf(vec3 p) {\n");
let mut var = VarCounter::new();
write_str!(code, "vec3 {} = p;\n", var.next());
diff --git a/src/win.rs b/src/win.rs
index d392819..83e2e29 100644
--- a/src/win.rs
+++ b/src/win.rs
@@ -8,7 +8,6 @@ use std::ffi::{c_char, c_int, c_uint, c_void, CStr, CString};
use std::sync::Mutex;
use std::{fmt, mem};
-
pub type AudioCallback = fn(sample_rate: u32, samples: &mut [f32]);
struct AudioData {
@@ -445,7 +444,7 @@ out vec4 o_color;
let mut status: GLint = 0;
unsafe { gl::GetShaderiv(id, gl::COMPILE_STATUS, (&mut status) as _) };
if status == 0 {
- return Err(format!("failed to compile"));
+ return Err("failed to compile".to_string());
}
}
@@ -494,7 +493,7 @@ impl Program {
let mut status: GLint = 0;
unsafe { gl::GetProgramiv(id, gl::LINK_STATUS, (&mut status) as _) };
if status == 0 {
- return Err(format!("failed to link"));
+ return Err("failed to link".to_string());
}
}
@@ -795,7 +794,7 @@ impl Window {
pub fn aspect_ratio(&self) -> f32 {
let (w, h) = self.size();
- return w as f32 / h as f32;
+ w as f32 / h as f32
}
pub fn viewport(&mut self, x: i32, y: i32, w: i32, h: i32) {
@@ -1078,15 +1077,15 @@ impl Window {
pub fn any_key_down(&mut self, keys: &[Key]) -> bool {
keys.iter().any(|&k| self.is_key_down(k))
}
-
+
pub fn is_shift_down(&mut self) -> bool {
self.is_key_down(Key::LShift) || self.is_key_down(Key::RShift)
}
-
+
pub fn is_ctrl_down(&mut self) -> bool {
self.is_key_down(Key::LCtrl) || self.is_key_down(Key::RCtrl)
}
-
+
pub fn is_alt_down(&mut self) -> bool {
self.is_key_down(Key::LAlt) || self.is_key_down(Key::RAlt)
}