Use independent Sobol sequences for different sets of dimensions.
This reduces correlation artifacts, while preserving good convergence for the most part.
This commit is contained in:
parent
aecff883ab
commit
22b7151919
|
@ -374,7 +374,7 @@ pub struct LightPath {
|
||||||
sampling_seed: u32,
|
sampling_seed: u32,
|
||||||
pixel_co: (u32, u32),
|
pixel_co: (u32, u32),
|
||||||
sample_number: u32, // Which sample in the LDS sequence this is.
|
sample_number: u32, // Which sample in the LDS sequence this is.
|
||||||
dim_offset: Cell<u32>,
|
dim_offset: u32,
|
||||||
time: f32,
|
time: f32,
|
||||||
wavelength: f32,
|
wavelength: f32,
|
||||||
|
|
||||||
|
@ -407,7 +407,7 @@ impl LightPath {
|
||||||
sampling_seed: sampling_seed,
|
sampling_seed: sampling_seed,
|
||||||
pixel_co: pixel_co,
|
pixel_co: pixel_co,
|
||||||
sample_number: sample_number,
|
sample_number: sample_number,
|
||||||
dim_offset: Cell::new(6),
|
dim_offset: 0,
|
||||||
time: time,
|
time: time,
|
||||||
wavelength: wavelength,
|
wavelength: wavelength,
|
||||||
|
|
||||||
|
@ -430,9 +430,14 @@ impl LightPath {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_lds_samp(&self) -> f32 {
|
fn next_lds_sequence(&mut self) {
|
||||||
let dimension = self.dim_offset.get();
|
self.dim_offset = 0;
|
||||||
self.dim_offset.set(dimension + 1);
|
self.sampling_seed += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn next_lds_samp(&mut self) -> f32 {
|
||||||
|
let dimension = self.dim_offset;
|
||||||
|
self.dim_offset += 1;
|
||||||
get_sample(
|
get_sample(
|
||||||
dimension,
|
dimension,
|
||||||
self.sample_number,
|
self.sample_number,
|
||||||
|
@ -481,6 +486,7 @@ impl LightPath {
|
||||||
self.light_attenuation /= self.closure_sample_pdf;
|
self.light_attenuation /= self.closure_sample_pdf;
|
||||||
|
|
||||||
// Prepare light ray
|
// Prepare light ray
|
||||||
|
self.next_lds_sequence();
|
||||||
let light_n = self.next_lds_samp();
|
let light_n = self.next_lds_samp();
|
||||||
let light_uvw = (
|
let light_uvw = (
|
||||||
self.next_lds_samp(),
|
self.next_lds_samp(),
|
||||||
|
@ -599,6 +605,7 @@ impl LightPath {
|
||||||
|
|
||||||
// Sample closure
|
// Sample closure
|
||||||
let (dir, filter, pdf) = {
|
let (dir, filter, pdf) = {
|
||||||
|
self.next_lds_sequence();
|
||||||
let u = self.next_lds_samp();
|
let u = self.next_lds_samp();
|
||||||
let v = self.next_lds_samp();
|
let v = self.next_lds_samp();
|
||||||
closure.sample(
|
closure.sample(
|
||||||
|
@ -701,10 +708,7 @@ fn get_sample(dimension: u32, i: u32, pixel_co: (u32, u32), seed: u32) -> f32 {
|
||||||
match dimension {
|
match dimension {
|
||||||
d if d < sobol::MAX_DIMENSION as u32 => {
|
d if d < sobol::MAX_DIMENSION as u32 => {
|
||||||
// Sobol sampling.
|
// Sobol sampling.
|
||||||
// We skip the first 4 samples, because that mitigates some poor
|
sobol::sample(d, i, seed)
|
||||||
// sampling at low sample counts like 16.
|
|
||||||
sobol::sample(d, i + 4, seed)
|
|
||||||
// halton::sample(d, i + seed)
|
|
||||||
}
|
}
|
||||||
d => {
|
d => {
|
||||||
// Random sampling.
|
// Random sampling.
|
||||||
|
|
|
@ -15,8 +15,12 @@ include!(concat!(env!("OUT_DIR"), "/vectors.inc"));
|
||||||
/// parameter exceeds 2^16-1, the sample set will start repeating.
|
/// parameter exceeds 2^16-1, the sample set will start repeating.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn sample(dimension: u32, index: u32, seed: u32) -> f32 {
|
pub fn sample(dimension: u32, index: u32, seed: u32) -> f32 {
|
||||||
|
// This index shuffling approach is due to Brent Burley, and is
|
||||||
|
// what allows us to create statistically independent Sobol sequences.
|
||||||
let shuffled_rev_index = lk_scramble(index.reverse_bits(), hash(seed, 2));
|
let shuffled_rev_index = lk_scramble(index.reverse_bits(), hash(seed, 2));
|
||||||
|
|
||||||
let scramble = hash(dimension ^ seed, 2);
|
let scramble = hash(dimension ^ seed, 2);
|
||||||
|
|
||||||
let sobol = lk_scramble(sobol_u32_rev(dimension, shuffled_rev_index), scramble).reverse_bits();
|
let sobol = lk_scramble(sobol_u32_rev(dimension, shuffled_rev_index), scramble).reverse_bits();
|
||||||
u32_to_0_1_f32(sobol)
|
u32_to_0_1_f32(sobol)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user