pbrt_r3/samplers/
sobol.rs1use crate::core::prelude::*;
2
3use std::sync::Arc;
4use std::sync::RwLock;
5
6#[derive(Debug, PartialEq, Default, Clone)]
7pub struct SobolSampler {
8 pub base: BaseGlobalSampler,
9 sample_bounds: Bounds2i,
13 resolution: u32,
14 log2_resolution: u32,
15}
16
17impl SobolSampler {
18 pub fn new(samples_per_pixel: u32, sample_bounds: &Bounds2i) -> Self {
19 let diagonal = sample_bounds.diagonal();
20 let resolution = round_up_pow2(u32::max(diagonal.x as u32, diagonal.y as u32));
21 let log2_resolution = log2int(resolution);
22 SobolSampler {
23 base: BaseGlobalSampler::new(round_up_pow2(samples_per_pixel)),
24 sample_bounds: *sample_bounds,
28 resolution,
29 log2_resolution,
30 }
31 }
32}
33
34impl Sampler for SobolSampler {
35 fn start_pixel(&mut self, p: &Point2i) {
36 let _p = ProfilePhase::new(Prof::StartPixel);
37
38 self.base.base.start_pixel(p);
39 self.base.dimension = 0;
40 self.base.interval_sample_index = self.get_index_for_sample(0);
43 self.base.array_end_dim = BaseGlobalSampler::array_start_dim
44 + (self.base.base.sample_array1d.len() + 2 * self.base.base.sample_array2d.len())
45 as u32;
46 let samples1d_array_sizes = self.base.base.samples1d_array_sizes.len();
47 {
49 let l = samples1d_array_sizes;
50 for i in 0..l {
51 let n_samples =
52 self.base.base.samples1d_array_sizes[i] * self.base.base.samples_per_pixel;
53 for j in 0..n_samples {
54 let index = self.get_index_for_sample(j as i64);
55 self.base.base.sample_array1d[i][j as usize] =
56 self.sample_dimension(index, self.base.array_end_dim + i as u32);
57 }
58 }
59 }
60 {
62 let dim = BaseGlobalSampler::array_start_dim + samples1d_array_sizes as u32;
63 let l = self.base.base.samples2d_array_sizes.len();
64 for i in 0..l {
65 let n_samples =
66 self.base.base.samples2d_array_sizes[i] * self.base.base.samples_per_pixel;
67 for j in 0..n_samples {
68 let index = self.get_index_for_sample(j as i64);
69 self.base.base.sample_array2d[i][j as usize].x =
70 self.sample_dimension(index, dim);
71 self.base.base.sample_array2d[i][j as usize].y =
72 self.sample_dimension(index, dim + 1);
73 }
74 }
75 }
76 }
77
78 fn start_next_sample(&mut self) -> bool {
79 self.base.dimension = 0;
80 self.base.interval_sample_index =
83 self.get_index_for_sample((self.base.base.current_pixel_sample_index + 1) as i64);
84 return self.base.base.start_next_sample();
85 }
86
87 fn set_sample_number(&mut self, sample_num: u32) -> bool {
88 self.base.dimension = 0;
89 self.base.interval_sample_index = self.get_index_for_sample(sample_num as i64);
92 return self.base.base.set_sample_number(sample_num);
93 }
94
95 fn get_1d(&mut self) -> Float {
96 if self.base.dimension >= BaseGlobalSampler::array_start_dim
97 && self.base.dimension < self.base.array_end_dim
98 {
99 self.base.dimension = self.base.array_end_dim;
100 }
101 let d = self.base.dimension;
102 let x = self.sample_dimension(self.base.interval_sample_index, d);
103 self.base.dimension += 1;
104
105 return x;
114 }
115
116 fn get_2d(&mut self) -> Point2f {
117 if self.base.dimension + 1 >= BaseGlobalSampler::array_start_dim
118 && self.base.dimension < self.base.array_end_dim
119 {
120 self.base.dimension = self.base.array_end_dim;
121 }
122 let d = self.base.dimension;
123 let x = self.sample_dimension(self.base.interval_sample_index, d);
125 let y = self.sample_dimension(self.base.interval_sample_index, d + 1);
126 let p = Point2f::new(x, y);
127 self.base.dimension += 2;
128
129 return p;
141 }
142
143 fn request_1d_array(&mut self, n: u32) {
144 self.base.request_1d_array(n);
145 }
146 fn request_2d_array(&mut self, n: u32) {
147 self.base.request_2d_array(n);
148 }
149 fn get_1d_array(&mut self, n: u32) -> Option<Vec<Float>> {
150 return self.base.get_1d_array(n);
151 }
152 fn get_2d_array(&mut self, n: u32) -> Option<Vec<Vector2f>> {
153 return self.base.get_2d_array(n);
154 }
155
156 fn clone_with_seed(&self, _seed: u32) -> Arc<RwLock<dyn Sampler>> {
157 return Arc::new(RwLock::new(self.clone()));
158 }
159
160 fn get_samples_per_pixel(&self) -> u32 {
161 return self.base.base.samples_per_pixel;
162 }
163}
164
165unsafe impl Sync for SobolSampler {}
166
167impl GlobalSampler for SobolSampler {
168 fn get_index_for_sample(&self, sample_num: i64) -> i64 {
169 let p = self.base.base.current_pixel - self.sample_bounds.min;
170 return sobol_interval_to_index(self.log2_resolution, sample_num as u64, &p) as i64;
171 }
172 fn sample_dimension(&self, index: i64, dim: u32) -> Float {
173 let mut s = sobol_sample(index, dim, 0);
174 if dim == 0 || dim == 1 {
176 s = s * (self.resolution as Float) + self.sample_bounds.min[dim as usize] as Float;
177 s = Float::clamp(
178 s - self.base.base.current_pixel[dim as usize] as Float,
179 0.0,
180 ONE_MINUS_EPSILON,
181 );
182 s = Float::fract(s);
183 }
184 return s;
185 }
186
187 fn get_base(&mut self) -> &mut BaseGlobalSampler {
188 return &mut self.base;
189 }
190}
191
192pub fn create_sobol_sampler(
193 params: &ParamSet,
194 sample_bounds: &Bounds2i,
195) -> Result<Arc<RwLock<dyn Sampler>>, PbrtError> {
196 let mut nsamp = params.find_one_int("pixelsamples", 16) as u32;
197 {
198 let options = PbrtOptions::get();
199 if options.quick_render {
200 nsamp = 1;
201 }
202 }
203 return Ok(Arc::new(RwLock::new(SobolSampler::new(
204 nsamp,
205 sample_bounds,
206 ))));
207}