Set up some diagnostics for the specular highlight

This commit is contained in:
Savanni D'Gerinel 2024-06-23 23:04:15 -04:00
parent 324d37f858
commit f347e2e47d
4 changed files with 92 additions and 35 deletions

View File

@ -1,53 +1,101 @@
use ray_tracer::{types::*, PPM}; use ray_tracer::{types::*, PPM};
use rayon::prelude::*; use rayon::prelude::*;
use std::{fs::File, io::Write, sync::{Arc, RwLock}}; use std::{
fs::File,
io::Write,
sync::{Arc, RwLock},
};
const SIZE: usize = 100; const SIZE: usize = 100;
fn main() { fn render(
camera: &Point,
light: &PointLight,
sphere: &Sphere,
wall_z: f64,
wall_size: f64,
filename: &str,
) {
let canvas = Arc::new(RwLock::new(Canvas::new(SIZE, SIZE))); let canvas = Arc::new(RwLock::new(Canvas::new(SIZE, SIZE)));
let mut sphere = Sphere::default();
let mut material = Material::default();
material.color = Color::new(1., 0.2, 1.);
*sphere.material_mut() = material;
let light = PointLight::new(Point::new(-10., 10., -10.), Color::new(1., 1., 1.));
let camera = Point::new(0., 0., -5.);
let world_z = 10.;
let wall_size = 7.;
let half = wall_size / 2.;
let pixel_size = wall_size / SIZE as f64; let pixel_size = wall_size / SIZE as f64;
let half = wall_size / 2.;
(0..SIZE).into_par_iter().for_each(|x| { let ray = Ray::new(camera.clone(), (Point::new(0., 0., wall_z) - camera).normalize());
(0..SIZE).into_par_iter().for_each(|y| { let xs = ray.intersect(sphere);
let world_x = -half + pixel_size * x as f64;
let world_y = half - pixel_size * y as f64;
let position = Point::new(world_x, world_y, world_z);
let ray = Ray::new(
camera.clone(),
(position - camera).normalize(),
);
let xs = ray.intersect(&sphere);
match xs.hit() { match xs.hit() {
Some(hit) => { Some(hit) => {
let point = ray.position(hit.t); let point = ray.position(hit.t);
let normal = hit.object.normal_at(&point); let normal = hit.object.normal_at(&point);
let eye = -ray.direction; let eye = -ray.direction;
let color = hit.object.material().lighting(&light, &point, &eye, &normal); let color = hit.object.material().lighting(&light, &point, &eye, &normal);
println!("{:?}", color);
}
None => {}
}
(0..SIZE).into_par_iter().for_each(|x| {
(0..SIZE).into_par_iter().for_each(|y| {
let world_x = -half + pixel_size * x as f64;
let world_y = half - pixel_size * y as f64;
let position = Point::new(world_x, world_y, wall_z);
let ray = Ray::new(camera.clone(), (position - camera).normalize());
let xs = ray.intersect(sphere);
match xs.hit() {
Some(hit) => {
let point = ray.position(hit.t);
let normal = hit.object.normal_at(&point);
let eye = -ray.direction;
let color = hit
.object
.material()
.lighting(&light, &point, &eye, &normal);
*canvas.write().unwrap().pixel_mut(x, y) = color; *canvas.write().unwrap().pixel_mut(x, y) = color;
} }
None => {}, None => {}
} }
}); });
}); });
let canvas = canvas.read().unwrap(); let ppm = PPM::from(&*canvas.read().unwrap());
let mut file = File::create(filename).unwrap();
let ppm = PPM::from(&*canvas);
let mut file = File::create("sphere.ppm").unwrap();
let _ = file.write(ppm.as_bytes()); let _ = file.write(ppm.as_bytes());
} }
fn main() {
let mut sphere = Sphere::default();
let mut material = Material::default();
material.color = Color::new(1., 0.2, 1.);
*sphere.material_mut() = material;
let camera = Point::new(0., 0., -5.);
let wall_z = 10.;
let wall_size = 7.;
{
let light = PointLight::new(Point::new(0., 0., -10.), Color::new(1., 1., 1.));
render(&camera, &light, &sphere, wall_z, wall_size, "sphere_1.ppm");
}
{
let light = PointLight::new(Point::new(-1., 0., -10.), Color::new(1., 1., 1.));
render(&camera, &light, &sphere, wall_z, wall_size, "sphere_2.ppm");
}
{
let light = PointLight::new(Point::new(1., 0., -10.), Color::new(1., 1., 1.));
render(&camera, &light, &sphere, wall_z, wall_size, "sphere_3.ppm");
}
{
let light = PointLight::new(Point::new(0., -1., -10.), Color::new(1., 1., 1.));
render(&camera, &light, &sphere, wall_z, wall_size, "sphere_4.ppm");
}
{
let light = PointLight::new(Point::new(0., 1., -10.), Color::new(1., 1., 1.));
render(&camera, &light, &sphere, wall_z, wall_size, "sphere_5.ppm");
}
}

View File

@ -97,7 +97,8 @@ mod tests {
let m = Material::default(); let m = Material::default();
let position = Point::default(); let position = Point::default();
let eyev = Vector::new(0., -2_f64.sqrt() / 2., -2_f64.sqrt() / 2.); // let eyev = Vector::new(0., -2_f64.sqrt() / 2., -2_f64.sqrt() / 2.);
let eyev = Vector::new(0., -10., -10.).normalize();
let normalv = Vector::new(0., 0., -1.); let normalv = Vector::new(0., 0., -1.);
let light = PointLight::new(Point::new(0., 10., -10.), Color::new(1., 1., 1.)); let light = PointLight::new(Point::new(0., 10., -10.), Color::new(1., 1., 1.));

View File

@ -166,6 +166,14 @@ mod tests {
let v = Vector::new(1., -1., 0.); let v = Vector::new(1., -1., 0.);
let n = Vector::new(0., 1., 0.); let n = Vector::new(0., 1., 0.);
assert_eq!(v.reflect(&n), Vector::new(1., 1., 0.)); assert_eq!(v.reflect(&n), Vector::new(1., 1., 0.));
let v = Vector::new(-1., -1., 0.);
let n = Vector::new(1., 0., 0.);
assert_eq!(v.reflect(&n), Vector::new(1., -1., 0.));
let v = Vector::new(1., 0., -1.);
let n = Vector::new(0., 0., 1.);
assert_eq!(v.reflect(&n), Vector::new(1., 0., 1.));
} }
#[test] #[test]

View File

@ -27,7 +27,7 @@ impl Sphere {
pub fn normal_at(&self, world_point: &Point) -> Vector { pub fn normal_at(&self, world_point: &Point) -> Vector {
let inverted_transform = self.transformation.inverse(); let inverted_transform = self.transformation.inverse();
let object_point = &inverted_transform * world_point; let object_point = &inverted_transform * world_point;
let object_normal = object_point - Point::new(0., 0., 0.); let object_normal = (object_point - Point::new(0., 0., 0.)).normalize();
let mut world_normal = inverted_transform.transpose() * *object_normal; let mut world_normal = inverted_transform.transpose() * *object_normal;
world_normal.3 = 0.; world_normal.3 = 0.;
Vector::from(world_normal).normalize() Vector::from(world_normal).normalize()