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

View File

@ -22,14 +22,17 @@ fn camera_render() {
2.0,
Point::new(0.0, 0.0, 0.0),
Vec3::new(0.0, 0.0, -1.0),
10
100,
50
);
// world
// world objects(spheres)
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.1, -100.0, -0.0), 100.0)));
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.0, 0.1, -1.0), 0.5)));
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.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);
write_image(

View File

@ -43,7 +43,8 @@ pub struct Camera {
pub viewport_top_left_pixel_center: Vec3,
// 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;
use rand::{thread_rng, Rng};
use crate::types_defined::Vec3;
impl Display for Vec3 {
@ -36,6 +37,33 @@ impl Vec3 {
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 {