From 77cf8772104cec5c6d61fd655020658b950faf37 Mon Sep 17 00:00:00 2001 From: Matthew Gordon Date: Sat, 23 Nov 2019 21:36:59 -0500 Subject: [PATCH] Factor out Sampler struct and add shadow casting There are now bad rendering artifacts which I believe are caused by precision issues. --- src/camera.rs | 17 +++++------------ src/integrators.rs | 20 +++++++++++++------- src/lib.rs | 1 + src/sampler.rs | 23 +++++++++++++++++++++++ 4 files changed, 42 insertions(+), 19 deletions(-) create mode 100644 src/sampler.rs diff --git a/src/camera.rs b/src/camera.rs index a3188d8..57f3371 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -4,6 +4,7 @@ use super::colour::{ColourRgbF, NamedColour}; use super::image::ImageRgbF; use super::integrators::{DirectionalLight, Integrator, PhongIntegrator}; use super::raycasting::Ray; +use super::sampler::Sampler; use super::scene::Scene; struct ImageSampler { @@ -61,7 +62,7 @@ impl ImageSampler { } } -pub fn render_scene<'a, T: RealField>(output_image: &mut ImageRgbF, scene: &Scene) { +pub fn render_scene(output_image: &mut ImageRgbF, scene: &Scene) { let image_sampler = ImageSampler::new( output_image.get_width(), output_image.get_height(), @@ -76,22 +77,14 @@ pub fn render_scene<'a, T: RealField>(output_image: &mut ImageRgbF, scene: &S colour: ColourRgbF::from_named(NamedColour::White) * directional_intensity, }], }; + let sampler = Sampler { scene }; 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); - let hit = scene - .objects - .iter() - .flat_map(|object| object.intersect(&ray)) - .min_by( - |a, b| match PartialOrd::partial_cmp(&a.distance, &b.distance) { - None => std::cmp::Ordering::Less, - Some(ordering) => ordering, - }, - ); + let hit = sampler.sample(&ray); let colour = match hit { None => ColourRgbF::from_named(NamedColour::Black), - Some(intersection_info) => integrator.integrate(&intersection_info), + Some(intersection_info) => integrator.integrate(&sampler, &intersection_info), }; output_image.set_colour(row, column, colour); } diff --git a/src/integrators.rs b/src/integrators.rs index 5f7ceb8..f117769 100644 --- a/src/integrators.rs +++ b/src/integrators.rs @@ -1,10 +1,11 @@ use nalgebra::{RealField, Vector3}; use super::colour::ColourRgbF; -use super::raycasting::IntersectionInfo; +use super::raycasting::{IntersectionInfo, Ray}; +use super::sampler::Sampler; pub trait Integrator { - fn integrate(&self, info: &IntersectionInfo) -> ColourRgbF; + fn integrate(&self, sampler: &Sampler, info: &IntersectionInfo) -> ColourRgbF; } pub struct DirectionalLight { @@ -18,13 +19,18 @@ pub struct PhongIntegrator { } impl Integrator for PhongIntegrator { - fn integrate(&self, info: &IntersectionInfo) -> ColourRgbF { + fn integrate(&self, sampler: &Sampler, info: &IntersectionInfo) -> ColourRgbF { self.lights .iter() - .map(|light| { - info.material.bsdf()(info.retro, light.direction, light.colour) - * light.direction.dot(&info.normal) - }) + .map( + |light| match sampler.sample(&Ray::new(info.location, light.direction)) { + Some(_) => self.ambient_light, + None => { + info.material.bsdf()(info.retro, light.direction, light.colour) + * light.direction.dot(&info.normal) + } + }, + ) .fold(self.ambient_light, |a, b| a + b) } } diff --git a/src/lib.rs b/src/lib.rs index 2eb446f..ea9f378 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,4 +4,5 @@ pub mod image; pub mod integrators; pub mod materials; pub mod raycasting; +pub mod sampler; pub mod scene; diff --git a/src/sampler.rs b/src/sampler.rs new file mode 100644 index 0000000..172bcb6 --- /dev/null +++ b/src/sampler.rs @@ -0,0 +1,23 @@ +use super::raycasting::{IntersectionInfo, Ray}; +use super::scene::Scene; + +use nalgebra::RealField; + +pub struct Sampler<'a, T: RealField> { + pub scene: &'a Scene, +} + +impl<'a, T: RealField> Sampler<'a, T> { + pub fn sample(&self, ray: &Ray) -> Option> { + self.scene + .objects + .iter() + .flat_map(|object| object.intersect(&ray)) + .min_by( + |a, b| match PartialOrd::partial_cmp(&a.distance, &b.distance) { + None => std::cmp::Ordering::Less, + Some(ordering) => ordering, + }, + ) + } +}