Add Phong material

This commit is contained in:
Matthew Gordon 2019-11-27 17:05:51 -05:00
parent 0a7963097c
commit dbbd855c73
4 changed files with 44 additions and 6 deletions

View File

@ -1,5 +1,6 @@
use nalgebra::{convert, RealField, Vector3}; use nalgebra::{convert, RealField, Vector3};
use super::algebra_utils::try_change_of_basis_matrix;
use super::colour::ColourRgbF; use super::colour::ColourRgbF;
use super::raycasting::{IntersectionInfo, Ray}; use super::raycasting::{IntersectionInfo, Ray};
use super::sampler::Sampler; use super::sampler::Sampler;
@ -25,13 +26,19 @@ impl<T: RealField> Integrator<T> for WhittedIntegrator<T> {
self.lights self.lights
.iter() .iter()
.map(|light| { .map(|light| {
let basis_change =
try_change_of_basis_matrix(&info.tangent, &info.cotangent, &info.normal)
.expect("Normal, tangent and cotangent don't for a valid basis.");
match sampler match sampler
.sample(&Ray::new(info.location, light.direction).bias(convert(0.000000001))) .sample(&Ray::new(info.location, light.direction).bias(convert(0.000000001)))
{ {
Some(_) => self.ambient_light, Some(_) => self.ambient_light,
None => { None => {
info.material.bsdf()(info.retro, light.direction, light.colour) info.material.bsdf()(
* light.direction.dot(&info.normal) basis_change * info.retro,
basis_change * light.direction,
light.colour,
) * light.direction.dot(&info.normal).abs()
} }
} }
}) })

View File

@ -1,3 +1,4 @@
pub mod algebra_utils;
pub mod camera; pub mod camera;
pub mod colour; pub mod colour;
pub mod image; pub mod image;

View File

@ -13,7 +13,7 @@ use std::rc::Rc;
use vanrijn::camera::partial_render_scene; use vanrijn::camera::partial_render_scene;
use vanrijn::colour::{ColourRgbF, NamedColour}; use vanrijn::colour::{ColourRgbF, NamedColour};
use vanrijn::image::{ClampingToneMapper, ImageRgbF, ImageRgbU8, ToneMapper}; use vanrijn::image::{ClampingToneMapper, ImageRgbF, ImageRgbU8, ToneMapper};
use vanrijn::materials::LambertianMaterial; use vanrijn::materials::{LambertianMaterial, PhongMaterial};
use vanrijn::raycasting::{Plane, Sphere}; use vanrijn::raycasting::{Plane, Sphere};
use vanrijn::scene::Scene; use vanrijn::scene::Scene;
@ -88,9 +88,11 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
Box::new(Sphere::new( Box::new(Sphere::new(
Vector3::new(0.0, 1.5, 6.0), Vector3::new(0.0, 1.5, 6.0),
1.0, 1.0,
Rc::new(LambertianMaterial { Rc::new(PhongMaterial {
colour: ColourRgbF::from_named(NamedColour::Red), colour: ColourRgbF::from_named(NamedColour::Red),
diffuse_strength: 0.1, diffuse_strength: 0.05,
smoothness: 20.0,
specular_strength: 250.0,
}), }),
)), )),
], ],

View File

@ -1,6 +1,6 @@
use nalgebra::{RealField, Vector3}; use nalgebra::{RealField, Vector3};
use super::colour::ColourRgbF; use super::colour::{ColourRgbF, NamedColour};
use std::fmt::Debug; use std::fmt::Debug;
@ -36,3 +36,31 @@ impl<T: RealField> Material<T> for LambertianMaterial<T> {
) )
} }
} }
#[derive(Debug)]
pub struct PhongMaterial<T: RealField> {
pub colour: ColourRgbF<T>,
pub diffuse_strength: T,
pub specular_strength: T,
pub smoothness: T,
}
impl<T: RealField> Material<T> for PhongMaterial<T> {
fn bsdf<'a>(
&'a self,
) -> Box<dyn Fn(Vector3<T>, Vector3<T>, ColourRgbF<T>) -> ColourRgbF<T> + 'a> {
Box::new(
move |w_o: Vector3<T>, w_i: Vector3<T>, colour_in: ColourRgbF<T>| {
if w_i.z < T::zero() || w_o.z < T::zero() {
ColourRgbF::from_vector3(&Vector3::zeros())
} else {
let reflection_vector = Vector3::new(-w_i.x, -w_i.y, w_i.z);
self.colour * colour_in * self.diffuse_strength
+ ColourRgbF::from_named(NamedColour::White)
* w_o.dot(&reflection_vector).abs().powf(self.smoothness)
* (self.specular_strength / w_i.dot(&Vector3::z_axis()))
}
},
)
}
}