Use unscrambled Van der Corput for sampling time dimension.
This gives notably better results at powers of two. Also experimenting with Halton bases 3 and 4 for DoF.
This commit is contained in:
parent
76781eb639
commit
aba177c536
105
src/renderer.rs
105
src/renderer.rs
|
@ -232,16 +232,22 @@ impl<'a> Renderer<'a> {
|
||||||
// to work well with golden-ratio sampling. Since we only use sobol
|
// to work well with golden-ratio sampling. Since we only use sobol
|
||||||
// and golden ratio sampling, we do this up-front here rather than in
|
// and golden ratio sampling, we do this up-front here rather than in
|
||||||
// the samplers themselves.
|
// the samplers themselves.
|
||||||
let si_offset =
|
let pixel_offset = owen4_fast(morton::encode(x, y), self.seed);
|
||||||
owen4_fast(morton::encode(x, y), self.seed).wrapping_mul(self.spp as u32);
|
let si_offset = pixel_offset.wrapping_mul(self.spp as u32);
|
||||||
|
|
||||||
for si in 0..(self.spp as u32) {
|
for si in 0..(self.spp as u32) {
|
||||||
let mut sample_gen = SampleGen::new(si_offset + si, self.seed);
|
let sii = si_offset.wrapping_add(si);
|
||||||
|
let mut sample_gen = SampleGen::new(sii, self.seed);
|
||||||
|
|
||||||
// Raw sample numbers.
|
// Raw sample numbers.
|
||||||
let d0 = golden_ratio_sample(si.wrapping_add(si_offset));
|
let d0 = golden_ratio_sample(
|
||||||
let [d1, d2, d3, _] = sample_gen.next_dims();
|
sii.wrapping_add(rrand::mix32_seed(self.seed, 1111)),
|
||||||
sample_gen.inc_padding();
|
);
|
||||||
|
let d1 = van_der_corput(sii, rrand::mix32_seed(self.seed, 2222));
|
||||||
|
let d2 = halton_3(sii, rrand::mix32_seed(self.seed, 3333));
|
||||||
|
let d3 = halton_5(sii, rrand::mix32_seed(self.seed, 4444));
|
||||||
|
// let [d2, d3, _, _] = sample_gen.next_dims();
|
||||||
|
// sample_gen.inc_padding();
|
||||||
let [d4, d5, _, _] = sample_gen.next_dims();
|
let [d4, d5, _, _] = sample_gen.next_dims();
|
||||||
sample_gen.inc_padding();
|
sample_gen.inc_padding();
|
||||||
|
|
||||||
|
@ -584,7 +590,92 @@ impl SampleGen {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Golden ratio sampler.
|
/// The Van der Corput sequence.
|
||||||
|
///
|
||||||
|
/// NOTE: use this for motion blur, because the jittering introduced by
|
||||||
|
/// Owen Scrambling in the main sampler actually causes banding artifacts
|
||||||
|
/// at the sample cell borders, and actually *increases* noise.
|
||||||
|
fn van_der_corput(i: u32, seed: u32) -> f32 {
|
||||||
|
use sobol_burley::parts::u32_to_f32_norm;
|
||||||
|
u32_to_f32_norm(i.reverse_bits().wrapping_add(seed))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Halton base 3.
|
||||||
|
fn halton_3(mut i: u32, seed: u32) -> f32 {
|
||||||
|
const BASE: u32 = 3;
|
||||||
|
const POW: u32 = 13;
|
||||||
|
const TOP_BASE: u32 = {
|
||||||
|
let mut b = 1;
|
||||||
|
let mut i = 0;
|
||||||
|
while i < POW {
|
||||||
|
b *= BASE;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
b
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut result = 0;
|
||||||
|
for _ in 0..POW {
|
||||||
|
result *= BASE;
|
||||||
|
let next = i / BASE;
|
||||||
|
result += i - (next * BASE);
|
||||||
|
i = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = ((result as u64 + seed as u64) % TOP_BASE as u64) as u32;
|
||||||
|
|
||||||
|
result as f32 * (1.0 / TOP_BASE as f32)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Halton base 5.
|
||||||
|
fn halton_5(mut i: u32, seed: u32) -> f32 {
|
||||||
|
const BASE: u32 = 5;
|
||||||
|
const POW: u32 = 13;
|
||||||
|
const TOP_BASE: u32 = {
|
||||||
|
let mut b = 1;
|
||||||
|
let mut i = 0;
|
||||||
|
while i < POW {
|
||||||
|
b *= BASE;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
b
|
||||||
|
};
|
||||||
|
const ORDER: [u32; 5] = [0, 3, 1, 4, 2];
|
||||||
|
|
||||||
|
let mut result = 0;
|
||||||
|
for _ in 0..POW {
|
||||||
|
result *= BASE;
|
||||||
|
let next = i / BASE;
|
||||||
|
result += ORDER[(i - (next * BASE)) as usize];
|
||||||
|
i = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = ((result as u64 + seed as u64) % TOP_BASE as u64) as u32;
|
||||||
|
|
||||||
|
result as f32 * (1.0 / TOP_BASE as f32)
|
||||||
|
}
|
||||||
|
|
||||||
|
// fn next_power_of_three(mut n: u64) -> u64 {
|
||||||
|
// n = n.saturating_sub(1);
|
||||||
|
// let mut i = 1;
|
||||||
|
// while n > 0 {
|
||||||
|
// n /= 3;
|
||||||
|
// i *= 3;
|
||||||
|
// }
|
||||||
|
// i
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn next_power_of_five(mut n: u64) -> u64 {
|
||||||
|
// n = n.saturating_sub(1);
|
||||||
|
// let mut i = 1;
|
||||||
|
// while n > 0 {
|
||||||
|
// n /= 5;
|
||||||
|
// i *= 5;
|
||||||
|
// }
|
||||||
|
// i
|
||||||
|
// }
|
||||||
|
|
||||||
|
/// The golden ratio sequence.
|
||||||
///
|
///
|
||||||
// NOTE: use this for the wavelength dimension, because
|
// NOTE: use this for the wavelength dimension, because
|
||||||
// due to the nature of hero wavelength sampling this ends up
|
// due to the nature of hero wavelength sampling this ends up
|
||||||
|
|
Loading…
Reference in New Issue
Block a user