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:
Nathan Vegdahl 2020-04-22 18:38:05 +09:00
parent aecff883ab
commit 22b7151919
2 changed files with 17 additions and 9 deletions

View File

@ -374,7 +374,7 @@ pub struct LightPath {
sampling_seed: u32,
pixel_co: (u32, u32),
sample_number: u32, // Which sample in the LDS sequence this is.
dim_offset: Cell<u32>,
dim_offset: u32,
time: f32,
wavelength: f32,
@ -407,7 +407,7 @@ impl LightPath {
sampling_seed: sampling_seed,
pixel_co: pixel_co,
sample_number: sample_number,
dim_offset: Cell::new(6),
dim_offset: 0,
time: time,
wavelength: wavelength,
@ -430,9 +430,14 @@ impl LightPath {
)
}
fn next_lds_samp(&self) -> f32 {
let dimension = self.dim_offset.get();
self.dim_offset.set(dimension + 1);
fn next_lds_sequence(&mut self) {
self.dim_offset = 0;
self.sampling_seed += 1;
}
fn next_lds_samp(&mut self) -> f32 {
let dimension = self.dim_offset;
self.dim_offset += 1;
get_sample(
dimension,
self.sample_number,
@ -481,6 +486,7 @@ impl LightPath {
self.light_attenuation /= self.closure_sample_pdf;
// Prepare light ray
self.next_lds_sequence();
let light_n = self.next_lds_samp();
let light_uvw = (
self.next_lds_samp(),
@ -599,6 +605,7 @@ impl LightPath {
// Sample closure
let (dir, filter, pdf) = {
self.next_lds_sequence();
let u = self.next_lds_samp();
let v = self.next_lds_samp();
closure.sample(
@ -701,10 +708,7 @@ fn get_sample(dimension: u32, i: u32, pixel_co: (u32, u32), seed: u32) -> f32 {
match dimension {
d if d < sobol::MAX_DIMENSION as u32 => {
// Sobol sampling.
// We skip the first 4 samples, because that mitigates some poor
// sampling at low sample counts like 16.
sobol::sample(d, i + 4, seed)
// halton::sample(d, i + seed)
sobol::sample(d, i, seed)
}
d => {
// Random sampling.

View File

@ -15,8 +15,12 @@ include!(concat!(env!("OUT_DIR"), "/vectors.inc"));
/// parameter exceeds 2^16-1, the sample set will start repeating.
#[inline]
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 scramble = hash(dimension ^ seed, 2);
let sobol = lk_scramble(sobol_u32_rev(dimension, shuffled_rev_index), scramble).reverse_bits();
u32_to_0_1_f32(sobol)
}