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
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)
}
}
}

View File

@ -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;
// }
}
}

View File

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

View File

@ -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();

View File

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

View File

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