Blender  V3.3
eevee_sampling.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2021 Blender Foundation.
3  */
4 
11 #include "BLI_rand.h"
12 
13 #include "eevee_instance.hh"
14 #include "eevee_sampling.hh"
15 
16 namespace blender::eevee {
17 
18 /* -------------------------------------------------------------------- */
23 {
24  sample_count_ = inst_.is_viewport() ? scene->eevee.taa_samples : scene->eevee.taa_render_samples;
25 
26  if (sample_count_ == 0) {
27  BLI_assert(inst_.is_viewport());
28  sample_count_ = infinite_sample_count_;
29  }
30 
31  motion_blur_steps_ = !inst_.is_viewport() ? scene->eevee.motion_blur_steps : 1;
32  sample_count_ = divide_ceil_u(sample_count_, motion_blur_steps_);
33 
35  if (sample_count_ == infinite_sample_count_) {
36  /* Special case for viewport continuous rendering. We clamp to a max sample
37  * to avoid the jittered dof never converging. */
38  dof_ring_count_ = 6;
39  }
40  else {
41  dof_ring_count_ = sampling_web_ring_count_get(dof_web_density_, sample_count_);
42  }
43  dof_sample_count_ = sampling_web_sample_count_get(dof_web_density_, dof_ring_count_);
44  /* Change total sample count to fill the web pattern entirely. */
45  sample_count_ = divide_ceil_u(sample_count_, dof_sample_count_) * dof_sample_count_;
46  }
47  else {
48  dof_ring_count_ = 0;
49  dof_sample_count_ = 1;
50  }
51 
52  /* Only multiply after to have full the full DoF web pattern for each time steps. */
53  sample_count_ *= motion_blur_steps_;
54 }
55 
57 {
58  if (reset_) {
59  viewport_sample_ = 0;
60  }
61 
62  if (inst_.is_viewport()) {
63 
64  interactive_mode_ = viewport_sample_ < interactive_mode_threshold;
65 
66  bool interactive_mode_disabled = (inst_.scene->eevee.flag & SCE_EEVEE_TAA_REPROJECTION) == 0;
67  if (interactive_mode_disabled) {
68  interactive_mode_ = false;
69  sample_ = viewport_sample_;
70  }
71  else if (interactive_mode_) {
72  int interactive_sample_count = min_ii(interactive_sample_max_, sample_count_);
73 
74  if (viewport_sample_ < interactive_sample_count) {
75  /* Loop over the same starting samples. */
76  sample_ = sample_ % interactive_sample_count;
77  }
78  else {
79  /* Break out of the loop and resume normal pattern. */
80  sample_ = interactive_sample_count;
81  }
82  }
83  }
84 }
85 
87 {
88  {
89  /* TODO(fclem) we could use some persistent states to speedup the computation. */
90  double2 r, offset = {0, 0};
91  /* Using 2,3 primes as per UE4 Temporal AA presentation.
92  * http://advances.realtimerendering.com/s2014/epic/TemporalAA.pptx (slide 14) */
93  uint2 primes = {2, 3};
94  BLI_halton_2d(primes, offset, sample_ + 1, r);
95  /* WORKAROUND: We offset the distribution to make the first sample (0,0). This way, we are
96  * assured that at least one of the samples inside the TAA rotation will match the one from the
97  * draw manager. This makes sure overlays are correctly composited in static scene. */
98  data_.dimensions[SAMPLING_FILTER_U] = fractf(r[0] + (1.0 / 2.0));
99  data_.dimensions[SAMPLING_FILTER_V] = fractf(r[1] + (2.0 / 3.0));
100  /* TODO de-correlate. */
101  data_.dimensions[SAMPLING_TIME] = r[0];
102  data_.dimensions[SAMPLING_CLOSURE] = r[1];
103  data_.dimensions[SAMPLING_RAYTRACE_X] = r[0];
104  }
105  {
106  double2 r, offset = {0, 0};
107  uint2 primes = {5, 7};
108  BLI_halton_2d(primes, offset, sample_ + 1, r);
109  data_.dimensions[SAMPLING_LENS_U] = r[0];
110  data_.dimensions[SAMPLING_LENS_V] = r[1];
111  /* TODO de-correlate. */
112  data_.dimensions[SAMPLING_LIGHTPROBE] = r[0];
113  data_.dimensions[SAMPLING_TRANSPARENCY] = r[1];
114  }
115  {
116  /* Using leaped Halton sequence so we can reused the same primes as lens. */
117  double3 r, offset = {0, 0, 0};
118  uint64_t leap = 11;
119  uint3 primes = {5, 4, 7};
120  BLI_halton_3d(primes, offset, sample_ * leap, r);
121  data_.dimensions[SAMPLING_SHADOW_U] = r[0];
122  data_.dimensions[SAMPLING_SHADOW_V] = r[1];
123  data_.dimensions[SAMPLING_SHADOW_W] = r[2];
124  /* TODO de-correlate. */
125  data_.dimensions[SAMPLING_RAYTRACE_U] = r[0];
126  data_.dimensions[SAMPLING_RAYTRACE_V] = r[1];
127  data_.dimensions[SAMPLING_RAYTRACE_W] = r[2];
128  }
129  {
130  /* Using leaped Halton sequence so we can reused the same primes. */
131  double2 r, offset = {0, 0};
132  uint64_t leap = 5;
133  uint2 primes = {2, 3};
134  BLI_halton_2d(primes, offset, sample_ * leap, r);
135  data_.dimensions[SAMPLING_SHADOW_X] = r[0];
136  data_.dimensions[SAMPLING_SHADOW_Y] = r[1];
137  /* TODO de-correlate. */
138  data_.dimensions[SAMPLING_SSS_U] = r[0];
139  data_.dimensions[SAMPLING_SSS_V] = r[1];
140  }
141 
142  data_.push_update();
143 
144  viewport_sample_++;
145  sample_++;
146 
147  reset_ = false;
148 }
149 
152 /* -------------------------------------------------------------------- */
157 {
158  float3 sample;
159  sample.z = rand.x * 2.0f - 1.0f; /* cos theta */
160 
161  float r = sqrtf(fmaxf(0.0f, 1.0f - square_f(sample.z))); /* sin theta */
162 
163  float omega = rand.y * 2.0f * M_PI;
164  sample.x = r * cosf(omega);
165  sample.y = r * sinf(omega);
166 
167  sample *= sqrtf(sqrtf(rand.z));
168  return sample;
169 }
170 
172 {
173  float omega = rand.y * 2.0f * M_PI;
174  return sqrtf(rand.x) * float2(cosf(omega), sinf(omega));
175 }
176 
178 {
179  /* Fibonacci spiral. */
180  float omega = 4.0f * M_PI * (1.0f + sqrtf(5.0f)) * rand.x;
181  float r = sqrtf(rand.x);
182  /* Random rotation. */
183  omega += rand.y * 2.0f * M_PI;
184  return r * float2(cosf(omega), sinf(omega));
185 }
186 
187 void Sampling::dof_disk_sample_get(float *r_radius, float *r_theta) const
188 {
189  if (dof_ring_count_ == 0) {
190  *r_radius = *r_theta = 0.0f;
191  return;
192  }
193 
194  int s = sample_ - 1;
195  int ring = 0;
196  int ring_sample_count = 1;
197  int ring_sample = 1;
198 
199  s = s * (dof_web_density_ - 1);
200  s = s % dof_sample_count_;
201 
202  /* Choosing sample to we get faster convergence.
203  * The issue here is that we cannot map a low discrepancy sequence to this sampling pattern
204  * because the same sample could be chosen twice in relatively short intervals. */
205  /* For now just use an ascending sequence with an offset. This gives us relatively quick
206  * initial coverage and relatively high distance between samples. */
207  /* TODO(@fclem) We can try to order samples based on a LDS into a table to avoid duplicates.
208  * The drawback would be some memory consumption and initialize time. */
209  int samples_passed = 1;
210  while (s >= samples_passed) {
211  ring++;
212  ring_sample_count = ring * dof_web_density_;
213  ring_sample = s - samples_passed;
214  ring_sample = (ring_sample + 1) % ring_sample_count;
215  samples_passed += ring_sample_count;
216  }
217 
218  *r_radius = ring / (float)dof_ring_count_;
219  *r_theta = 2.0f * M_PI * ring_sample / (float)ring_sample_count;
220 }
221 
224 /* -------------------------------------------------------------------- */
228 /* Creates a discrete cumulative distribution function table from a given curvemapping.
229  * Output cdf vector is expected to already be sized according to the wanted resolution. */
231 {
232  BLI_assert(cdf.size() > 1);
233  cdf[0] = 0.0f;
234  /* Actual CDF evaluation. */
235  for (int u : cdf.index_range()) {
236  float x = (float)(u + 1) / (float)(cdf.size() - 1);
237  cdf[u + 1] = cdf[u] + BKE_curvemapping_evaluateF(&curve, 0, x);
238  }
239  /* Normalize the CDF. */
240  for (int u : cdf.index_range()) {
241  cdf[u] /= cdf.last();
242  }
243  /* Just to make sure. */
244  cdf.last() = 1.0f;
245 }
246 
247 /* Inverts a cumulative distribution function.
248  * Output vector is expected to already be sized according to the wanted resolution. */
250 {
251  for (int u : inverted_cdf.index_range()) {
252  float x = (float)u / (float)(inverted_cdf.size() - 1);
253  for (int i : cdf.index_range()) {
254  if (i == cdf.size() - 1) {
255  inverted_cdf[u] = 1.0f;
256  }
257  else if (cdf[i] >= x) {
258  float t = (x - cdf[i]) / (cdf[i + 1] - cdf[i]);
259  inverted_cdf[u] = ((float)i + t) / (float)(cdf.size() - 1);
260  break;
261  }
262  }
263  }
264 }
265 
268 } // namespace blender::eevee
typedef float(TangentPoint)[2]
float BKE_curvemapping_evaluateF(const struct CurveMapping *cumap, int cur, float value)
#define BLI_assert(a)
Definition: BLI_assert.h:46
MINLINE int min_ii(int a, int b)
MINLINE uint divide_ceil_u(uint a, uint b)
MINLINE float square_f(float a)
#define M_PI
Definition: BLI_math_base.h:20
Random number functions.
void BLI_halton_3d(const unsigned int prime[3], double offset[3], int n, double *r)
Definition: rand.cc:311
void BLI_halton_2d(const unsigned int prime[2], double offset[2], int n, double *r)
Definition: rand.cc:298
@ SCE_EEVEE_TAA_REPROJECTION
@ SCE_EEVEE_DOF_JITTER
_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 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 t
int64_t size() const
Definition: BLI_vector.hh:694
const T & last(const int64_t n=0) const
Definition: BLI_vector.hh:663
IndexRange index_range() const
Definition: BLI_vector.hh:920
static void cdf_invert(Vector< float > &cdf, Vector< float > &inverted_cdf)
static float2 sample_disk(const float2 &rand)
void dof_disk_sample_get(float *r_radius, float *r_theta) const
void init(const Scene *scene)
static float2 sample_spiral(const float2 &rand)
static void cdf_from_curvemapping(const CurveMapping &curve, Vector< float > &cdf)
static float3 sample_ball(const float3 &rand)
#define sinf(x)
Definition: cuda/compat.h:102
#define cosf(x)
Definition: cuda/compat.h:101
Scene scene
Curve curve
float inverted_cdf[FILTER_CDF_TABLE_SIZE]
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
MINLINE float fractf(float a)
#define fmaxf(x, y)
Definition: metal/compat.h:228
#define sqrtf(x)
Definition: metal/compat.h:243
vec_base< float, 2 > float2
unsigned __int64 uint64_t
Definition: stdint.h:90
struct SceneEEVEE eevee