9.Diffuse Materials

This commit is contained in:
dengqn 2025-08-05 01:47:04 +08:00
parent edd518b54e
commit 71ae83d205
4 changed files with 55 additions and 15 deletions

View File

@ -12,6 +12,7 @@ impl Camera {
camera_center: Point, camera_center: Point,
focal_length: Vec3, focal_length: Vec3,
sample_times: i8, sample_times: i8,
reflect_depth: i8
) -> Self { ) -> Self {
let image_height = ((image_width as f32 / aspect_ratio) as i32).max(1); 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); let viewport_width = viewport_height * (image_width as f32 / image_height as f32);
@ -45,7 +46,8 @@ impl Camera {
viewport_u_delta, viewport_u_delta,
viewport_v_delta, viewport_v_delta,
viewport_top_left_pixel_center, 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 + (i as f32 + bias.x) * self.viewport_u_delta
+ (j as f32 + bias.y) * self.viewport_v_delta; + (j as f32 + bias.y) * self.viewport_v_delta;
let r = Ray::new(self.camera_center, pix_sample - self.camera_center); 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 = color + sample_color;
} }
// color * each sample color // color * each sample color
@ -89,15 +91,21 @@ impl Camera {
img_content img_content
} }
fn ray_color(&self, ray: &Ray, world: &HittableList) -> Vec3 { fn ray_color(&self, ray: &Ray, depth: i8, world: &HittableList) -> Vec3 {
let hr = world.hit(&ray, 0.0, f32::MAX);
// 反射次数
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 { if hr.t >= 0.0 {
let normal_color = 0.5 * (hr.normal + Point::new(1.0, 1.0, 1.0)); // diffuse normal vec
return if hr.front_face { let diffuse_vec = Vec3::random_unit();
normal_color let lambertian_vec = diffuse_vec + hr.normal;
} else { // 每次反射按0.5计算颜色(反射率
Color::new(1.0, 1.0, 1.0) - normal_color return 0.5 * self.ray_color(&Ray::new(ray.point, lambertian_vec), depth - 1, world);
};
} }
// v / |v| // v / |v|
let unit_direction = ray.direction / ray.direction.length(); let unit_direction = ray.direction / ray.direction.length();

View File

@ -22,14 +22,17 @@ fn camera_render() {
2.0, 2.0,
Point::new(0.0, 0.0, 0.0), Point::new(0.0, 0.0, 0.0),
Vec3::new(0.0, 0.0, -1.0), Vec3::new(0.0, 0.0, -1.0),
10 100,
50
); );
// world // world
// world objects(spheres) // world objects(spheres)
let mut world = HittableList::new(); 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.0, 0.1, -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.3, 0.1, -1.0), 0.1)));
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.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); let ppm_content = camera.render(&world);
write_image( write_image(

View File

@ -43,7 +43,8 @@ pub struct Camera {
pub viewport_top_left_pixel_center: Vec3, pub viewport_top_left_pixel_center: Vec3,
// sample times // sample times
pub sample_times: i8 pub sample_times: i8,
pub reflect_depth: i8
} }
/* /*

View File

@ -1,6 +1,7 @@
use std::{fmt::Display, ops::{Add, AddAssign, Div, Mul, MulAssign, Sub}}; use std::{fmt::Display, ops::{Add, AddAssign, Div, Mul, MulAssign, Sub}};
use std::fmt; use std::fmt;
use rand::{thread_rng, Rng};
use crate::types_defined::Vec3; use crate::types_defined::Vec3;
impl Display for Vec3 { impl Display for Vec3 {
@ -36,6 +37,33 @@ impl Vec3 {
return self.length_squared().sqrt(); 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 { impl Add for Vec3 {