Blender V5.0
kernel/sample/tabulated_sobol.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#include "kernel/globals.h"
6
8
9#include "util/hash.h"
10
11#pragma once
13
16 const uint dimension,
17 const uint seed)
18{
19 const uint sample_count = kernel_data.integrator.tabulated_sobol_sequence_size;
20
21 /* Shuffle the pattern order and sample index to decorrelate
22 * dimensions and make the most of the finite patterns we have.
23 * The funky sample mask stuff is to ensure that we only shuffle
24 * *within* the current sample pattern, which is necessary to avoid
25 * early repeat pattern use. */
26 const uint pattern_i = hash_shuffle_uint(dimension, NUM_TAB_SOBOL_PATTERNS, seed);
27 /* sample_count should always be a power of two, so this results in a mask. */
28 const uint sample_mask = sample_count - 1;
29 const uint sample_shuffled = nested_uniform_scramble(sample,
30 hash_wang_seeded_uint(dimension, seed));
31 sample = (sample & ~sample_mask) | (sample_shuffled & sample_mask);
32
33 return ((pattern_i * sample_count) + sample) % (sample_count * NUM_TAB_SOBOL_PATTERNS);
34}
35
37 const uint sample,
38 const uint rng_hash,
39 const uint dimension)
40{
41 uint seed = rng_hash;
42
43 /* Use the same sample sequence seed for all pixels when using
44 * scrambling distance. */
45 if (kernel_data.integrator.scrambling_distance < 1.0f) {
46 seed = kernel_data.integrator.seed;
47 }
48
49 /* Fetch the sample. */
50 const uint index = tabulated_sobol_shuffled_sample_index(kg, sample, dimension, seed);
51 float x = kernel_data_fetch(sample_pattern_lut, index * NUM_TAB_SOBOL_DIMENSIONS);
52
53 /* Do limited Cranley-Patterson rotation when using scrambling distance. */
54 if (kernel_data.integrator.scrambling_distance < 1.0f) {
55 const float jitter_x = hash_wang_seeded_float(dimension, rng_hash) *
56 kernel_data.integrator.scrambling_distance;
57 x += jitter_x;
58 x -= floorf(x);
59 }
60
61 return x;
62}
63
65 const uint sample,
66 const uint rng_hash,
67 const uint dimension)
68{
69 uint seed = rng_hash;
70
71 /* Use the same sample sequence seed for all pixels when using
72 * scrambling distance. */
73 if (kernel_data.integrator.scrambling_distance < 1.0f) {
74 seed = kernel_data.integrator.seed;
75 }
76
77 /* Fetch the sample. */
78 const uint index = tabulated_sobol_shuffled_sample_index(kg, sample, dimension, seed);
79 float x = kernel_data_fetch(sample_pattern_lut, index * NUM_TAB_SOBOL_DIMENSIONS);
80 float y = kernel_data_fetch(sample_pattern_lut, index * NUM_TAB_SOBOL_DIMENSIONS + 1);
81
82 /* Do limited Cranley-Patterson rotation when using scrambling distance. */
83 if (kernel_data.integrator.scrambling_distance < 1.0f) {
84 const float jitter_x = hash_wang_seeded_float(dimension, rng_hash) *
85 kernel_data.integrator.scrambling_distance;
86 const float jitter_y = hash_wang_seeded_float(dimension, rng_hash ^ 0xca0e1151) *
87 kernel_data.integrator.scrambling_distance;
88 x += jitter_x;
89 y += jitter_y;
90 x -= floorf(x);
91 y -= floorf(y);
92 }
93
94 return make_float2(x, y);
95}
96
98 const uint sample,
99 const uint rng_hash,
100 const uint dimension)
101{
102 uint seed = rng_hash;
103
104 /* Use the same sample sequence seed for all pixels when using
105 * scrambling distance. */
106 if (kernel_data.integrator.scrambling_distance < 1.0f) {
107 seed = kernel_data.integrator.seed;
108 }
109
110 /* Fetch the sample. */
111 const uint index = tabulated_sobol_shuffled_sample_index(kg, sample, dimension, seed);
112 float x = kernel_data_fetch(sample_pattern_lut, index * NUM_TAB_SOBOL_DIMENSIONS);
113 float y = kernel_data_fetch(sample_pattern_lut, index * NUM_TAB_SOBOL_DIMENSIONS + 1);
114 float z = kernel_data_fetch(sample_pattern_lut, index * NUM_TAB_SOBOL_DIMENSIONS + 2);
115
116 /* Do limited Cranley-Patterson rotation when using scrambling distance. */
117 if (kernel_data.integrator.scrambling_distance < 1.0f) {
118 const float jitter_x = hash_wang_seeded_float(dimension, rng_hash) *
119 kernel_data.integrator.scrambling_distance;
120 const float jitter_y = hash_wang_seeded_float(dimension, rng_hash ^ 0xca0e1151) *
121 kernel_data.integrator.scrambling_distance;
122 const float jitter_z = hash_wang_seeded_float(dimension, rng_hash ^ 0xbf604c5a) *
123 kernel_data.integrator.scrambling_distance;
124 x += jitter_x;
125 y += jitter_y;
126 z += jitter_z;
127 x -= floorf(x);
128 y -= floorf(y);
129 z -= floorf(z);
130 }
131
132 return make_float3(x, y, z);
133}
134
136 const uint sample,
137 const uint rng_hash,
138 const uint dimension)
139{
140 uint seed = rng_hash;
141
142 /* Use the same sample sequence seed for all pixels when using
143 * scrambling distance. */
144 if (kernel_data.integrator.scrambling_distance < 1.0f) {
145 seed = kernel_data.integrator.seed;
146 }
147
148 /* Fetch the sample. */
149 const uint index = tabulated_sobol_shuffled_sample_index(kg, sample, dimension, seed);
150 float x = kernel_data_fetch(sample_pattern_lut, index * NUM_TAB_SOBOL_DIMENSIONS);
151 float y = kernel_data_fetch(sample_pattern_lut, index * NUM_TAB_SOBOL_DIMENSIONS + 1);
152 float z = kernel_data_fetch(sample_pattern_lut, index * NUM_TAB_SOBOL_DIMENSIONS + 2);
153 float w = kernel_data_fetch(sample_pattern_lut, index * NUM_TAB_SOBOL_DIMENSIONS + 3);
154
155 /* Do limited Cranley-Patterson rotation when using scrambling distance. */
156 if (kernel_data.integrator.scrambling_distance < 1.0f) {
157 const float jitter_x = hash_wang_seeded_float(dimension, rng_hash) *
158 kernel_data.integrator.scrambling_distance;
159 const float jitter_y = hash_wang_seeded_float(dimension, rng_hash ^ 0xca0e1151) *
160 kernel_data.integrator.scrambling_distance;
161 const float jitter_z = hash_wang_seeded_float(dimension, rng_hash ^ 0xbf604c5a) *
162 kernel_data.integrator.scrambling_distance;
163 const float jitter_w = hash_wang_seeded_float(dimension, rng_hash ^ 0x99634d1d) *
164 kernel_data.integrator.scrambling_distance;
165 x += jitter_x;
166 y += jitter_y;
167 z += jitter_z;
168 w += jitter_w;
169 x -= floorf(x);
170 y -= floorf(y);
171 z -= floorf(z);
172 w -= floorf(w);
173 }
174
175 return make_float4(x, y, z, w);
176}
177
unsigned int uint
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
Definition btQuadWord.h:117
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
static unsigned long seed
Definition btSoftBody.h:39
ccl_device_inline uint nested_uniform_scramble(const uint i, const uint seed)
#define kernel_data
#define kernel_data_fetch(name, index)
#define NUM_TAB_SOBOL_DIMENSIONS
const ThreadKernelGlobalsCPU * KernelGlobals
#define NUM_TAB_SOBOL_PATTERNS
#define CCL_NAMESPACE_END
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
ccl_device_inline uint hash_wang_seeded_uint(uint i, const uint seed)
Definition hash.h:557
ccl_device_inline uint hash_shuffle_uint(uint i, const uint length, const uint seed)
Definition hash.h:591
ccl_device_inline float hash_wang_seeded_float(const uint i, const uint seed)
Definition hash.h:567
CCL_NAMESPACE_BEGIN ccl_device uint tabulated_sobol_shuffled_sample_index(KernelGlobals kg, uint sample, const uint dimension, const uint seed)
ccl_device float2 tabulated_sobol_sample_2D(KernelGlobals kg, const uint sample, const uint rng_hash, const uint dimension)
ccl_device float4 tabulated_sobol_sample_4D(KernelGlobals kg, const uint sample, const uint rng_hash, const uint dimension)
ccl_device float3 tabulated_sobol_sample_3D(KernelGlobals kg, const uint sample, const uint rng_hash, const uint dimension)
ccl_device float tabulated_sobol_sample_1D(KernelGlobals kg, const uint sample, const uint rng_hash, const uint dimension)
#define floorf
#define ccl_device
#define make_float2
#define make_float4