use nalgebra::{convert, RealField, Vector3}; use super::colour::ColourRgbF; use super::raycasting::{IntersectionInfo, Ray}; use super::sampler::Sampler; pub trait Integrator { fn integrate(&self, sampler: &Sampler, info: &IntersectionInfo) -> ColourRgbF; } pub struct DirectionalLight { pub direction: Vector3, pub colour: ColourRgbF, } pub struct WhittedIntegrator { pub ambient_light: ColourRgbF, pub lights: Vec>, } // TODO: Get rid of the magic bias number, which should be calculated base on expected error // bounds and tangent direction impl Integrator for WhittedIntegrator { fn integrate(&self, sampler: &Sampler, info: &IntersectionInfo) -> ColourRgbF { self.lights .iter() .map(|light| { match sampler .sample(&Ray::new(info.location, light.direction).bias(convert(0.000000001))) { 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) } }