pbrt_r3/samplers/
sobol.rs

1use 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    //dimension: u32,
10    //dimension_1d: u32,
11    //dimension_2d: u32,
12    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            //dimension: 0,
25            //dimension_1d: 0,
26            //dimension_2d: 0,
27            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.dimension_1d = 0;
41        //self.dimension_2d = 0;
42        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        // Compute 1D array samples for _GlobalSampler_
48        {
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        // Compute 2D array samples for _GlobalSampler_
61        {
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.dimension_1d = 0;
81        //self.dimension_2d = 0;
82        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.dimension_1d = 0;
90        //self.dimension_2d = 0;
91        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        //if self.dimension_1d >= BaseGlobalSampler::array_start_dim
106        //    && self.dimension_1d < self.base.array_end_dim
107        //{
108        //    self.dimension_1d = self.base.array_end_dim;
109        //}
110        //let d = self.dimension_1d;
111        //let x = self.sample_dimension(self.base.interval_sample_index, d);
112        //self.dimension_1d += 1;
113        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        //println!("d:{}/{}", d, self.base.array_end_dim);
124        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        //if self.dimension_2d + 1 >= BaseGlobalSampler::array_start_dim
130        //    && self.dimension_2d < self.base.array_end_dim
131        //{
132        //    self.dimension_2d = self.base.array_end_dim;
133        //}
134        //let d = self.dimension_2d;
135        //println!("d:{}/{}", d, self.base.array_end_dim);
136        //let x = self.sample_dimension(self.base.interval_sample_index, d);
137        //let y = self.sample_dimension(self.base.interval_sample_index, d + 1);
138        //let p = Point2f::new(x, y);
139        //self.dimension_2d += 2;
140        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        // Remap Sobol$'$ dimensions used for pixel samples
175        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}