Added Phong integrator (actually only computing lambertion yet)

This commit is contained in:
Matthew Gordon 2019-11-12 22:11:06 -05:00
parent 4f60719523
commit d9af6dad94
3 changed files with 42 additions and 12 deletions

View File

@ -1,6 +1,7 @@
use nalgebra::{convert, RealField, Vector3};
use nalgebra::{clamp, convert, RealField, Vector3};
use super::image::OutputImage;
use super::integrators::{DirectionalLight, Integrator, PhongIntegrator};
use super::raycasting::Ray;
use super::scene::Scene;
@ -59,12 +60,22 @@ impl<T: RealField> ImageSampler<T> {
}
}
pub fn render_scene<T: RealField>(output_image: &mut OutputImage, scene: &Scene<T>) {
pub fn render_scene<T: RealField>(output_image: &mut OutputImage, scene: &Scene<T>)
where
f32: From<T>,
{
let image_sampler = ImageSampler::new(
output_image.get_width(),
output_image.get_height(),
scene.camera_location,
);
let integrator = PhongIntegrator::<T> {
ambient_light: convert(0.1),
lights: vec![DirectionalLight {
direction: Vector3::new(convert(1.0), convert(1.0), convert(-1.0)).normalize(),
intensity: convert(0.3),
}],
};
for column in 0..output_image.get_width() {
for row in 0..output_image.get_height() {
let ray = image_sampler.ray_for_pixel(row, column);
@ -79,9 +90,10 @@ pub fn render_scene<T: RealField>(output_image: &mut OutputImage, scene: &Scene<
},
);
let gray = match hit {
None => 0,
Some(_) => 255,
None => convert(0.0),
Some(intersection_info) => integrator.integrate(&intersection_info),
};
let gray = f32::from(clamp(gray * convert(255.0), convert(0.0), convert(255.0))) as u8;
output_image.set_color(row, column, gray, gray, gray);
}
}

View File

@ -2,3 +2,4 @@ pub mod raycasting;
pub mod image;
pub mod camera;
pub mod scene;
pub mod integrators;

View File

@ -23,6 +23,7 @@ impl<T: RealField> Ray<T> {
pub struct IntersectionInfo<T: RealField> {
pub distance: T,
pub location: Vector3<T>,
pub normal: Vector3<T>,
}
pub trait Intersect<T: RealField> {
@ -44,15 +45,30 @@ impl<T: RealField> Intersect<T> for Sphere<T> {
fn intersect(&self, ray: &Ray<T>) -> Option<IntersectionInfo<T>> {
// t0/p0 is the point on the ray that's closest to the centre of the sphere
let t0 = (self.centre - ray.origin).dot(&ray.direction);
let p0 = ray.point_at(t0);
if (self.centre - p0).norm() <= self.radius {
Some(IntersectionInfo {
distance: t0,
location: p0,
})
} else {
None
let delta_squared =
t0 * t0 - ((ray.origin - self.centre).norm_squared() - self.radius * self.radius);
if delta_squared > self.radius {
//No initersection
return None;
}
let delta = delta_squared.sqrt();
let distance = if (self.centre - ray.origin).norm() <= self.radius {
// radius origin is inside sphere
t0 + delta
} else {
t0 - delta
};
if distance < T::zero() {
// Sphere is behind ray origin
return None;
};
let location = ray.point_at(distance);
let normal = (location - self.centre).normalize();
Some(IntersectionInfo {
distance,
location,
normal,
})
}
}
@ -91,6 +107,7 @@ impl<T: RealField> Intersect<T> for Plane<T> {
Some(IntersectionInfo {
distance: t,
location: ray.point_at(t),
normal: self.normal,
})
}
}