diff --git a/src/main.rs b/src/main.rs index f58a1eb..0b85428 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,7 +13,7 @@ use std::rc::Rc; use vanrijn::camera::partial_render_scene; use vanrijn::colour::{ColourRgbF, NamedColour}; use vanrijn::image::{ClampingToneMapper, ImageRgbF, ImageRgbU8, ToneMapper}; -use vanrijn::materials::{LambertianMaterial, PhongMaterial}; +use vanrijn::materials::{LambertianMaterial, PhongMaterial, ReflectiveMaterial}; use vanrijn::raycasting::{Plane, Sphere}; use vanrijn::scene::Scene; @@ -80,9 +80,10 @@ pub fn main() -> Result<(), Box> { Box::new(Sphere::new( Vector3::new(-1.25, -0.5, 6.0), 1.0, - Rc::new(LambertianMaterial { + Rc::new(ReflectiveMaterial { colour: ColourRgbF::from_named(NamedColour::Blue), - diffuse_strength: 0.1, + diffuse_strength: 0.01, + reflection_strength: 0.99, }), )), Box::new(Sphere::new( diff --git a/src/materials.rs b/src/materials.rs index f3bf3a1..74bf165 100644 --- a/src/materials.rs +++ b/src/materials.rs @@ -1,4 +1,4 @@ -use nalgebra::{RealField, Vector3}; +use nalgebra::{convert, RealField, Vector3}; use super::colour::{ColourRgbF, NamedColour}; @@ -68,3 +68,39 @@ impl Material for PhongMaterial { ) } } + +#[derive(Debug)] +pub struct ReflectiveMaterial { + pub colour: ColourRgbF, + pub diffuse_strength: T, + pub reflection_strength: T, +} + +impl Material for ReflectiveMaterial { + fn bsdf<'a>( + &'a self, + ) -> Box, Vector3, ColourRgbF) -> ColourRgbF + 'a> { + Box::new( + move |w_o: Vector3, w_i: Vector3, colour_in: ColourRgbF| { + if w_i.z < T::zero() || w_o.z < T::zero() { + ColourRgbF::new(T::zero(), T::one(), T::one()) + } else { + let reflection_vector = Vector3::new(-w_o.x, -w_o.y, w_o.z); + let reflection_colour = colour_in * self.reflection_strength; + let diffuse_colour = self.colour * colour_in * self.diffuse_strength; + let sigma: T = convert(0.001); + let two: T = convert(2.0); + let reflection_factor = (-w_i.dot(&reflection_vector).acos().powf(two) + / (two * sigma * sigma)) + .exp(); + reflection_colour * reflection_factor + + diffuse_colour * (T::one() - reflection_factor) + } + }, + ) + } + + fn sample(&self, w_o: &Vector3) -> Vec> { + vec![Vector3::new(-w_o.x, -w_o.y, w_o.z)] + } +}