9.Diffuse Materials
This commit is contained in:
parent
edd518b54e
commit
71ae83d205
|
@ -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();
|
||||
|
|
11
src/main.rs
11
src/main.rs
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
28
src/vec3.rs
28
src/vec3.rs
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue