This commit is contained in:
dengqn 2025-08-12 16:58:30 +08:00
parent cbd072af4a
commit 2018b02e02
7 changed files with 76 additions and 58 deletions

8
.idea/.gitignore vendored Normal file
View File

@ -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

View File

@ -34,7 +34,7 @@ impl<'a> Camera<'a> {
// height per pix // height per pix
let viewport_v_delta = viewport_v / (image_height as f32); let viewport_v_delta = viewport_v / (image_height as f32);
let viewport_top_left_pixel = 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 // padding 0.5* delta u/v
let viewport_top_left_pixel_center = let viewport_top_left_pixel_center =
viewport_top_left_pixel - viewport_u_delta / 2.0 - viewport_v_delta / 2.0; 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), 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); let hit = world.hit(&ray, 0.001, f32::MAX, hit_record);
if hit { 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 hit_m = &hit_record.material;
let hc = &mut HitRecord{ let hc = &mut HitRecord{
t: hit_record.t, t: hit_record.t,
@ -126,42 +124,22 @@ impl<'a> Camera<'a> {
let hit_c = match hit_m { let hit_c = match hit_m {
Some(mk) => { Some(mk) => {
let mc = match mk { let mc = match mk {
MaterialKind::Lambertian(l) => { // MaterialKind::Lambertian(l) => l.albedo,
if l.scatter(ray, hc, attenuation, scatted) { MaterialKind::Lambertian(l) => self.scatter_color(ray, hc, l, depth, world),
let r_c = self.ray_color(scatted, depth - 1, world); MaterialKind::Metal(m) => self.scatter_color(ray, hc, m, depth, 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)
}
}
}; };
return mc mc
}, },
None => { None => {
// if hit_record.t >= 0.0 { if hit_record.t >= 0.0 {
// // diffuse normal vec let diffuse_vec = Vec3::random_unit();
// let diffuse_vec = Vec3::random_unit(); let lambertian_vec = diffuse_vec + hit_record.normal;
// let lambertian_vec = diffuse_vec + hit_record.normal; 0.5 * self.ray_color(&Ray::new(ray.point, lambertian_vec), depth - 1, world)
// // 每次反射按0.5计算颜色(反射率 } else {
// return 0.5 * self.ray_color(&Ray::new(ray.point, lambertian_vec), depth - 1, world);
// }
Color::new(0.0, 0.0, 0.0) Color::new(0.0, 0.0, 0.0)
} }
}
}; };
return hit_c; return hit_c;
} }
@ -176,4 +154,32 @@ impl<'a> Camera<'a> {
fn random_square(&self, rng: &mut ThreadRng) -> Vec3 { 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) 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)
}
}
} }

View File

@ -32,7 +32,7 @@ impl HittableList {
for object in &self.objects { for object in &self.objects {
let hit = object.hit(r, t_min, closest_so_far, temp_hit_record); 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; hits = true;
closest_so_far = temp_hit_record.t; closest_so_far = temp_hit_record.t;
hit_record.t = temp_hit_record.t; hit_record.t = temp_hit_record.t;
@ -47,9 +47,10 @@ impl HittableList {
} else { } else {
None None
}; };
if temp_hit_record.t >= 0.0 {
return true; // if temp_hit_record.t >= 0.0 {
} // return true;
// }
} }
} }

View File

@ -23,8 +23,8 @@ fn main() {
fn camera_render() { fn camera_render() {
let width: i32 = 1920; let width: i32 = 800/2;
let height: i32 = 1080; let height: i32 = 600/2;
let pw_r = PPMWriter::new( let pw_r = PPMWriter::new(
BufWriter::new(File::create("./target/ray_sphere_normal_scene_render.ppm").unwrap()), BufWriter::new(File::create("./target/ray_sphere_normal_scene_render.ppm").unwrap()),
width, height); width, height);
@ -37,28 +37,30 @@ fn camera_render() {
let mut camera: Camera = Camera::new( let mut camera: Camera = Camera::new(
width, width,
16.0 / 9.0, 4.0 / 3.0,
2.0, 2.0,
Point::new(0.0, -0.5, 0.0), Point::new(0.0, -0.0, 0.0),
Vec3::new(0.0, 0.0, -0.5), Vec3::new(0.0, 0.0, 1.0),
100, 127,
50, 127,
pw pw
); );
// world // world
// world objects(spheres) // world objects(spheres)
let mut world = HittableList::new(); let mut world = HittableList::new();
let plane_m = Some(MaterialKind::Lambertian(Lambertian{albedo: Color::new(0.3, 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.999, 0.999, 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.1, 0.2, 0.5)})); 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_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)})); 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.0), 0.5, center_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(-1.0, 0.0, -1.0), 0.5, left_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(-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(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); camera.render(&world);
// write_image( // write_image(

View File

@ -28,12 +28,13 @@ impl Clone for Lambertian {
impl Material for Lambertian { impl Material for Lambertian {
fn scatter(&self, r_in: &Ray, hit_record: &mut HitRecord, attenuation: &mut Color, scattered: &mut Ray) -> bool { 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); // let scatter_direction = reflect(r_in.direction, hit_record.normal);
if near_zero(scatter_direction) { // if near_zero(scatter_direction) {
scattered.direction = hit_record.normal; // scattered.direction = r_in.direction;
} // }
*scattered = Ray::new(hit_record.p, scatter_direction); *scattered = Ray::new(hit_record.p, scatter_direction);
*attenuation = self.albedo.clone(); *attenuation = self.albedo.clone();

View File

@ -11,7 +11,7 @@ pub fn clamp(value: f32, low: f32, high: f32) -> f32 {
} }
pub fn near_zero(v: Vec3) -> bool { 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 v.x.abs() < EPSILON && v.y.abs() < EPSILON && v.z.abs() < EPSILON
} }

View File

@ -34,7 +34,7 @@ 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 {
// hit_record.t = -1.0; hit_record.t = -1.0;
return false return false
} }
} }