Bias shadow rays to fix noise in image

This commit is contained in:
Matthew Gordon 2019-11-23 22:08:50 -05:00
parent 77cf877210
commit 5a0646aaa2
3 changed files with 29 additions and 14 deletions

View File

@ -2,7 +2,7 @@ use nalgebra::{convert, RealField, Vector3};
use super::colour::{ColourRgbF, NamedColour};
use super::image::ImageRgbF;
use super::integrators::{DirectionalLight, Integrator, PhongIntegrator};
use super::integrators::{DirectionalLight, Integrator, WhittedIntegrator};
use super::raycasting::Ray;
use super::sampler::Sampler;
use super::scene::Scene;
@ -69,13 +69,20 @@ pub fn render_scene<T: RealField>(output_image: &mut ImageRgbF<T>, scene: &Scene
scene.camera_location,
);
let ambient_intensity: T = convert(0.0);
let directional_intensity: T = convert(0.9);
let integrator = PhongIntegrator::<T> {
let directional_intensity1: T = convert(0.7);
let directional_intensity2: T = convert(0.3);
let integrator = WhittedIntegrator::<T> {
ambient_light: ColourRgbF::from_named(NamedColour::White) * ambient_intensity,
lights: vec![DirectionalLight {
lights: vec![
DirectionalLight {
direction: Vector3::new(convert(1.0), convert(1.0), convert(-1.0)).normalize(),
colour: ColourRgbF::from_named(NamedColour::White) * directional_intensity,
}],
colour: ColourRgbF::from_named(NamedColour::White) * directional_intensity1,
},
DirectionalLight {
direction: Vector3::new(convert(-0.5), convert(2.0), convert(-0.5)).normalize(),
colour: ColourRgbF::from_named(NamedColour::White) * directional_intensity2,
},
],
};
let sampler = Sampler { scene };
for column in 0..output_image.get_width() {

View File

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

View File

@ -21,6 +21,10 @@ impl<T: RealField> Ray<T> {
pub fn point_at(&self, t: T) -> Vector3<T> {
return self.origin + self.direction * t;
}
pub fn bias(&self, amount: T) -> Ray<T> {
Ray::new(self.origin + self.direction * amount, self.direction)
}
}
#[derive(Debug)]