Blender  V3.3
pattern.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright 2011-2022 Blender Foundation */
3 
4 #pragma once
5 
6 #include "kernel/sample/jitter.h"
7 #include "util/hash.h"
8 
10 
11 /* Pseudo random numbers, uncomment this for debugging correlations. Only run
12  * this single threaded on a CPU for repeatable results. */
13 //#define __DEBUG_CORRELATION__
14 
15 /* High Dimensional Sobol.
16  *
17  * Multidimensional sobol with generator matrices. Dimension 0 and 1 are equal
18  * to classic Van der Corput and Sobol sequences. */
19 
20 #ifdef __SOBOL__
21 
22 /* Skip initial numbers that for some dimensions have clear patterns that
23  * don't cover the entire sample space. Ideally we would have a better
24  * progressive pattern that doesn't suffer from this problem, because even
25  * with this offset some dimensions are quite poor.
26  */
27 # define SOBOL_SKIP 64
28 
29 ccl_device uint sobol_dimension(KernelGlobals kg, int index, int dimension)
30 {
31  uint result = 0;
32  uint i = index + SOBOL_SKIP;
33  for (int j = 0, x; (x = find_first_set(i)); i >>= x) {
34  j += x;
35  result ^= __float_as_uint(kernel_data_fetch(sample_pattern_lut, 32 * dimension + j - 1));
36  }
37  return result;
38 }
39 
40 #endif /* __SOBOL__ */
41 
43  uint rng_hash,
44  int sample,
45  int dimension)
46 {
47 #ifdef __DEBUG_CORRELATION__
48  return (float)drand48();
49 #endif
50 
51 #ifdef __SOBOL__
52  if (kernel_data.integrator.sampling_pattern == SAMPLING_PATTERN_PMJ)
53 #endif
54  {
55  return pmj_sample_1D(kg, sample, rng_hash, dimension);
56  }
57 
58 #ifdef __SOBOL__
59  /* Sobol sequence value using direction vectors. */
60  uint result = sobol_dimension(kg, sample, dimension);
61  float r = (float)result * (1.0f / (float)0xFFFFFFFF);
62 
63  /* Cranly-Patterson rotation using rng seed */
64  float shift;
65 
66  /* Hash rng with dimension to solve correlation issues.
67  * See T38710, T50116.
68  */
69  uint tmp_rng = cmj_hash_simple(dimension, rng_hash);
70  shift = tmp_rng * (kernel_data.integrator.scrambling_distance / (float)0xFFFFFFFF);
71 
72  return r + shift - floorf(r + shift);
73 #endif
74 }
75 
77  uint rng_hash,
78  int sample,
79  int dimension,
80  ccl_private float *fx,
81  ccl_private float *fy)
82 {
83 #ifdef __DEBUG_CORRELATION__
84  *fx = (float)drand48();
85  *fy = (float)drand48();
86  return;
87 #endif
88 
89 #ifdef __SOBOL__
90  if (kernel_data.integrator.sampling_pattern == SAMPLING_PATTERN_PMJ)
91 #endif
92  {
93  pmj_sample_2D(kg, sample, rng_hash, dimension, fx, fy);
94 
95  return;
96  }
97 
98 #ifdef __SOBOL__
99  /* Sobol. */
100  *fx = path_rng_1D(kg, rng_hash, sample, dimension);
101  *fy = path_rng_1D(kg, rng_hash, sample, dimension + 1);
102 #endif
103 }
104 
111 {
112  n = (n << 13U) ^ n;
113  n = n * (n * n * 15731U + 789221U) + 1376312589U;
114 
115  return n;
116 }
117 
124 {
125  const uint qx = 1103515245U * ((x >> 1U) ^ (y));
126  const uint qy = 1103515245U * ((y >> 1U) ^ (x));
127  const uint n = 1103515245U * ((qx) ^ (qy >> 3U));
128 
129  return n;
130 }
131 
133  const int sample,
134  const int x,
135  const int y)
136 {
137  const uint rng_hash = hash_iqnt2d(x, y) ^ kernel_data.integrator.seed;
138 
139 #ifdef __DEBUG_CORRELATION__
140  srand48(rng_hash + sample);
141 #else
142  (void)sample;
143 #endif
144 
145  return rng_hash;
146 }
147 
149 {
150  if (pattern == SAMPLING_PATTERN_PMJ) {
151  /* See Section 10.2.1, "Progressive Multi-Jittered Sample Sequences", Christensen et al.
152  * We can use this to get divide sample sequence into two classes for easier variance
153  * estimation. */
154  return popcount(uint(sample) & 0xaaaaaaaa) & 1;
155  }
156  else {
157  /* TODO(Stefan): Are there reliable ways of dividing CMJ and Sobol into two classes? */
158  return sample & 0x1;
159  }
160 }
161 
typedef float(TangentPoint)[2]
unsigned int uint
Definition: BLI_sys_types.h:67
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
#define ccl_device_forceinline
Definition: cuda/compat.h:35
#define ccl_device
Definition: cuda/compat.h:32
#define ccl_private
Definition: cuda/compat.h:48
#define ccl_device_inline
Definition: cuda/compat.h:34
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
#define kernel_data
const KernelGlobalsCPU *ccl_restrict KernelGlobals
#define kernel_data_fetch(name, index)
SyclQueue void void size_t num_bytes void
ccl_device void pmj_sample_2D(KernelGlobals kg, uint sample, uint rng_hash, uint dimension, ccl_private float *x, ccl_private float *y)
ccl_device float pmj_sample_1D(KernelGlobals kg, uint sample, uint rng_hash, uint dimension)
ccl_device_inline uint cmj_hash_simple(uint i, uint p)
@ SAMPLING_PATTERN_PMJ
Definition: kernel/types.h:180
#define floorf(x)
Definition: metal/compat.h:224
ccl_device_inline bool sample_is_even(int pattern, int sample)
Definition: pattern.h:148
ccl_device_inline uint hash_iqint1(uint n)
Definition: pattern.h:110
ccl_device_inline uint hash_iqnt2d(const uint x, const uint y)
Definition: pattern.h:123
CCL_NAMESPACE_BEGIN ccl_device_forceinline float path_rng_1D(KernelGlobals kg, uint rng_hash, int sample, int dimension)
Definition: pattern.h:42
ccl_device_forceinline void path_rng_2D(KernelGlobals kg, uint rng_hash, int sample, int dimension, ccl_private float *fx, ccl_private float *fy)
Definition: pattern.h:76
ccl_device_inline uint path_rng_hash_init(KernelGlobals kg, const int sample, const int x, const int y)
Definition: pattern.h:132
ccl_device_inline uint __float_as_uint(float f)
Definition: util/math.h:263
ccl_device_inline uint popcount(uint x)
Definition: util/math.h:794
ccl_device_inline uint find_first_set(uint x)
Definition: util/math.h:853