ft: 9: diffuse materials
This commit is contained in:
@@ -12,6 +12,7 @@ pub struct Camera {
|
||||
image_width: u32,
|
||||
image_height: u32,
|
||||
anti_alias_rate: u32,
|
||||
max_depth: u32,
|
||||
center: Vec3,
|
||||
pixel00_loc: Vec3,
|
||||
pixel_delta_u: Vec3,
|
||||
@@ -45,6 +46,7 @@ impl Camera {
|
||||
image_width: image_width,
|
||||
image_height: image_height,
|
||||
anti_alias_rate: anti_alias_rate,
|
||||
max_depth: 50,
|
||||
center: camera_center,
|
||||
pixel00_loc: pixel00_loc,
|
||||
pixel_delta_u: pixel_delta_u,
|
||||
@@ -70,7 +72,7 @@ impl Camera {
|
||||
+ (y * self.pixel_delta_v / (self.anti_alias_rate + 1) as f32);
|
||||
let ray_dir = pixel_loc - self.center;
|
||||
let r = Ray::new(self.center, ray_dir);
|
||||
pixel_colour += self.ray_colour(&hittables, &r);
|
||||
pixel_colour += self.ray_colour(&hittables, &r, self.max_depth);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,11 +86,15 @@ impl Camera {
|
||||
imgbuf.save("output.png").unwrap();
|
||||
}
|
||||
|
||||
fn ray_colour<T: Hittable>(&self, hittables: &Vec<T>, r: &Ray) -> Colour {
|
||||
fn ray_colour<T: Hittable>(&self, hittables: &Vec<T>, r: &Ray, depth: u32) -> Colour {
|
||||
if depth <= 0 {
|
||||
return Colour::nil();
|
||||
}
|
||||
|
||||
let closest = Hit::hit_list(hittables, r);
|
||||
if let Some(hit) = closest {
|
||||
let n = hit.n();
|
||||
return 0.5 * Colour::new(n.x() + 1., n.y() + 1., n.z() + 1.);
|
||||
let dir = *hit.n() + Vec3::random_unit_hemisphere(hit.n());
|
||||
return 0.5 * self.ray_colour(hittables, &Ray::new(*hit.p(), dir), depth - 1);
|
||||
}
|
||||
|
||||
// background
|
||||
|
||||
@@ -19,6 +19,6 @@ fn main() {
|
||||
world.push(Sphere::new(Vec3::new(0., 0., -0.1), 0.01));
|
||||
world.push(Sphere::new(Vec3::new(0., -100.5, -1.), 100.));
|
||||
|
||||
let c = Camera::new_aa(16. / 9., 400, 2);
|
||||
let c = Camera::new_aa(16. / 9., 400, 3);
|
||||
c.render(&world);
|
||||
}
|
||||
|
||||
@@ -28,7 +28,9 @@ impl Hit {
|
||||
for hittable in hittables {
|
||||
if let Some(hit) = hittable.hit(r) {
|
||||
// hit happens in front of camera and is closer than closest
|
||||
if *hit.t() > 0. && (closest.is_none() || closest.as_ref().unwrap().t() > hit.t()) {
|
||||
if *hit.t() > 0.001
|
||||
&& (closest.is_none() || closest.as_ref().unwrap().t() > hit.t())
|
||||
{
|
||||
closest = Some(hit);
|
||||
}
|
||||
}
|
||||
|
||||
52
src/vec3.rs
52
src/vec3.rs
@@ -4,6 +4,8 @@ use std::{
|
||||
ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
|
||||
};
|
||||
|
||||
use rand::RngExt;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Vec3 {
|
||||
r: f32,
|
||||
@@ -26,6 +28,33 @@ impl Vec3 {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn random() -> Vec3 {
|
||||
let mut rng = rand::rng();
|
||||
Vec3 {
|
||||
r: rng.random_range(-1.0..1.),
|
||||
g: rng.random_range(-1.0..1.),
|
||||
b: rng.random_range(-1.0..1.),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn random_unit() -> Vec3 {
|
||||
loop {
|
||||
let v = Vec3::random();
|
||||
if v.length_squared() <= 1. {
|
||||
return v / v.length();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn random_unit_hemisphere(n: &Vec3) -> Vec3 {
|
||||
let v = Vec3::random_unit();
|
||||
if n.dot(&v) > 0.0 {
|
||||
v
|
||||
} else {
|
||||
-v
|
||||
}
|
||||
}
|
||||
|
||||
pub fn x(&self) -> &f32 {
|
||||
&self.r
|
||||
}
|
||||
@@ -67,9 +96,26 @@ impl Vec3 {
|
||||
}
|
||||
|
||||
pub fn output(self) -> image::Rgb<u8> {
|
||||
let ir = (255.599 * self.r.clamp(0., 1.)) as u8;
|
||||
let ig = (255.599 * self.g.clamp(0., 1.)) as u8;
|
||||
let ib = (255.599 * self.b.clamp(0., 1.)) as u8;
|
||||
// gamma correction
|
||||
let r = if self.r > 0. {
|
||||
sqrt(self.r).clamp(0., 1.)
|
||||
} else {
|
||||
0.
|
||||
};
|
||||
let g = if self.g > 0. {
|
||||
sqrt(self.g).clamp(0., 1.)
|
||||
} else {
|
||||
0.
|
||||
};
|
||||
let b = if self.b > 0. {
|
||||
sqrt(self.b).clamp(0.1, 1.)
|
||||
} else {
|
||||
0.
|
||||
};
|
||||
|
||||
let ir = (255.599 * r) as u8;
|
||||
let ig = (255.599 * g) as u8;
|
||||
let ib = (255.599 * b) as u8;
|
||||
|
||||
image::Rgb([ir, ig, ib])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user