Fix two issues in the previous implementation: * Only power-of-two prefixes were progressively stratified, not suffixes. This resulted in unnecessarily increased noise when using non-power-of-two sample counts. * In order to try to get away with just a single sample pattern, the code used a combination of sample index shuffling and Cranley-Patterson rotation. Index shuffling is normally fine, but due to the sample patterns themselves not being quite right (as described above) this actually resulted in additional increased noise. Cranley-Patterson, on the other hand, always increases noise with randomized (t,s) nets like PMJ02, and should be avoided with these kinds of sequences. Addressed with the following changes: * Replace the sample pattern generation code with a much simpler algorithm recently published in the paper "Stochastic Generation of (t, s) Sample Sequences". This new implementation is easier to verify, produces fully progressively stratified PMJ02, and is *far* faster than the previous code, being O(N) in the number of samples generated. * It keeps the sample index shuffling, which works correctly now due to the improved sample patterns. But it now uses a newer high-quality hash instead of the original Laine-Karras hash. * The scrambling distance feature cannot (to my knowledge) be implemented with any decorrelation strategy other than Cranley-Patterson, so Cranley-Patterson is still used when that feature is enabled. But it is now disabled otherwise, since it increases noise. * In place of Cranley-Patterson, multiple independent patterns are generated and randomly chosen for different pixels and dimensions as described in the original PMJ paper. In this patch, the pattern selection is done via hash-based shuffling to ensure there are no repeats within a single pixel until all patterns have been used. The combination of these fixes brings the quality of Cycles' PMJ sampler in line with the previously submitted Sobol-Burley sampler in D15679. They are essentially indistinguishable in terms of quality/noise, which is expected since they are both randomized (0,2) sequences. Differential Revision: https://developer.blender.org/D15746
36 lines
799 B
C++
36 lines
799 B
C++
/* SPDX-License-Identifier: Apache-2.0
|
|
* Copyright 2011-2022 Blender Foundation */
|
|
|
|
#pragma once
|
|
|
|
#include "util/types.h"
|
|
|
|
CCL_NAMESPACE_BEGIN
|
|
|
|
/*
|
|
* Performs base-2 Owen scrambling on a reversed-bit unsigned integer.
|
|
*
|
|
* This is equivalent to the Laine-Karras permutation, but much higher
|
|
* quality. See https://psychopath.io/post/2021_01_30_building_a_better_lk_hash
|
|
*/
|
|
ccl_device_inline uint reversed_bit_owen(uint n, uint seed)
|
|
{
|
|
n ^= n * 0x3d20adea;
|
|
n += seed;
|
|
n *= (seed >> 16) | 1;
|
|
n ^= n * 0x05526c56;
|
|
n ^= n * 0x53a22864;
|
|
|
|
return n;
|
|
}
|
|
|
|
/*
|
|
* Performs base-2 Owen scrambling on an unsigned integer.
|
|
*/
|
|
ccl_device_inline uint nested_uniform_scramble(uint i, uint seed)
|
|
{
|
|
return reverse_integer_bits(reversed_bit_owen(reverse_integer_bits(i), seed));
|
|
}
|
|
|
|
CCL_NAMESPACE_END
|