chore: hit record

This commit is contained in:
dengqn 2025-08-09 01:19:01 +08:00
parent 89ad39b3e4
commit 11245af112
4 changed files with 44 additions and 33 deletions

View File

@ -4,7 +4,7 @@ use std::io::{BufWriter};
use crate::hittable::HittableList; use crate::hittable::HittableList;
use crate::math_utils::clamp; use crate::math_utils::clamp;
use crate::ppm_writer::PPMWriter; use crate::ppm_writer::PPMWriter;
use crate::types_defined::{Camera, Color, Point, Ray, Vec3}; use crate::types_defined::{Camera, Color, HitRecord, Point, Ray, Vec3};
use rand::rngs::ThreadRng; use rand::rngs::ThreadRng;
use rand::{Rng, thread_rng}; use rand::{Rng, thread_rng};
@ -89,11 +89,6 @@ impl<'a> Camera<'a> {
); );
self.ppm_file_writer.write(color.to_color()); self.ppm_file_writer.write(color.to_color());
// content
// img_content.push_str(&color_clamped.to_color_str().as_str());
// img_content.push('\n');
} }
} }
@ -108,11 +103,16 @@ impl<'a> Camera<'a> {
} }
// 限制出射光线的角度0.001经验值) // 限制出射光线的角度0.001经验值)
let hr = world.hit(&ray, 0.001, f32::MAX); let hit_record = &mut HitRecord{
if hr.t >= 0.0 { t: 0.0,
normal: Vec3::new(0.0, 0.0, 0.0),
front_face: false,
};
let hit = world.hit(&ray, 0.001, f32::MAX, hit_record);
if hit_record.t >= 0.0 {
// diffuse normal vec // diffuse normal vec
let diffuse_vec = Vec3::random_unit(); let diffuse_vec = Vec3::random_unit();
let lambertian_vec = diffuse_vec + hr.normal; let lambertian_vec = diffuse_vec + hit_record.normal;
// 每次反射按0.5计算颜色(反射率 // 每次反射按0.5计算颜色(反射率
return 0.5 * self.ray_color(&Ray::new(ray.point, lambertian_vec), depth - 1, world); return 0.5 * self.ray_color(&Ray::new(ray.point, lambertian_vec), depth - 1, world);
} }

View File

@ -1,7 +1,7 @@
use crate::types_defined::{HitRecord, Ray, Vec3}; use crate::types_defined::{HitRecord, Ray, Vec3};
pub trait Hittable { pub trait Hittable {
fn hit(&self, r: &Ray, t_min: f32, t_max: f32) -> HitRecord; fn hit(&self, r: &Ray, t_min: f32, t_max: f32, hit_record: &mut HitRecord) -> bool;
} }
@ -19,22 +19,33 @@ impl HittableList {
let _ = &self.objects.push(object); let _ = &self.objects.push(object);
} }
pub fn hit(&self, r: &Ray, t_min: f32, t_max: f32) -> HitRecord { pub fn hit(&self, r: &Ray, t_min: f32, t_max: f32, hit_record: &mut HitRecord) -> bool {
for object in &self.objects {
let temp = object.hit(r, t_min, t_max); let mut hits = false;
if temp.t >= 0.0 { let mut closest_so_far = t_max;
return temp
} let temp_hit_record = &mut HitRecord{
} t: 0.0,
HitRecord { normal: Vec3::new(0.0, 0.0, 0.0),
t: -1.0,
normal: Vec3 {
x: 0.0,
y: 0.0,
z: 0.0,
},
front_face: false, front_face: false,
};
for object in &self.objects {
let hit = object.hit(r, t_min, closest_so_far, temp_hit_record);
if hit {
hits = true;
closest_so_far = temp_hit_record.t;
hit_record.t = temp_hit_record.t;
hit_record.front_face = temp_hit_record.front_face;
hit_record.normal = temp_hit_record.normal;
if temp_hit_record.t >= 0.0 {
return true;
} }
} }
}
hits
}
} }

View File

@ -37,7 +37,7 @@ fn camera_render() {
width, width,
16.0 / 9.0, 16.0 / 9.0,
2.0, 2.0,
Point::new(0.0, 0.0, 0.0), Point::new(0.0, 0.0, 1.0),
Vec3::new(0.0, 0.0, -1.0), Vec3::new(0.0, 0.0, -1.0),
50, 50,
50, 50,

View File

@ -11,7 +11,7 @@ impl Sphere {
} }
impl hittable::Hittable for Sphere { impl hittable::Hittable for Sphere {
fn hit(&self, r: &Ray, t_min: f32, t_max: f32) -> HitRecord { fn hit(&self, r: &Ray, t_min: f32, t_max: f32, hit_record: &mut HitRecord) -> bool {
let a: f32 = r.direction.length_squared(); let a: f32 = r.direction.length_squared();
let h = r.direction.dot(self.center - r.point); let h = r.direction.dot(self.center - r.point);
// let b = -2.0 * r.direction.dot(sphere_center - r.point); // let b = -2.0 * r.direction.dot(sphere_center - r.point);
@ -28,19 +28,19 @@ impl hittable::Hittable for Sphere {
if root <= t_min || root >= t_max { if root <= t_min || root >= t_max {
root = far; root = far;
if root <= t_min || root >= t_max { if root <= t_min || root >= t_max {
root = -1.0; // hit_record.t = -1.0;
return false
} }
} }
let p = r.at(root); let p = r.at(root);
let normal = (p - self.center) / self.radius; let normal = (p - self.center) / self.radius;
HitRecord {
t: root, hit_record.t = root;
// p, hit_record.normal = normal;
normal, hit_record.front_face = r.direction.dot(normal) < 0.0;
// check if r.p inside(>=0) the sphere.
front_face: r.direction.dot(normal) < 0.0, true
}
} }
} }