diff options
author | eug-vs <eugene@eug-vs.xyz> | 2021-10-28 01:53:59 +0300 |
---|---|---|
committer | eug-vs <eugene@eug-vs.xyz> | 2021-10-28 01:53:59 +0300 |
commit | 5ffd25826d8ea286e9176ada64dba3fba65bb55b (patch) | |
tree | af17ccfb82690ecd9a4a46bedc207e6b87086578 | |
parent | 7e4d84eb99ed3f9e3681c3cdda0c5de3b91ef90a (diff) | |
download | pistol-5ffd25826d8ea286e9176ada64dba3fba65bb55b.tar.gz |
refactor: separate ligthing functions
-rw-r--r-- | src/camera.rs | 86 |
1 files changed, 52 insertions, 34 deletions
diff --git a/src/camera.rs b/src/camera.rs index 31a0c5e..c132e44 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -5,7 +5,7 @@ use std::fmt; type Vector = Vector3<f32>; -pub const HEIGHT: i32 = 40; +pub const HEIGHT: i32 = 30; pub const WIDTH: i32 = HEIGHT * 3; #[derive(Debug)] @@ -96,7 +96,7 @@ impl Camera { } pub fn render(& mut self) { - let palette = "$@B%8&WM#oahkbdpqwmZO0QLCJUYXzcvunxrjft/\\|()1{}[]?-_+~<>i!lI;:,\"^`'. "; + let palette = "$@B%8&WM#oahkbdpqwmZO0QLCJUYXzcvunxrjft/\\|()1{}[]?-_+~<>i!lI;:,\"^`'. ".to_string(); let (screen_width, screen_height) = self.screen(); let cross = self.up.cross(self.direction); @@ -117,62 +117,80 @@ impl Camera { // Apply transform to unit square centered at (1, 0, 0) let ray_dir = operator * Vector { x: 1.0, y: 0.5 - jx, z: 0.5 - ix }; - let brightness = self.shoot_ray(ray_dir); - self.buffer.0[i][j] = palette.chars().nth((brightness * palette.len() as f32) as usize - 1).unwrap(); + let collision = self.ray_marching(self.position, ray_dir); + + let brightness = match collision { + Some(point) => self.light_point(point), + None => 0.0 + }; + + self.buffer.0[i][j] = palette + .chars() + .nth(((1.0 - brightness) * (palette.len() - 1) as f32) as usize) + .unwrap(); } } } pub fn normal(&self, point: Vector) -> Vector { - let d = 0.01; - - let dx = Vector { x: d, y: 0.0, z: 0.0 }; - let dfdx = (self.sdf(point + dx) - self.sdf(point - dx)) / (2.0 * d); + let d = 0.001; - let dy = Vector { x: 0.0, y: d, z: 0.0 }; - let dfdy = (self.sdf(point + dy) - self.sdf(point - dy)) / (2.0 * d); + let dx = Vector::unit_x() * d; + let dy = Vector::unit_y() * d; + let dz = Vector::unit_z() * d; - let dz = Vector { x: 0.0, y: 0.0, z: d }; - let dfdz = (self.sdf(point + dz) - self.sdf(point - dz)) / (2.0 * d); - - Vector { x: dfdx, y: dfdy, z: dfdz }.normalize() + return (Vector { + x: (self.sdf(point + dx) - self.sdf(point - dx)), + y: (self.sdf(point + dy) - self.sdf(point - dy)), + z: (self.sdf(point + dz) - self.sdf(point - dz)), + } / (2.0 * d)).normalize() } - pub fn shoot_ray(&self, direction: Vector) -> f32 { + pub fn ray_marching(&self, origin: Vector, direction: Vector) -> Option<Vector> { let threshold = 0.1; let ray = direction.normalize(); - let mut point = self.position; + let mut point = origin; let mut dist = 0.0; let mut count = 0; - while dist < self.brightness && count < 50 { + while dist < 10.0 && count < 30 { count += 1; dist = self.sdf(point); if dist < threshold { - // Collision in point! Let's calculate lights now: - let mut res: f32 = 1.0; - let mut t = 0.001; - let k = 2.0; + return Some(point); + } + point += ray * dist; + } - while t < 7.0 { - let h = self.sdf(point - self.light * t); - if h < 0.001 { - return 0.97 - } - res = res.min(k * h / t); - t += h; + return None + } - } + pub fn light_point(&self, point: Vector) -> f32 { + let base_light = 0.1; + return base_light + (1.0 - base_light) * (self.apply_shadow(point) * 0.7 + self.apply_ambient(point) * 0.3) + } - let normal = self.normal(point); - let dot = -(normal.dot(self.light)); + pub fn apply_shadow(&self, point: Vector) -> f32 { + let mut res: f32 = 1.0; + let mut t = 0.001; + let k = 4.0; - return 1.0 - 0.5 * dot.max(0.01).min(0.98) - 0.5 * res.min(0.98) + while t < 7.0 { + let h = self.sdf(point - self.light * t); + if h < 0.001 { + return 0.00 } - point = point + ray * dist; + res = res.min(k * h / t); + t += h; } - return 1.0 + return res + } + + pub fn apply_ambient(&self, point: Vector) -> f32 { + let normal = self.normal(point); + let dot = -(normal.dot(self.light)); + return dot.min(1.0).max(0.0) } } |