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 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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.));
|
||||||
|
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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()
|
||||||
|
|
Loading…
Reference in New Issue