pbrt/src/integrators/base.rs

71 lines
2.2 KiB
Rust

use super::state::PathState;
use crate::core::light::Light;
use shared::core::geometry::Ray;
use shared::core::interaction::{Interaction, InteractionTrait};
use shared::core::primitive::Primitive;
use shared::core::shape::ShapeIntersection;
use shared::lights::LightSampler;
use shared::spectra::SampledWavelengths;
use shared::utils::sampling::power_heuristic;
use shared::{Float, SHADOW_EPSILON};
use std::sync::Arc;
#[derive(Clone, Debug)]
pub struct IntegratorBase {
pub aggregate: Arc<Primitive>,
pub lights: Vec<Arc<Light>>,
pub infinite_lights: Vec<Arc<Light>>,
}
impl IntegratorBase {
pub fn new(aggregate: Arc<Primitive>, lights: Vec<Arc<Light>>) -> Self {
let infinite_lights = lights
.iter()
.filter(|light| light.light_type().is_infinite())
.cloned()
.collect();
Self {
aggregate,
lights,
infinite_lights,
}
}
pub fn intersect(&self, ray: &Ray, t_max: Option<Float>) -> Option<ShapeIntersection> {
self.aggregate.intersect(ray, t_max)
}
pub fn intersect_p(&self, ray: &Ray, t_max: Option<Float>) -> bool {
self.aggregate.intersect_p(ray, t_max)
}
pub fn unoccluded(&self, p0: &Interaction, p1: &Interaction) -> bool {
!self.intersect_p(&p0.spawn_ray_to_interaction(p1), Some(1. - SHADOW_EPSILON))
}
pub fn add_infinite_light_contribution(
&self,
state: &mut PathState,
ray: &Ray,
lambda: &SampledWavelengths,
light_sampler: Option<&LightSampler>,
use_mis: bool,
) {
for light in &self.infinite_lights {
let le = light.le(ray, lambda);
if le.is_black() {
continue;
}
if state.depth == 0 || state.specular_bounce || !use_mis {
state.l += state.beta * le;
} else if let Some(sampler) = light_sampler {
let p_l = sampler.pmf_with_context(&state.prev_ctx, light)
* light.pdf_li(&state.prev_ctx, ray.d, true);
let w_b = power_heuristic(1, state.prev_pdf, 1, p_l);
state.l += state.beta * w_b * le;
}
}
}
}