Factor integrators into submodules

This commit is contained in:
Matthew Gordon 2021-10-02 16:37:16 -04:00
parent ab7cf9ed72
commit c83416682e
3 changed files with 90 additions and 72 deletions

19
src/integrators/mod.rs Normal file
View File

@ -0,0 +1,19 @@
use super::colour::Photon;
use super::raycasting::IntersectionInfo;
use super::sampler::Sampler;
mod whitted_integrator;
pub use whitted_integrator::*;
mod simple_random_integrator;
pub use simple_random_integrator::*;
pub trait Integrator {
fn integrate(
&self,
sampler: &Sampler,
info: &IntersectionInfo,
photon: &Photon,
recursion_limit: u16,
) -> Photon;
}

View File

@ -0,0 +1,65 @@
use crate::math::Vec3;
use crate::colour::{ColourRgbF, Photon, Spectrum};
use crate::materials::MaterialSampleResult;
use crate::raycasting::{IntersectionInfo, Ray};
use crate::sampler::Sampler;
use crate::util::algebra_utils::try_change_of_basis_matrix;
use super::Integrator;
pub struct SimpleRandomIntegrator {}
impl Integrator for SimpleRandomIntegrator {
fn integrate(
&self,
sampler: &Sampler,
info: &IntersectionInfo,
photon: &Photon,
recursion_limit: u16,
) -> Photon {
if recursion_limit == 0 {
return Photon {
wavelength: 0.0,
intensity: 0.0,
};
}
let world_to_bsdf_space =
try_change_of_basis_matrix(&info.tangent, &info.cotangent, &info.normal)
.expect("Normal, tangent and cotangent don't form a valid basis.");
let bsdf_to_world_space = world_to_bsdf_space
.try_inverse()
.expect("Expected matrix to be invertable.");
let world_space_w_i = info.retro;
let w_i = world_to_bsdf_space * world_space_w_i;
let MaterialSampleResult {
direction: w_o,
pdf: w_o_pdf,
} = info.material.sample(&w_i, &photon);
let world_space_w_o = bsdf_to_world_space * w_o;
info.material.bsdf()(
&w_o,
&w_i,
&match sampler.sample(&Ray::new(info.location, world_space_w_o).bias(0.000_000_1)) {
None => photon.set_intensity(test_lighting_environment(
&world_space_w_o,
photon.wavelength,
)),
Some(recursive_hit) => {
self.integrate(&sampler, &recursive_hit, &photon, recursion_limit - 1)
}
}
.scale_intensity(w_o_pdf)
.scale_intensity(world_space_w_o.dot(&info.normal).abs()),
)
}
}
pub fn test_lighting_environment(w_o: &Vec3, wavelength: f64) -> f64 {
let sun_direction = Vec3::new(1.0, 1.0, -1.0).normalize();
if w_o.dot(&sun_direction) >= 0.99 {
300.0
} else {
let sky_colour = ColourRgbF::new(w_o.y(), w_o.y(), 1.0);
Spectrum::reflection_from_linear_rgb(&sky_colour).intensity_at_wavelength(wavelength)
}
}

View File

@ -1,20 +1,11 @@
use crate::math::Vec3; use crate::math::Vec3;
use crate::colour::{Photon, Spectrum};
use crate::materials::MaterialSampleResult;
use crate::raycasting::{IntersectionInfo, Ray};
use crate::sampler::Sampler;
use crate::util::algebra_utils::try_change_of_basis_matrix;
use super::colour::{ColourRgbF, Photon, Spectrum}; use super::Integrator;
use super::materials::MaterialSampleResult;
use super::raycasting::{IntersectionInfo, Ray};
use super::sampler::Sampler;
use super::util::algebra_utils::try_change_of_basis_matrix;
pub trait Integrator {
fn integrate(
&self,
sampler: &Sampler,
info: &IntersectionInfo,
photon: &Photon,
recursion_limit: u16,
) -> Photon;
}
pub struct DirectionalLight { pub struct DirectionalLight {
pub direction: Vec3, pub direction: Vec3,
@ -94,60 +85,3 @@ impl Integrator for WhittedIntegrator {
}) })
} }
} }
pub struct SimpleRandomIntegrator {}
impl Integrator for SimpleRandomIntegrator {
fn integrate(
&self,
sampler: &Sampler,
info: &IntersectionInfo,
photon: &Photon,
recursion_limit: u16,
) -> Photon {
if recursion_limit == 0 {
return Photon {
wavelength: 0.0,
intensity: 0.0,
};
}
let world_to_bsdf_space =
try_change_of_basis_matrix(&info.tangent, &info.cotangent, &info.normal)
.expect("Normal, tangent and cotangent don't form a valid basis.");
let bsdf_to_world_space = world_to_bsdf_space
.try_inverse()
.expect("Expected matrix to be invertable.");
let world_space_w_i = info.retro;
let w_i = world_to_bsdf_space * world_space_w_i;
let MaterialSampleResult {
direction: w_o,
pdf: w_o_pdf,
} = info.material.sample(&w_i, &photon);
let world_space_w_o = bsdf_to_world_space * w_o;
info.material.bsdf()(
&w_o,
&w_i,
&match sampler.sample(&Ray::new(info.location, world_space_w_o).bias(0.000_000_1)) {
None => photon.set_intensity(test_lighting_environment(
&world_space_w_o,
photon.wavelength,
)),
Some(recursive_hit) => {
self.integrate(&sampler, &recursive_hit, &photon, recursion_limit - 1)
}
}
.scale_intensity(w_o_pdf)
.scale_intensity(world_space_w_o.dot(&info.normal).abs()),
)
}
}
pub fn test_lighting_environment(w_o: &Vec3, wavelength: f64) -> f64 {
let sun_direction = Vec3::new(1.0, 1.0, -1.0).normalize();
if w_o.dot(&sun_direction) >= 0.99 {
300.0
} else {
let sky_colour = ColourRgbF::new(w_o.y(), w_o.y(), 1.0);
Spectrum::reflection_from_linear_rgb(&sky_colour).intensity_at_wavelength(wavelength)
}
}