From 2018b02e02cdfb04672e2072a380271e49930349 Mon Sep 17 00:00:00 2001 From: dengqn Date: Tue, 12 Aug 2025 16:58:30 +0800 Subject: [PATCH] bug fix --- .idea/.gitignore | 8 +++++ src/camera.rs | 76 +++++++++++++++++++++++++---------------------- src/hittable.rs | 9 +++--- src/main.rs | 28 +++++++++-------- src/material.rs | 9 +++--- src/math_utils.rs | 2 +- src/sphere.rs | 2 +- 7 files changed, 76 insertions(+), 58 deletions(-) create mode 100644 .idea/.gitignore diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/src/camera.rs b/src/camera.rs index a0ce7b9..59ab37a 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -34,7 +34,7 @@ impl<'a> Camera<'a> { // height per pix let viewport_v_delta = viewport_v / (image_height as f32); let viewport_top_left_pixel = - camera_center + focal_length - viewport_u / 2.0 - viewport_v / 2.0; + camera_center - focal_length - viewport_u / 2.0 - viewport_v / 2.0; // padding 0.5* delta u/v let viewport_top_left_pixel_center = viewport_top_left_pixel - viewport_u_delta / 2.0 - viewport_v_delta / 2.0; @@ -89,7 +89,7 @@ impl<'a> Camera<'a> { clamp(color.z, 0.0, 1.0), ); - self.ppm_file_writer.write(color.to_color()); + self.ppm_file_writer.write(color_clamped.to_color()); } } @@ -113,8 +113,6 @@ impl<'a> Camera<'a> { }; let hit = world.hit(&ray, 0.001, f32::MAX, hit_record); if hit { - let scatted = &mut Ray::new(Point::new(0.0, 0.0, 0.0), Vec3::random()); - let attenuation = &mut Color::new(1.0, 1.0, 1.0); let hit_m = &hit_record.material; let hc = &mut HitRecord{ t: hit_record.t, @@ -126,42 +124,22 @@ impl<'a> Camera<'a> { let hit_c = match hit_m { Some(mk) => { let mc = match mk { - MaterialKind::Lambertian(l) => { - if l.scatter(ray, hc, attenuation, scatted) { - let r_c = self.ray_color(scatted, depth - 1, world); - let sc_color = Vec3::new(attenuation.x * r_c.x, attenuation.y * r_c.y, attenuation.z * r_c.z); - // *attenuation * ; - Color::new(sc_color.x, sc_color.y, sc_color.z) - } else { - Color::new(0.0, 0.0, 0.0) - } - }, - MaterialKind::Metal(m) => { - if m.scatter(ray, hc, attenuation, scatted) { - let r_c = self.ray_color(scatted, depth - 1, world); - let sc_color = Vec3::new(attenuation.x * r_c.x, attenuation.y * r_c.y, attenuation.z * r_c.z); - // *attenuation * ; - - Color::new(sc_color.x, sc_color.y, sc_color.z) - } else { - Color::new(0.0, 0.0, 0.0) - } - } + // MaterialKind::Lambertian(l) => l.albedo, + MaterialKind::Lambertian(l) => self.scatter_color(ray, hc, l, depth, world), + MaterialKind::Metal(m) => self.scatter_color(ray, hc, m, depth, world), }; - return mc + mc }, None => { - // if hit_record.t >= 0.0 { - // // diffuse normal vec - // let diffuse_vec = Vec3::random_unit(); - // let lambertian_vec = diffuse_vec + hit_record.normal; - // // 每次反射按0.5计算颜色(反射率 ) - // return 0.5 * self.ray_color(&Ray::new(ray.point, lambertian_vec), depth - 1, world); - // } - Color::new(0.0, 0.0, 0.0) + if hit_record.t >= 0.0 { + let diffuse_vec = Vec3::random_unit(); + let lambertian_vec = diffuse_vec + hit_record.normal; + 0.5 * self.ray_color(&Ray::new(ray.point, lambertian_vec), depth - 1, world) + } else { + Color::new(0.0, 0.0, 0.0) + } } }; - return hit_c; } @@ -176,4 +154,32 @@ impl<'a> Camera<'a> { fn random_square(&self, rng: &mut ThreadRng) -> Vec3 { Vec3::new(rng.gen_range(-0.5..0.1), rng.gen_range(-0.5..0.1), 0.0) } + + + fn scatter_color( + &self, + ray: &Ray, + hc: &mut HitRecord, + material: &impl Material, + depth: i8, + world: &HittableList, + ) -> Color { + let mut scatted = Ray::new(Point::new(0.0, 0.0, 0.0), Vec3::random()); + let mut attenuation = Color::new(1.0, 1.0, 1.0); + if material.scatter(ray, hc, &mut attenuation, &mut scatted) { + let r_c = self.ray_color(&scatted, depth - 1, world); + let sc_color = Vec3::new( + attenuation.x * r_c.x, + attenuation.y * r_c.y, + attenuation.z * r_c.z, + ); + Color::new(sc_color.x, sc_color.y, sc_color.z) + } else { + Color::new(0.0, 0.0, 0.0) + } + } + } + + + diff --git a/src/hittable.rs b/src/hittable.rs index 013920b..3a75c3d 100644 --- a/src/hittable.rs +++ b/src/hittable.rs @@ -32,7 +32,7 @@ impl HittableList { for object in &self.objects { let hit = object.hit(r, t_min, closest_so_far, temp_hit_record); - if hit { + if hit && temp_hit_record.t < closest_so_far { hits = true; closest_so_far = temp_hit_record.t; hit_record.t = temp_hit_record.t; @@ -47,9 +47,10 @@ impl HittableList { } else { None }; - if temp_hit_record.t >= 0.0 { - return true; - } + + // if temp_hit_record.t >= 0.0 { + // return true; + // } } } diff --git a/src/main.rs b/src/main.rs index 878b230..cfc1d51 100644 --- a/src/main.rs +++ b/src/main.rs @@ -23,8 +23,8 @@ fn main() { fn camera_render() { - let width: i32 = 1920; - let height: i32 = 1080; + let width: i32 = 800/2; + let height: i32 = 600/2; let pw_r = PPMWriter::new( BufWriter::new(File::create("./target/ray_sphere_normal_scene_render.ppm").unwrap()), width, height); @@ -37,28 +37,30 @@ fn camera_render() { let mut camera: Camera = Camera::new( width, - 16.0 / 9.0, + 4.0 / 3.0, 2.0, - Point::new(0.0, -0.5, 0.0), - Vec3::new(0.0, 0.0, -0.5), - 100, - 50, + Point::new(0.0, -0.0, 0.0), + Vec3::new(0.0, 0.0, 1.0), + 127, + 127, pw ); // world // world objects(spheres) let mut world = HittableList::new(); - let plane_m = Some(MaterialKind::Lambertian(Lambertian{albedo: Color::new(0.3, 0.2, 0.5)})); - // let plane2_m = Some(MaterialKind::Metal(Metal{albedo: Color::new(0.999, 0.999, 0.999)})); - let center_m = Some(MaterialKind::Lambertian(Lambertian{albedo: Color::new(0.1, 0.2, 0.5)})); + let plane_m = Some(MaterialKind::Lambertian(Lambertian{albedo: Color::new(0.899, 0.899, 0.999)})); + let plane2_m = Some(MaterialKind::Metal(Metal{albedo: Color::new(0.784,0.784,0.784)})); + let center_m = Some(MaterialKind::Lambertian(Lambertian{albedo: Color::new(0.5, 0.5, 0.5)})); let left_m = Some(MaterialKind::Metal(Metal{albedo: Color::new(0.799, 0.599, 0.799)})); + let left_behind_m = Some(MaterialKind::Lambertian(Lambertian{albedo: Color::new(0.799, 0.599, 0.599)})); let right_m = Some(MaterialKind::Metal(Metal{albedo: Color::new(0.8, 0.6, 0.2)})); - world.put(Box::new(Sphere::new(Point::new(0.0, -100.5, -1.2), 100.0, plane_m))); - world.put(Box::new(Sphere::new(Point::new(0.0, 0.0, -1.2), 0.5, center_m))); - world.put(Box::new(Sphere::new(Point::new(-2.0, 0.0, -1.0), 1.0, left_m))); + world.put(Box::new(Sphere::new(Point::new(0.0, 0.0, -1.0), 0.5, center_m))); + world.put(Box::new(Sphere::new(Point::new(-1.0, 0.0, -1.0), 0.5, left_m))); + world.put(Box::new(Sphere::new(Point::new(-2.5, 1.5, -3.5), 1.5, left_behind_m))); world.put(Box::new(Sphere::new(Point::new(1.0, 0.0, -1.0), 0.5, right_m))); + world.put(Box::new(Sphere::new(Point::new(0.0, -25.5, -1.0), 25.0, plane_m))); camera.render(&world); // write_image( diff --git a/src/material.rs b/src/material.rs index 5f3ffb0..d741b5d 100644 --- a/src/material.rs +++ b/src/material.rs @@ -28,12 +28,13 @@ impl Clone for Lambertian { impl Material for Lambertian { fn scatter(&self, r_in: &Ray, hit_record: &mut HitRecord, attenuation: &mut Color, scattered: &mut Ray) -> bool { - let scatter_direction = hit_record.normal + Vec3::random_unit(); + let scatter_direction = r_in.direction + Vec3::random_unit_on_hemisphere(hit_record.normal); + // hit_record.normal + Vec3::random_unit(); // let scatter_direction = reflect(r_in.direction, hit_record.normal); - if near_zero(scatter_direction) { - scattered.direction = hit_record.normal; - } + // if near_zero(scatter_direction) { + // scattered.direction = r_in.direction; + // } *scattered = Ray::new(hit_record.p, scatter_direction); *attenuation = self.albedo.clone(); diff --git a/src/math_utils.rs b/src/math_utils.rs index f93f297..1fd024f 100644 --- a/src/math_utils.rs +++ b/src/math_utils.rs @@ -11,7 +11,7 @@ pub fn clamp(value: f32, low: f32, high: f32) -> f32 { } pub fn near_zero(v: Vec3) -> bool { - const EPSILON: f32 = 1e-8; + const EPSILON: f32 = 1e-4; v.x.abs() < EPSILON && v.y.abs() < EPSILON && v.z.abs() < EPSILON } diff --git a/src/sphere.rs b/src/sphere.rs index 80ef1b1..76741a5 100644 --- a/src/sphere.rs +++ b/src/sphere.rs @@ -34,7 +34,7 @@ impl hittable::Hittable for Sphere { if root <= t_min || root >= t_max { root = far; if root <= t_min || root >= t_max { - // hit_record.t = -1.0; + hit_record.t = -1.0; return false } }