Implement screen-space blue-noise sampling properly.

This commit is contained in:
Nathan Vegdahl 2022-07-21 03:41:23 -07:00
parent 83b48f722d
commit ec9a121e72
2 changed files with 51 additions and 6 deletions

View File

@ -17,8 +17,10 @@ use crate::{
image::Image,
math::{probit, upper_power_of_two, Float4},
mis::power_heuristic,
morton,
ray::{Ray, RayBatch},
scene::{Scene, SceneLightSample},
scramble::z_scramble,
surface,
timer::Timer,
tracer::Tracer,
@ -246,8 +248,8 @@ impl<'a> Renderer<'a> {
// 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
// the samplers themselves.
let si_offset = crate::scramble::owen(hilbert::xy2i(x, y), self.seed)
.wrapping_mul(self.spp as u32);
let si_offset =
z_scramble(morton::xy2i(x, y), self.seed).wrapping_mul(self.spp as u32);
for si in 0..self.spp {
let si = (si as u32).wrapping_add(si_offset);

View File

@ -4,11 +4,54 @@ use crate::hash::hash_u32;
pub fn owen(n: u32, seed: u32) -> u32 {
let mut result = n;
for b in 0..31 {
let mask = (!0) << (b + 1);
result ^= hash_u32(n & mask, seed) & (1 << b);
for i in 0..32 {
let mask = if i < 31 { (!0) << (i + 1) } else { 0 };
result ^= hash_u32(n & mask, seed) & (1 << i);
}
result ^= hash_u32(0, seed) & (1 << 31); // Handle highest bit.
result
}
/// Performs z-scrambling from the paper "Screen-Space Blue-Noise
/// Diffusion of Monte Carlo Sampling Error via Hierarchical Ordering
/// of Pixels" by Ahmed et al., except using a more complete and
/// efficient algorithm based on the Owen scrambling function above.
pub fn z_scramble(n: u32, seed: u32) -> u32 {
let mut result = 0;
for i in 0..16 {
let mask = if i < 15 { (!0) << ((i + 1) * 2) } else { 0 };
let entry = (hash_u32(n & mask, seed) % 24) as usize;
let cell = ((n >> (i * 2)) & 0b11) as usize;
result |= (Z_TABLE[entry][cell] as u32) << (i * 2);
}
result
}
const Z_TABLE: &[[u8; 4]; 24] = &[
[0, 1, 2, 3],
[0, 1, 3, 2],
[0, 2, 1, 3],
[0, 2, 3, 1],
[0, 3, 1, 2],
[0, 3, 2, 1],
[1, 0, 2, 3],
[1, 0, 3, 2],
[1, 2, 0, 3],
[1, 2, 3, 0],
[1, 3, 0, 2],
[1, 3, 2, 0],
[2, 0, 1, 3],
[2, 0, 3, 1],
[2, 1, 0, 3],
[2, 1, 3, 0],
[2, 3, 0, 1],
[2, 3, 1, 0],
[3, 0, 1, 2],
[3, 0, 2, 1],
[3, 1, 0, 2],
[3, 1, 2, 0],
[3, 2, 0, 1],
[3, 2, 1, 0],
];