Set up some diagnostics for the specular highlight
This commit is contained in:
parent
324d37f858
commit
f347e2e47d
|
@ -1,53 +1,101 @@
|
|||
use ray_tracer::{types::*, PPM};
|
||||
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;
|
||||
|
||||
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 pixel_size = wall_size / SIZE as f64;
|
||||
let half = wall_size / 2.;
|
||||
|
||||
let ray = Ray::new(camera.clone(), (Point::new(0., 0., wall_z) - 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);
|
||||
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;
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
let ppm = PPM::from(&*canvas.read().unwrap());
|
||||
let mut file = File::create(filename).unwrap();
|
||||
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 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_z = 10.;
|
||||
let wall_size = 7.;
|
||||
let half = wall_size / 2.;
|
||||
|
||||
let pixel_size = wall_size / SIZE as f64;
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
(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, world_z);
|
||||
{
|
||||
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 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;
|
||||
}
|
||||
None => {},
|
||||
}
|
||||
});
|
||||
});
|
||||
{
|
||||
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 canvas = canvas.read().unwrap();
|
||||
{
|
||||
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 ppm = PPM::from(&*canvas);
|
||||
let mut file = File::create("sphere.ppm").unwrap();
|
||||
let _ = file.write(ppm.as_bytes());
|
||||
{
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,7 +97,8 @@ mod tests {
|
|||
let m = Material::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 light = PointLight::new(Point::new(0., 10., -10.), Color::new(1., 1., 1.));
|
||||
|
||||
|
|
|
@ -166,6 +166,14 @@ mod tests {
|
|||
let v = Vector::new(1., -1., 0.);
|
||||
let n = Vector::new(0., 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]
|
||||
|
|
|
@ -27,7 +27,7 @@ impl Sphere {
|
|||
pub fn normal_at(&self, world_point: &Point) -> Vector {
|
||||
let inverted_transform = self.transformation.inverse();
|
||||
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;
|
||||
world_normal.3 = 0.;
|
||||
Vector::from(world_normal).normalize()
|
||||
|
|
Loading…
Reference in New Issue