pbrt_r3/integrators/
directlighting.rs1use crate::core::prelude::*;
2
3use std::sync::Arc;
4use std::sync::RwLock;
5
6#[derive(Copy, Clone, Debug, PartialEq)]
7pub enum DirectLightingLightStrategy {
8 UniformSampleAll,
9 UniformSampleOne,
10}
11
12type LightStrategy = DirectLightingLightStrategy;
13
14pub struct DirectLightingIntegrator {
15 base: BaseSamplerIntegrator,
16 strategy: LightStrategy,
17 max_depth: i32,
18 n_light_samples: Vec<u32>,
19}
20
21impl DirectLightingIntegrator {
22 pub fn new(
23 strategy: LightStrategy,
24 max_depth: i32,
25 camera: &Arc<dyn Camera>,
26 sampler: &Arc<RwLock<dyn Sampler>>,
27 pixel_bounds: &Bounds2i,
28 ) -> Self {
29 DirectLightingIntegrator {
30 base: BaseSamplerIntegrator::new(camera, sampler, pixel_bounds),
31 strategy,
32 max_depth,
33 n_light_samples: Vec::new(),
34 }
35 }
36}
37
38impl Integrator for DirectLightingIntegrator {
39 fn render(&mut self, scene: &Scene) {
40 BaseSamplerIntegrator::render(self, scene);
41 }
42
43 fn get_camera(&self) -> Arc<dyn Camera> {
44 return Arc::clone(&self.base.camera);
45 }
46}
47
48unsafe impl Sync for DirectLightingIntegrator {}
49
50impl SamplerIntegrator for DirectLightingIntegrator {
51 fn preprocess(&mut self, scene: &Scene, sampler: &mut dyn Sampler) {
52 if self.strategy == LightStrategy::UniformSampleAll {
53 for light in scene.lights.iter() {
54 let count = sampler.round_count(light.as_ref().get_sample_count());
55 self.n_light_samples.push(count);
56 }
57 for _ in 0..self.max_depth {
58 for j in 0..scene.lights.len() {
59 let n = self.n_light_samples[j];
60 sampler.request_2d_array(n);
61 sampler.request_2d_array(n);
62 }
63 }
64 }
65 }
66 fn li(
67 &self,
68 ray: &RayDifferential,
69 scene: &Scene,
70 sampler: &mut dyn Sampler,
71 arena: &mut MemoryArena,
72 depth: i32,
73 ) -> Spectrum {
74 let _p = ProfilePhase::new(Prof::SamplerIntegratorLi);
75
76 if let Some(mut isect) = scene.intersect(&ray.ray) {
77 let wo = isect.wo;
78
79 isect.compute_scattering_functions(ray, arena, TransportMode::Radiance, false);
80
81 let tisect = Interaction::from(isect);
82 let isect = tisect.as_surface_interaction().unwrap();
83
84 if isect.bsdf.is_some() {
85 let mut l = isect.le(&wo);
86 if !scene.lights.is_empty() {
87 match self.strategy {
88 LightStrategy::UniformSampleAll => {
89 l += uniform_sample_all_lights(
90 &tisect,
91 scene,
92 arena,
93 sampler,
94 &self.n_light_samples,
95 false,
96 );
97 }
98 LightStrategy::UniformSampleOne => {
99 l += uniform_sample_one_light(
100 &tisect, scene, arena, sampler, false, None,
101 );
102 }
103 }
104 }
105 if depth + 1 < self.max_depth {
106 l += self.specular_reflect(ray, isect, scene, sampler, arena, depth);
107 l += self.specular_transmit(ray, isect, scene, sampler, arena, depth);
108 }
109 return l;
110 } else {
111 let rd = RayDifferential::from(isect.spawn_ray(&ray.ray.d));
112 return self.li(&rd, scene, sampler, arena, depth);
113 }
114 } else {
115 let l = scene
116 .lights
117 .iter()
118 .map(|light| -> Spectrum {
119 return light.as_ref().le(ray);
120 })
121 .fold(Spectrum::zero(), |a, b| {
122 return a + b;
123 });
124 return l;
125 }
126 }
127
128 fn get_sampler(&self) -> Arc<RwLock<dyn Sampler>> {
129 return Arc::clone(&self.base.sampler);
130 }
131
132 fn get_pixel_bounds(&self) -> Bounds2i {
133 return self.base.pixel_bounds;
134 }
135}
136
137pub fn create_direct_lighting_integrator(
138 params: &ParamSet,
139 sampler: &Arc<RwLock<dyn Sampler>>,
140 camera: &Arc<dyn Camera>,
141) -> Result<Arc<RwLock<dyn Integrator>>, PbrtError> {
142 let max_depth = params.find_one_int("maxdepth", 5);
143 let st = params.find_one_string("strategy", "all");
144 let sterategy = if st == "one" {
145 LightStrategy::UniformSampleOne
146 } else {
147 LightStrategy::UniformSampleAll
148 };
149 let film = camera.as_ref().get_film();
150 let pixel_bounds = film.read().unwrap().get_sample_bounds();
151
152 return Ok(Arc::new(RwLock::new(DirectLightingIntegrator::new(
153 sterategy,
154 max_depth,
155 camera,
156 sampler,
157 &pixel_bounds,
158 ))));
159}