diff options
-rw-r--r-- | src/main.rs | 33 | ||||
-rw-r--r-- | src/sdf.rs | 103 | ||||
-rw-r--r-- | src/win.rs | 33 |
3 files changed, 137 insertions, 32 deletions
diff --git a/src/main.rs b/src/main.rs index 2bcdd06..e5ad5cb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -61,10 +61,19 @@ impl View { } fn try_main() -> Result<(), String> { - use sdf::{R3ToR}; - let funciton = R3ToR::smooth_min( - R3ToR::sphere_f32(1.2), - R3ToR::cube_f32(1.0) + use sdf::{R3ToR, RToR, R3ToR3, Constant}; + 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 ); let my_sdf = sdf::Sdf::from_function(funciton); @@ -86,7 +95,7 @@ uniform float u_level_set; my_sdf.to_glsl(&mut fshader_source); fshader_source.push_str( " -#define ITERATIONS 20 +#define ITERATIONS 30 #define AA_X 1 #define AA_Y 1 @@ -136,7 +145,9 @@ void main() { float threshold = 0.02; if (min_dist < threshold) { float L = 0.3 + max(0., dot(normal(p), normalize(vec3(.8,1,.6)))); - final_color += L * (1.0/threshold) * (threshold-min_dist) * vec3(1.0, 0.0, 0.0); + float brightness = (1.0/threshold) * (threshold-min_dist); + brightness = pow(brightness, 8.0); + final_color += L * brightness * vec3(1.0, 0.0, 0.0); break; } @@ -235,15 +246,21 @@ 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 motion = Vec3::new(dx, dy, dz); if let Some(motion) = motion.try_normalize(0.001) { - let move_speed = 2.0; + let move_speed = 4.0 * speed_multiplier; let motion = motion * frame_dt * move_speed; let motion = view.rotation() * motion; view.pos += motion; } - let level_set_speed = 1.0; + let level_set_speed = 1.0 * speed_multiplier; view.level_set += dl * frame_dt * level_set_speed; } @@ -12,6 +12,7 @@ macro_rules! write_str { pub enum Constant { F32(f32), Time(f32, f32), + // @TODO: sin, sqrt, mod } impl From<f32> for Constant { @@ -32,6 +33,12 @@ impl Constant { pub struct Constant3(Constant, Constant, Constant); +impl From<(Constant, Constant, Constant)> for Constant3 { + fn from(x: (Constant, Constant, Constant)) -> Self { + Self(x.0, x.1, x.2) + } +} + impl Constant3 { fn to_glsl(&self) -> String { format!( @@ -45,23 +52,39 @@ impl Constant3 { pub enum R3ToR3 { Identity, + Compose(Box<R3ToR3>, Box<R3ToR3>), Translate(Constant3), + Sin(Constant), + //@TODO InfiniteMirrors(f32) } pub enum RToR { Identity, + Compose(Box<RToR>, Box<RToR>), Add(Constant), } pub enum R3ToR { Sphere(Constant), Cube(Constant), - PrePost(Box<R3ToR3>, Box<R3ToR>, Box<RToR>), + Compose(Box<R3ToR3>, Box<R3ToR>, Box<RToR>), Mix(Box<R3ToR>, Box<R3ToR>, Constant), SmoothMin(Box<R3ToR>, Box<R3ToR>), Min(Box<R3ToR>, Box<R3ToR>), } +impl R3ToR3 { + pub fn compose(self, b: Self) -> Self { + Self::Compose(Box::new(self), Box::new(b)) + } +} + +impl RToR { + pub fn compose(self, b: Self) -> Self { + Self::Compose(Box::new(self), Box::new(b)) + } +} + impl R3ToR { pub fn sphere_f32(r: f32) -> Self { Self::Sphere(r.into()) @@ -86,6 +109,10 @@ impl R3ToR { 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)) + } } #[derive(Clone, Copy)] @@ -136,17 +163,22 @@ impl Function for RToR { use RToR::*; match self { - Identity => return input, + Identity => input, Add(x) => { + let output = var.next(); write_str!( code, - "float {} = {input} + {};\n", - var.next(), + "float {output} = {input} + {};\n", x.to_glsl() ); + 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 + }, } - var.prev() } } @@ -155,18 +187,34 @@ impl Function for R3ToR3 { use R3ToR3::*; match self { - Identity => return input, + Identity => input, Translate(by) => { + let output = var.next(); write_str!( code, - "vec3 {} = {input} + {};\n", - var.next(), + "vec3 {output} = {input} + {};\n", by.to_glsl() ); + 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 + }, + Compose(a, b) => { + let a_output = a.to_glsl(input, code, var); + let b_output = b.to_glsl(a_output, code, var); + b_output } } - - var.prev() } } @@ -178,54 +226,63 @@ impl Function for R3ToR { // these SDFs. Sphere(r) => { let r = r.to_glsl(); - write_str!(code, "float {} = length({input}) - {r};\n", var.next()); + 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(); write_str!( code, - "float {} = length(max({q},0.0)) + min(max({q}.x,max({q}.y,{q}.z)),0.0);\n", - var.next() - ) + "float {output} = length(max({q},0.0)) + min(max({q}.x,max({q}.y,{q}.z)),0.0);\n" + ); + 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(); write_str!( code, - "float {} = mix({a_output}, {b_output}, clamp({t}, 0.0, 1.0));\n", - var.next() + "float {output} = mix({a_output}, {b_output}, clamp({t}, 0.0, 1.0));\n" ); + output } Min(a, b) => { 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 {} = min({a_output}, {b_output});\n", - var.next() + "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); + let output = var.next(); // for now we're using a fixed k value // i don't want to make this a Constant right now, // since most values of k (i.e. <0, >1) look bad/just like min. let k = 0.2; write_str!( code, - "float {} = sdf_smooth_min({a_output}, {b_output}, {k});\n", - var.next() + "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 }, - _ => todo!(), } - - var.prev() } } @@ -8,6 +8,7 @@ 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 { @@ -23,7 +24,7 @@ pub struct Window { audio_data: Option<Box<AudioData>>, } -#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum Key { A, B, @@ -80,6 +81,12 @@ pub enum Key { Space, Enter, Escape, + LShift, + RShift, + LCtrl, + RCtrl, + LAlt, + RAlt, F1, F2, F3, @@ -165,6 +172,12 @@ impl Key { KP_7 => Key::NumPad7, KP_8 => Key::NumPad8, KP_9 => Key::NumPad9, + LSHIFT => Key::LShift, + RSHIFT => Key::RShift, + LCTRL => Key::LCtrl, + RCTRL => Key::RCtrl, + LALT => Key::LAlt, + RALT => Key::RAlt, _ => return None, }) } @@ -239,6 +252,12 @@ impl Key { Key::NumPad7 => KP_7, Key::NumPad8 => KP_8, Key::NumPad9 => KP_9, + Key::LShift => LSHIFT, + Key::RShift => RSHIFT, + Key::LCtrl => LCTRL, + Key::RCtrl => RCTRL, + Key::LAlt => LALT, + Key::RAlt => RALT, } } } @@ -1059,6 +1078,18 @@ 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) + } pub fn swap(&mut self) { unsafe { sdl::gl_swap_window(self.sdlwin) }; |