diff options
author | Rosyid Haryadi <rosyid_haryadi@protonmail.com> | 2025-03-02 01:32:01 +0700 |
---|---|---|
committer | Rosyid Haryadi <rosyid_haryadi@protonmail.com> | 2025-03-02 01:32:01 +0700 |
commit | da70c57d01cf6ffe7c1aab30921eb22cd5197dae (patch) | |
tree | cff1c2e09f92445efbfff5dccb7c10522f5b6c33 | |
parent | 1207c2c55c772155d02a148d76616881f3f6c125 (diff) |
upd: diffuse material
-rw-r--r-- | src/calculus.rs | 37 | ||||
-rw-r--r-- | src/camera.rs | 25 | ||||
-rw-r--r-- | src/global.rs | 2 |
3 files changed, 53 insertions, 11 deletions
diff --git a/src/calculus.rs b/src/calculus.rs index a39c8a5..8865154 100644 --- a/src/calculus.rs +++ b/src/calculus.rs @@ -16,6 +16,43 @@ pub mod calculus { Self { x, y, z } } + fn random() -> Self { + let mut rng = rand::rng(); + Self::new( + rng.random(), + rng.random(), + rng.random(), + ) + } + + fn random_range(min: f32, max: f32) -> Self { + let mut rng = rand::rng(); + Self::new( + rng.random_range(min..max), + rng.random_range(min..max), + rng.random_range(min..max), + ) + } + + fn random_unit() -> Vec3 { + loop { + let p = Self::random_range(-1.0, 1.0); + let lensq = p.mag_sqr(); + if f32::EPSILON < lensq && lensq <= 1.0 { + return p.scalar_mul(1.0 / lensq.sqrt()) + } + } + } + + pub fn random_on_hemisphere(normal: &Vec3) -> Vec3 { + let on_unit_sphere = Self::random_unit(); + if on_unit_sphere.dot_prod(normal) > 0.0 { + on_unit_sphere + } else { + on_unit_sphere.scalar_mul(-1.0) + } + } + pub fn add(&self, other: &Self) -> Self { Self { x: self.x + other.x, diff --git a/src/camera.rs b/src/camera.rs index 8e9cf68..ec37c70 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -13,6 +13,7 @@ pub struct Camera { delta_pixel_u: Vec3, delta_pixel_v: Vec3, pixel_samples_scale: f32, + max_depth: usize, } impl Camera { @@ -45,6 +46,8 @@ impl Camera { &delta_pixel_u.add(&delta_pixel_u).scalar_mul(0.5) ); + let max_depth = 50; + Self { aspect_ratio, image_width, @@ -55,6 +58,7 @@ impl Camera { delta_pixel_v, samples_per_pixel, pixel_samples_scale, + max_depth } } @@ -73,18 +77,18 @@ impl Camera { } } - fn ray_color(&self, ray: &Ray, world: &HittableList) -> Color { + fn ray_color(&self, ray: &Ray, world: &HittableList, depth: usize) -> Color { + if depth <= 0 { + return Color::new(0.0, 0.0, 0.0); + } + let mut rec = HitRecord::default(); let ray_t = Interval::new(0.0, f32::INFINITY); if world.hit(ray, ray_t, &mut rec) { - let color = Color::new(1.0, 1.0, 1.0) - .add(&Color::new( - rec.normal.x, - rec.normal.y, - rec.normal.z) - ) - .mul_scalar(0.5); - return color; + let direction = Vec3::random_on_hemisphere(&rec.normal); + let origin = rec.position.clone(); + let r = Ray { origin, direction }; + return self.ray_color(&r, world, depth - 1).mul_scalar(0.5); } let unit_direction = ray.direction.unit(); @@ -97,10 +101,11 @@ impl Camera { pub fn render(&self, display_buffer: &mut DisplayBuffer, world: &HittableList) { (0..self.image_height).for_each(|j| { (0..self.image_width).for_each(|i| { + println!("Processing line {} col {}", j, i); let mut pixel_color = Color::new(0.0, 0.0, 0.0); (0..self.samples_per_pixel).for_each(|_| { let r = self.get_ray(i, j); - let ray_color = self.ray_color(&r, world); + let ray_color = self.ray_color(&r, world, self.max_depth); pixel_color = pixel_color.add(&ray_color); }); pixel_color = pixel_color.mul_scalar(self.pixel_samples_scale); diff --git a/src/global.rs b/src/global.rs index 3f74ba1..3975609 100644 --- a/src/global.rs +++ b/src/global.rs @@ -3,7 +3,7 @@ use crate::interval::Interval; // "Ideal" aspect ratio, allowing fraction pub const ASPECT_RATIO: f32 = 16.0f32 / 9.0f32; -pub const IMG_WIDTH: usize = 1000; +pub const IMG_WIDTH: usize = 400; pub const IMG_HEIGHT: usize = get_image_height(IMG_WIDTH, ASPECT_RATIO); pub const VIEWPORT_HEIGHT: f32 = 2.0; |