diff --git a/src/camera.rs b/src/camera.rs index 904d12c..38b3426 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -12,6 +12,7 @@ impl Camera { camera_center: Point, focal_length: Vec3, sample_times: i8, + reflect_depth: i8 ) -> Self { let image_height = ((image_width as f32 / aspect_ratio) as i32).max(1); let viewport_width = viewport_height * (image_width as f32 / image_height as f32); @@ -45,7 +46,8 @@ impl Camera { viewport_u_delta, viewport_v_delta, viewport_top_left_pixel_center, - sample_times: sample_times, + sample_times, + reflect_depth, } } @@ -67,7 +69,7 @@ impl Camera { + (i as f32 + bias.x) * self.viewport_u_delta + (j as f32 + bias.y) * self.viewport_v_delta; let r = Ray::new(self.camera_center, pix_sample - self.camera_center); - let sample_color = self.ray_color(&r, world); + let sample_color = self.ray_color(&r, self.reflect_depth, world); color = color + sample_color; } // color * each sample color @@ -89,15 +91,21 @@ impl Camera { img_content } - fn ray_color(&self, ray: &Ray, world: &HittableList) -> Vec3 { - let hr = world.hit(&ray, 0.0, f32::MAX); + fn ray_color(&self, ray: &Ray, depth: i8, world: &HittableList) -> Vec3 { + + // 反射次数 + if depth <= 0 { + return Vec3::new(0.0, 0.0, 0.0); + } + + // 限制出射光线的角度(0.001经验值) + let hr = world.hit(&ray, 0.01, f32::MAX); if hr.t >= 0.0 { - let normal_color = 0.5 * (hr.normal + Point::new(1.0, 1.0, 1.0)); - return if hr.front_face { - normal_color - } else { - Color::new(1.0, 1.0, 1.0) - normal_color - }; + // diffuse normal vec + let diffuse_vec = Vec3::random_unit(); + let lambertian_vec = diffuse_vec + hr.normal; + // 每次反射按0.5计算颜色(反射率 ) + return 0.5 * self.ray_color(&Ray::new(ray.point, lambertian_vec), depth - 1, world); } // v / |v| let unit_direction = ray.direction / ray.direction.length(); diff --git a/src/main.rs b/src/main.rs index 9451879..88871a3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,14 +22,17 @@ fn camera_render() { 2.0, Point::new(0.0, 0.0, 0.0), Vec3::new(0.0, 0.0, -1.0), - 10 + 100, + 50 ); // world // world objects(spheres) let mut world = HittableList::new(); - world.put(Box::new(Sphere::new(Point::new(0.0, 0.0, -1.0), 0.5))); - world.put(Box::new(Sphere::new(Point::new(0.1, -100.0, -0.0), 100.0))); - world.put(Box::new(Sphere::new(Point::new(-0.5, 0.2, -0.5), 0.2))); + world.put(Box::new(Sphere::new(Point::new(0.0, 0.1, -1.0), 0.5))); + world.put(Box::new(Sphere::new(Point::new(0.3, 0.1, -1.0), 0.1))); + world.put(Box::new(Sphere::new(Point::new(-0.5, 0.0, -1.0), 0.3))); + world.put(Box::new(Sphere::new(Point::new(0.0, -100.0, -1.0), 100.0))); + world.put(Box::new(Sphere::new(Point::new(-0.5, 0.2, -0.5), 0.4))); let ppm_content = camera.render(&world); write_image( diff --git a/src/types_defined.rs b/src/types_defined.rs index 4b5a4c6..01b784c 100644 --- a/src/types_defined.rs +++ b/src/types_defined.rs @@ -43,7 +43,8 @@ pub struct Camera { pub viewport_top_left_pixel_center: Vec3, // sample times - pub sample_times: i8 + pub sample_times: i8, + pub reflect_depth: i8 } /* diff --git a/src/vec3.rs b/src/vec3.rs index cc277df..6464960 100644 --- a/src/vec3.rs +++ b/src/vec3.rs @@ -1,6 +1,7 @@ use std::{fmt::Display, ops::{Add, AddAssign, Div, Mul, MulAssign, Sub}}; use std::fmt; +use rand::{thread_rng, Rng}; use crate::types_defined::Vec3; impl Display for Vec3 { @@ -36,6 +37,33 @@ impl Vec3 { return self.length_squared().sqrt(); } + pub fn random_range(min: f32, max: f32) -> Self { + let rng = &mut thread_rng(); + Vec3::new(rng.gen_range(min..max), rng.gen_range(min..max), rng.gen_range(min..max)) + } + + pub fn random() -> Self { + let rng = &mut thread_rng(); + Vec3::new(rng.r#gen(), rng.r#gen(), rng.r#gen()) + } + + pub fn random_unit() -> Self { + loop { + let v = Vec3::random(); + if f32::MIN < v.length_squared() && v.length_squared() <= 1.0 { + return v / v.length_squared(); + } + } + } + + pub fn random_unit_on_hemisphere(point_normal: Vec3) -> Self { + let on_unit_sphere = Vec3::random_unit(); + if on_unit_sphere.dot(point_normal) > 0.0 { + on_unit_sphere + } else { + Vec3::new(0.0, 0.0, 0.0) - on_unit_sphere + } + } } impl Add for Vec3 {