aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoreug-vs <eugene@eug-vs.xyz>2021-10-26 00:46:41 +0300
committereug-vs <eugene@eug-vs.xyz>2021-10-26 00:46:41 +0300
commitbd2150c70e5cbfc06cedfc6ec7e765d31c4ed506 (patch)
tree274e8e1e080d2caa34e244c90b80f214f7ee6bb0
parent430ebecd2c3fe35393a3eb7861bdcff84525e9eb (diff)
downloadpistol-bd2150c70e5cbfc06cedfc6ec7e765d31c4ed506.tar.gz
feat: implement lighting
-rw-r--r--src/camera.rs36
-rw-r--r--src/main.rs6
-rw-r--r--src/vector.rs7
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