Blender V5.0
eevee_sampling.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2021 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#include "BKE_colortools.hh"
12#include "BKE_scene.hh"
13
14#include "BLI_rand.h"
15
16#include "BLI_math_base.hh"
17#include "BLI_math_base_safe.h"
18
19#include "eevee_instance.hh"
20#include "eevee_sampling.hh"
21
22namespace blender::eevee {
23
24/* -------------------------------------------------------------------- */
27
28void Sampling::init(const Scene *scene)
29{
30 /* Note: Cycles have different option for view layers sample overrides. The current behavior
31 * matches the default `Use`, which simply override if non-zero. */
32 uint64_t render_sample_count = (inst_.view_layer->samples > 0) ? inst_.view_layer->samples :
34
35 sample_count_ = inst_.is_viewport() ? scene->eevee.taa_samples : render_sample_count;
36
37 if (inst_.is_image_render) {
38 sample_count_ = math::max(uint64_t(1), sample_count_);
39 }
40
41 if (sample_count_ == 0) {
42 BLI_assert(inst_.is_viewport());
43 sample_count_ = infinite_sample_count_;
44 }
45
46 if (inst_.is_viewport()) {
47 /* We can't rely on the film module as it is initialized later. */
48 int pixel_size = BKE_render_preview_pixel_size(&inst_.scene->r);
49 if (pixel_size > 1) {
50 /* Enforce to render at least all the film pixel once. */
51 sample_count_ = max_ii(sample_count_, square_i(pixel_size));
52 }
53 }
54
55 motion_blur_steps_ = !inst_.is_viewport() && ((scene->r.mode & R_MBLUR) != 0) ?
57 1;
58 sample_count_ = divide_ceil_u(sample_count_, motion_blur_steps_);
59
60 if (scene->eevee.flag & SCE_EEVEE_DOF_JITTER) {
61 if (sample_count_ == infinite_sample_count_) {
62 /* Special case for viewport continuous rendering. We clamp to a max sample
63 * to avoid the jittered dof never converging. */
64 dof_ring_count_ = 6;
65 }
66 else {
67 dof_ring_count_ = sampling_web_ring_count_get(dof_web_density_, sample_count_);
68 }
69 dof_sample_count_ = sampling_web_sample_count_get(dof_web_density_, dof_ring_count_);
70 /* Change total sample count to fill the web pattern entirely. */
71 sample_count_ = divide_ceil_u(sample_count_, dof_sample_count_) * dof_sample_count_;
72 }
73 else {
74 dof_ring_count_ = 0;
75 dof_sample_count_ = 1;
76 }
77
78 /* Only multiply after to have full the full DoF web pattern for each time steps. */
79 sample_count_ *= motion_blur_steps_;
80
81 auto clamp_value_load = [](float value) { return (value > 0.0) ? value : 1e20; };
82
83 clamp_data_.sun_threshold = clamp_value_load(inst_.world.sun_threshold());
84 clamp_data_.surface_direct = clamp_value_load(scene->eevee.clamp_surface_direct);
85 clamp_data_.surface_indirect = clamp_value_load(scene->eevee.clamp_surface_indirect);
86 clamp_data_.volume_direct = clamp_value_load(scene->eevee.clamp_volume_direct);
87 clamp_data_.volume_indirect = clamp_value_load(scene->eevee.clamp_volume_indirect);
88}
89
90void Sampling::init(const Object &probe_object)
91{
92 BLI_assert(inst_.is_baking());
93 const ::LightProbe &lightprobe = DRW_object_get_data_for_drawing<::LightProbe>(probe_object);
94
95 sample_count_ = max_ii(1, lightprobe.grid_bake_samples);
96 sample_ = 0;
97}
98
100{
101 if (reset_) {
102 viewport_sample_ = 0;
103 }
104
105 if (inst_.is_viewport()) {
106
107 interactive_mode_ = viewport_sample_ < interactive_mode_threshold;
108
109 bool interactive_mode_disabled = (inst_.scene->eevee.flag & SCE_EEVEE_TAA_REPROJECTION) == 0 ||
110 inst_.is_viewport_image_render;
111 if (interactive_mode_disabled) {
112 interactive_mode_ = false;
113 sample_ = viewport_sample_;
114 }
115 else if (interactive_mode_) {
116 int interactive_sample_count = interactive_sample_max_;
117
118 if (viewport_sample_ < interactive_sample_count) {
119 /* Loop over the same starting samples. */
120 sample_ = sample_ % interactive_sample_count;
121 }
122 else {
123 /* Break out of the loop and resume normal pattern. */
124 sample_ = interactive_sample_count;
125 }
126 }
127 }
128}
129
131{
132 {
133 /* Repeat the sequence for all pixels that are being up-scaled. */
134 uint64_t sample_filter = sample_ / square_i(inst_.film.scaling_factor_get());
135 if (interactive_mode()) {
136 sample_filter = sample_filter % interactive_sample_aa_;
137 }
138 /* TODO(fclem) we could use some persistent states to speedup the computation. */
139 double2 r, offset = {0, 0};
140 /* Using 2,3 primes as per UE4 Temporal AA presentation.
141 * http://advances.realtimerendering.com/s2014/epic/TemporalAA.pptx (slide 14) */
142 uint2 primes = {2, 3};
143 BLI_halton_2d(primes, offset, sample_filter + 1, r);
144 /* WORKAROUND: We offset the distribution to make the first sample (0,0). This way, we are
145 * assured that at least one of the samples inside the TAA rotation will match the one from the
146 * draw manager. This makes sure overlays are correctly composited in static scene. */
147 data_.dimensions[SAMPLING_FILTER_U] = fractf(r[0] + (1.0 / 2.0));
148 data_.dimensions[SAMPLING_FILTER_V] = fractf(r[1] + (2.0 / 3.0));
149 /* TODO de-correlate. */
150 data_.dimensions[SAMPLING_TIME] = r[0];
151 data_.dimensions[SAMPLING_CLOSURE] = r[1];
152 data_.dimensions[SAMPLING_RAYTRACE_X] = r[0];
153 }
154 {
155 double3 r, offset = {0, 0, 0};
156 uint3 primes = {5, 7, 3};
157 BLI_halton_3d(primes, offset, sample_ + 1, r);
158 data_.dimensions[SAMPLING_LENS_U] = r[0];
159 data_.dimensions[SAMPLING_LENS_V] = r[1];
160 /* TODO de-correlate. */
161 data_.dimensions[SAMPLING_LIGHTPROBE] = r[0];
162 data_.dimensions[SAMPLING_TRANSPARENCY] = r[1];
163 /* TODO de-correlate. */
164 data_.dimensions[SAMPLING_AO_U] = r[0];
165 data_.dimensions[SAMPLING_AO_V] = r[1];
166 data_.dimensions[SAMPLING_AO_W] = r[2];
167 /* TODO de-correlate. */
168 data_.dimensions[SAMPLING_CURVES_U] = r[0];
169 }
170 {
171 uint64_t sample_raytrace = sample_;
172 if (interactive_mode()) {
173 sample_raytrace = sample_raytrace % interactive_sample_raytrace_;
174 }
175 /* Using leaped Halton sequence so we can reused the same primes as lens. */
176 double3 r, offset = {0, 0, 0};
177 uint64_t leap = 13;
178 uint3 primes = {5, 7, 11};
179 BLI_halton_3d(primes, offset, sample_raytrace * leap + 1, r);
180 data_.dimensions[SAMPLING_SHADOW_U] = r[0];
181 data_.dimensions[SAMPLING_SHADOW_V] = r[1];
182 data_.dimensions[SAMPLING_SHADOW_W] = r[2];
183 /* TODO de-correlate. */
184 data_.dimensions[SAMPLING_RAYTRACE_U] = r[0];
185 data_.dimensions[SAMPLING_RAYTRACE_V] = r[1];
186 data_.dimensions[SAMPLING_RAYTRACE_W] = r[2];
187 }
188 {
189 double3 r, offset = {0, 0, 0};
190 uint3 primes = {2, 3, 5};
191 BLI_halton_3d(primes, offset, sample_ + 1, r);
192 /* WORKAROUND: We offset the distribution to make the first sample (0,0,0). */
193 /* TODO de-correlate. */
194 data_.dimensions[SAMPLING_SHADOW_I] = fractf(r[0] + (1.0 / 2.0));
195 data_.dimensions[SAMPLING_SHADOW_J] = fractf(r[1] + (2.0 / 3.0));
196 data_.dimensions[SAMPLING_SHADOW_K] = fractf(r[2] + (4.0 / 5.0));
197 }
198 {
199 uint64_t sample_volume = sample_;
200 if (interactive_mode()) {
201 sample_volume = sample_volume % interactive_sample_volume_;
202 }
203 double3 r, offset = {0, 0, 0};
204 uint3 primes = {2, 3, 5};
205 BLI_halton_3d(primes, offset, sample_volume + 1, r);
206 /* WORKAROUND: We offset the distribution to make the first sample (0,0,0). */
207 data_.dimensions[SAMPLING_VOLUME_U] = fractf(r[0] + (1.0 / 2.0));
208 data_.dimensions[SAMPLING_VOLUME_V] = fractf(r[1] + (2.0 / 3.0));
209 data_.dimensions[SAMPLING_VOLUME_W] = fractf(r[2] + (4.0 / 5.0));
210 }
211 {
212 /* Using leaped Halton sequence so we can reused the same primes. */
213 double2 r, offset = {0, 0};
214 uint64_t leap = 5;
215 uint2 primes = {2, 3};
216 BLI_halton_2d(primes, offset, sample_ * leap + 1, r);
217 data_.dimensions[SAMPLING_SHADOW_X] = r[0];
218 data_.dimensions[SAMPLING_SHADOW_Y] = r[1];
219 /* TODO de-correlate. */
220 data_.dimensions[SAMPLING_SSS_U] = r[0];
221 data_.dimensions[SAMPLING_SSS_V] = r[1];
222 }
223 {
224 /* Don't leave unused data undefined. */
225 data_.dimensions[SAMPLING_UNUSED_0] = 0.0f;
226 data_.dimensions[SAMPLING_UNUSED_1] = 0.0f;
227 data_.dimensions[SAMPLING_UNUSED_2] = 0.0f;
228 }
229
231 /* These numbers are often fed to `sqrt`. Make sure their values are in the expected range. */
232 BLI_assert(data_.dimensions[i] >= 0.0f);
233 BLI_assert(data_.dimensions[i] < 1.0f);
235 }
236
237 data_.push_update();
238
239 viewport_sample_++;
240 sample_++;
241
242 reset_ = false;
243}
244
246{
247 BLI_assert(inst_.is_viewport());
248 reset_ = true;
249}
250
252{
253 BLI_assert(inst_.is_viewport());
254 return reset_;
255}
256
258
259/* -------------------------------------------------------------------- */
262
264{
266 sample.z = rand.x * 2.0f - 1.0f; /* cos theta */
267
268 float r = sqrtf(fmaxf(0.0f, 1.0f - square_f(sample.z))); /* sin theta */
269
270 float omega = rand.y * 2.0f * M_PI;
271 sample.x = r * cosf(omega);
272 sample.y = r * sinf(omega);
273
274 sample *= sqrtf(sqrtf(rand.z));
275 return sample;
276}
277
279{
280 float omega = rand.y * 2.0f * M_PI;
281 return sqrtf(rand.x) * float2(cosf(omega), sinf(omega));
282}
283
285{
286 const float omega = rand.y * 2.0f * M_PI;
287 const float cos_theta = rand.x;
288 const float sin_theta = safe_sqrtf(1.0f - square_f(cos_theta));
289 return float3(sin_theta * float2(cosf(omega), sinf(omega)), cos_theta);
290}
291
293{
294 const float omega = rand.y * 2.0f * M_PI;
295 const float cos_theta = rand.x * 2.0f - 1.0f;
296 const float sin_theta = safe_sqrtf(1.0f - square_f(cos_theta));
297 return float3(sin_theta * float2(cosf(omega), sinf(omega)), cos_theta);
298}
299
301{
302 /* Fibonacci spiral. */
303 float omega = 4.0f * M_PI * (1.0f + sqrtf(5.0f)) * rand.x;
304 float r = sqrtf(rand.x);
305 /* Random rotation. */
306 omega += rand.y * 2.0f * M_PI;
307 return r * float2(cosf(omega), sinf(omega));
308}
309
310void Sampling::dof_disk_sample_get(float *r_radius, float *r_theta) const
311{
312 if (dof_ring_count_ == 0) {
313 *r_radius = *r_theta = 0.0f;
314 return;
315 }
316
317 int s = sample_ - 1;
318 int ring = 0;
319 int ring_sample_count = 1;
320 int ring_sample = 1;
321
322 s = s * (dof_web_density_ - 1);
323 s = s % dof_sample_count_;
324
325 /* Choosing sample to we get faster convergence.
326 * The issue here is that we cannot map a low discrepancy sequence to this sampling pattern
327 * because the same sample could be chosen twice in relatively short intervals. */
328 /* For now just use an ascending sequence with an offset. This gives us relatively quick
329 * initial coverage and relatively high distance between samples. */
330 /* TODO(@fclem) We can try to order samples based on a LDS into a table to avoid duplicates.
331 * The drawback would be some memory consumption and initialize time. */
332 int samples_passed = 1;
333 while (s >= samples_passed) {
334 ring++;
335 ring_sample_count = ring * dof_web_density_;
336 ring_sample = s - samples_passed;
337 ring_sample = (ring_sample + 1) % ring_sample_count;
338 samples_passed += ring_sample_count;
339 }
340
341 *r_radius = ring / float(dof_ring_count_);
342 *r_theta = 2.0f * M_PI * ring_sample / float(ring_sample_count);
343}
344
346
347/* -------------------------------------------------------------------- */
350
352{
353 BLI_assert(cdf.size() > 1);
354 cdf[0] = 0.0f;
355 /* Actual CDF evaluation. */
356 for (int u : IndexRange(cdf.size() - 1)) {
357 float x = float(u + 1) / float(cdf.size() - 1);
358 cdf[u + 1] = cdf[u] + BKE_curvemapping_evaluateF(&curve, 0, x);
359 }
360 /* Normalize the CDF. */
361 for (int u : cdf.index_range()) {
362 cdf[u] /= cdf.last();
363 }
364 /* Just to make sure. */
365 cdf.last() = 1.0f;
366}
367
369{
370 BLI_assert(cdf.first() == 0.0f && cdf.last() == 1.0f);
371 for (int u : inverted_cdf.index_range()) {
372 float x = clamp_f(u / float(inverted_cdf.size() - 1), 1e-5f, 1.0f - 1e-5f);
373 for (int i : cdf.index_range().drop_front(1)) {
374 if (cdf[i] >= x) {
375 float t = (x - cdf[i]) / (cdf[i] - cdf[i - 1]);
376 inverted_cdf[u] = (float(i) + t) / float(cdf.size() - 1);
377 break;
378 }
379 }
380 }
381}
382
384
385} // namespace blender::eevee
float BKE_curvemapping_evaluateF(const CurveMapping *cumap, int cur, float value)
int BKE_render_preview_pixel_size(const RenderData *r)
Definition scene.cc:2930
#define BLI_assert(a)
Definition BLI_assert.h:46
MINLINE uint divide_ceil_u(uint a, uint b)
MINLINE float clamp_f(float value, float min, float max)
MINLINE int square_i(int a)
MINLINE int max_ii(int a, int b)
MINLINE float square_f(float a)
MINLINE float safe_sqrtf(float a)
#define M_PI
Random number functions.
void BLI_halton_3d(const unsigned int prime[3], double offset[3], int n, double *r)
Definition rand.cc:250
void BLI_halton_2d(const unsigned int prime[2], double offset[2], int n, double *r)
Definition rand.cc:237
#define UNUSED_VARS_NDEBUG(...)
@ R_MBLUR
@ SCE_EEVEE_TAA_REPROJECTION
@ SCE_EEVEE_DOF_JITTER
T & DRW_object_get_data_for_drawing(const Object &object)
ccl_device_inline float cos_theta(const float3 w)
ccl_device_inline float sin_theta(const float3 w)
unsigned long long int uint64_t
constexpr IndexRange drop_front(int64_t n) const
int64_t size() const
const T & last(const int64_t n=0) const
IndexRange index_range() const
const T & first() const
static float3 sample_sphere(const float2 &rand)
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_hemisphere(const float2 &rand)
static float3 sample_ball(const float3 &rand)
nullptr float
#define SAMPLING_DIMENSION_COUNT
static int sampling_web_ring_count_get(int web_density, int sample_count)
static int sampling_web_sample_count_get(int web_density, int in_ring_count)
T max(const T &a, const T &b)
VecBase< uint32_t, 2 > uint2
VecBase< double, 2 > double2
VecBase< uint32_t, 3 > uint3
VecBase< float, 2 > float2
VecBase< double, 3 > double3
VecBase< float, 3 > float3
#define sqrtf
#define fmaxf
#define sinf
#define fractf
#define cosf
float clamp_surface_direct
float clamp_volume_indirect
float clamp_surface_indirect
float clamp_volume_direct
struct RenderData r
struct SceneEEVEE eevee
i
Definition text_draw.cc:230