diff options
author | eug-vs <eugene@eug-vs.xyz> | 2021-10-26 00:46:41 +0300 |
---|---|---|
committer | eug-vs <eugene@eug-vs.xyz> | 2021-10-26 00:46:41 +0300 |
commit | bd2150c70e5cbfc06cedfc6ec7e765d31c4ed506 (patch) | |
tree | 274e8e1e080d2caa34e244c90b80f214f7ee6bb0 | |
parent | 430ebecd2c3fe35393a3eb7861bdcff84525e9eb (diff) | |
download | pistol-bd2150c70e5cbfc06cedfc6ec7e765d31c4ed506.tar.gz |
feat: implement lighting
-rw-r--r-- | src/camera.rs | 36 | ||||
-rw-r--r-- | src/main.rs | 6 | ||||
-rw-r--r-- | src/vector.rs | 7 |
3 files changed, 39 insertions, 10 deletions
diff --git a/src/camera.rs b/src/camera.rs index 59283ab..a4fcb27 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -32,15 +32,21 @@ pub struct Camera { impl Camera { pub fn sdf(&self, point: Vector) -> f32 { + // Floor at z = -2 + let floor_dist = point.z + 1.0; + // Sphere let center = Vector { x: 3.0, y: 0.0, z: 0.0 }; let radius = 1.0; - let sphere_dist = (point - center).magnitude() - radius; - let floor_dist = point.z + 1.0; // Floor at z = -1 - sphere_dist.min(floor_dist) + // Small sphere + let center2 = Vector { x: 2.5, y: 0.5, z: 0.0 }; + let radius2 = 0.7; + let sphere2_dist = (point - center2).magnitude() - radius2; + + sphere_dist.max(-sphere2_dist).min(floor_dist) } pub fn screen(&self) -> (f32, f32) { @@ -77,7 +83,23 @@ impl Camera { } } + 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 dy = Vector { x: 0.0, y: d, z: 0.0 }; + let dfdy = (self.sdf(point + dy) - self.sdf(point - dy)) / (2.0 * 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 }.normalized() + } + pub fn shoot_ray(&self, direction: Vector) -> f32 { + let light = Vector { x: 1.0, y: 1.0, z: -1.0 }.normalized(); let threshold = 0.1; let ray = direction.normalized(); @@ -85,12 +107,14 @@ impl Camera { let mut dist = 0.0; let mut count = 0; - while dist < self.brightness && count < 25 { + while dist < self.brightness && count < 30 { count += 1; dist = self.sdf(point); if dist < threshold { - // println!("Dist: {}, point {}", dist, point); - return (point - self.position).magnitude() / self.brightness + // Collision in point! Let's calculate lights now: + let normal = self.normal(point); + let dot = -(normal * light); + return 1.0 - dot.max(0.01).min(0.98); } point = point + ray * dist; } diff --git a/src/main.rs b/src/main.rs index 7b63c04..5e25562 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,8 +20,6 @@ fn main() { buffer: Buffer([['.'; 100]; 50]) }; - for _i in 0..60 { - cam.render(); - println!("{}", cam.buffer); - } + cam.render(); + println!("{}", cam.buffer); } diff --git a/src/vector.rs b/src/vector.rs index d4e57cc..c4ddaab 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -58,6 +58,13 @@ impl ops::Div<f32> for Vector { } } +impl ops::Mul<Vector> for Vector { + type Output = f32; + fn mul(self, rhs: Vector) -> Self::Output { + self.x * rhs.x + self.y * rhs.y + self.z * rhs.z + } +} + impl Vector { pub fn magnitude_squared(self) -> f32 { self.x * self.x + self.y * self.y + self.z * self.z |