Blender  V3.3
subsurface_random_walk.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright 2011-2022 Blender Foundation */
3 
5 
6 #include "kernel/bvh/bvh.h"
7 
9 
10 /* Random walk subsurface scattering.
11  *
12  * "Practical and Controllable Subsurface Scattering for Production Path
13  * Tracing". Matt Jen-Yuan Chiang, Peter Kutz, Brent Burley. SIGGRAPH 2016. */
14 
15 /* Support for anisotropy from:
16  * "Path Traced Subsurface Scattering using Anisotropic Phase Functions
17  * and Non-Exponential Free Flights".
18  * Magnus Wrenninge, Ryusuke Villemin, Christophe Hery.
19  * https://graphics.pixar.com/library/PathTracedSubsurface/ */
20 
21 ccl_device void subsurface_random_walk_remap(const float albedo,
22  const float d,
23  float g,
24  ccl_private float *sigma_t,
25  ccl_private float *alpha)
26 {
27  /* Compute attenuation and scattering coefficients from albedo. */
28  const float g2 = g * g;
29  const float g3 = g2 * g;
30  const float g4 = g3 * g;
31  const float g5 = g4 * g;
32  const float g6 = g5 * g;
33  const float g7 = g6 * g;
34 
35  const float A = 1.8260523782f + -1.28451056436f * g + -1.79904629312f * g2 +
36  9.19393289202f * g3 + -22.8215585862f * g4 + 32.0234874259f * g5 +
37  -23.6264803333f * g6 + 7.21067002658f * g7;
38  const float B = 4.98511194385f +
39  0.127355959438f *
40  expf(31.1491581433f * g + -201.847017512f * g2 + 841.576016723f * g3 +
41  -2018.09288505f * g4 + 2731.71560286f * g5 + -1935.41424244f * g6 +
42  559.009054474f * g7);
43  const float C = 1.09686102424f + -0.394704063468f * g + 1.05258115941f * g2 +
44  -8.83963712726f * g3 + 28.8643230661f * g4 + -46.8802913581f * g5 +
45  38.5402837518f * g6 + -12.7181042538f * g7;
46  const float D = 0.496310210422f + 0.360146581622f * g + -2.15139309747f * g2 +
47  17.8896899217f * g3 + -55.2984010333f * g4 + 82.065982243f * g5 +
48  -58.5106008578f * g6 + 15.8478295021f * g7;
49  const float E = 4.23190299701f +
50  0.00310603949088f *
51  expf(76.7316253952f * g + -594.356773233f * g2 + 2448.8834203f * g3 +
52  -5576.68528998f * g4 + 7116.60171912f * g5 + -4763.54467887f * g6 +
53  1303.5318055f * g7);
54  const float F = 2.40602999408f + -2.51814844609f * g + 9.18494908356f * g2 +
55  -79.2191708682f * g3 + 259.082868209f * g4 + -403.613804597f * g5 +
56  302.85712436f * g6 + -87.4370473567f * g7;
57 
58  const float blend = powf(albedo, 0.25f);
59 
60  *alpha = (1.0f - blend) * A * powf(atanf(B * albedo), C) +
61  blend * D * powf(atanf(E * albedo), F);
62  *alpha = clamp(*alpha, 0.0f, 0.999999f); // because of numerical precision
63 
64  float sigma_t_prime = 1.0f / fmaxf(d, 1e-16f);
65  *sigma_t = sigma_t_prime / (1.0f - g);
66 }
67 
69  const float3 radius,
70  const float anisotropy,
71  ccl_private float3 *sigma_t,
72  ccl_private float3 *alpha,
73  ccl_private float3 *throughput)
74 {
75  float sigma_t_x, sigma_t_y, sigma_t_z;
76  float alpha_x, alpha_y, alpha_z;
77 
78  subsurface_random_walk_remap(albedo.x, radius.x, anisotropy, &sigma_t_x, &alpha_x);
79  subsurface_random_walk_remap(albedo.y, radius.y, anisotropy, &sigma_t_y, &alpha_y);
80  subsurface_random_walk_remap(albedo.z, radius.z, anisotropy, &sigma_t_z, &alpha_z);
81 
82  /* Throughput already contains closure weight at this point, which includes the
83  * albedo, as well as closure mixing and Fresnel weights. Divide out the albedo
84  * which will be added through scattering. */
85  *throughput = safe_divide_color(*throughput, albedo);
86 
87  /* With low albedo values (like 0.025) we get diffusion_length 1.0 and
88  * infinite phase functions. To avoid a sharp discontinuity as we go from
89  * such values to 0.0, increase alpha and reduce the throughput to compensate. */
90  const float min_alpha = 0.2f;
91  if (alpha_x < min_alpha) {
92  (*throughput).x *= alpha_x / min_alpha;
93  alpha_x = min_alpha;
94  }
95  if (alpha_y < min_alpha) {
96  (*throughput).y *= alpha_y / min_alpha;
97  alpha_y = min_alpha;
98  }
99  if (alpha_z < min_alpha) {
100  (*throughput).z *= alpha_z / min_alpha;
101  alpha_z = min_alpha;
102  }
103 
104  *sigma_t = make_float3(sigma_t_x, sigma_t_y, sigma_t_z);
105  *alpha = make_float3(alpha_x, alpha_y, alpha_z);
106 }
107 
108 /* References for Dwivedi sampling:
109  *
110  * [1] "A Zero-variance-based Sampling Scheme for Monte Carlo Subsurface Scattering"
111  * by Jaroslav Křivánek and Eugene d'Eon (SIGGRAPH 2014)
112  * https://cgg.mff.cuni.cz/~jaroslav/papers/2014-zerovar/
113  *
114  * [2] "Improving the Dwivedi Sampling Scheme"
115  * by Johannes Meng, Johannes Hanika, and Carsten Dachsbacher (EGSR 2016)
116  * https://cg.ivd.kit.edu/1951.php
117  *
118  * [3] "Zero-Variance Theory for Efficient Subsurface Scattering"
119  * by Eugene d'Eon and Jaroslav Křivánek (SIGGRAPH 2020)
120  * https://iliyan.com/publications/RenderingCourse2020
121  */
122 
123 ccl_device_forceinline float eval_phase_dwivedi(float v, float phase_log, float cos_theta)
124 {
125  /* Eq. 9 from [2] using precomputed log((v + 1) / (v - 1)) */
126  return 1.0f / ((v - cos_theta) * phase_log);
127 }
128 
129 ccl_device_forceinline float sample_phase_dwivedi(float v, float phase_log, float rand)
130 {
131  /* Based on Eq. 10 from [2]: `v - (v + 1) * pow((v - 1) / (v + 1), rand)`
132  * Since we're already pre-computing `phase_log = log((v + 1) / (v - 1))` for the evaluation,
133  * we can implement the power function like this. */
134  return v - (v + 1.0f) * expf(-rand * phase_log);
135 }
136 
138 {
139  /* Eq. 67 from [3] */
140  return 1.0f / sqrtf(1.0f - powf(alpha, 2.44294f - 0.0215813f * alpha + 0.578637f / alpha));
141 }
142 
144 {
145  float sin_theta = safe_sqrtf(1.0f - cos_theta * cos_theta);
146  float phi = M_2PI_F * randv;
147  float3 dir = make_float3(sin_theta * cosf(phi), sin_theta * sinf(phi), cos_theta);
148 
149  float3 T, B;
150  make_orthonormals(D, &T, &B);
151  return dir.x * T + dir.y * B + dir.z * D;
152 }
153 
155  float t,
156  bool hit,
157  ccl_private float3 *transmittance)
158 {
159  float3 T = volume_color_transmittance(sigma_t, t);
160  if (transmittance) {
161  *transmittance = T;
162  }
163  return hit ? T : sigma_t * T;
164 }
165 
166 /* Define the below variable to get the similarity code active,
167  * and the value represents the cutoff level */
168 #define SUBSURFACE_RANDOM_WALK_SIMILARITY_LEVEL 9
169 
172  RNGState rng_state,
173  ccl_private Ray &ray,
174  ccl_private LocalIntersection &ss_isect)
175 {
176  float bssrdf_u, bssrdf_v;
177  path_state_rng_2D(kg, &rng_state, PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
178 
179  const float3 P = INTEGRATOR_STATE(state, ray, P);
180  const float3 N = INTEGRATOR_STATE(state, ray, D);
181  const float ray_dP = INTEGRATOR_STATE(state, ray, dP);
182  const float time = INTEGRATOR_STATE(state, ray, time);
183  const float3 Ng = INTEGRATOR_STATE(state, subsurface, Ng);
184  const int object = INTEGRATOR_STATE(state, isect, object);
185  const int prim = INTEGRATOR_STATE(state, isect, prim);
186 
187  /* Sample diffuse surface scatter into the object. */
188  float3 D;
189  float pdf;
190  sample_cos_hemisphere(-N, bssrdf_u, bssrdf_v, &D, &pdf);
191  if (dot(-Ng, D) <= 0.0f) {
192  return false;
193  }
194 
195  /* Setup ray. */
196  ray.P = P;
197  ray.D = D;
198  ray.tmin = 0.0f;
199  ray.tmax = FLT_MAX;
200  ray.time = time;
201  ray.dP = ray_dP;
202  ray.dD = differential_zero_compact();
203  ray.self.object = object;
204  ray.self.prim = prim;
205  ray.self.light_object = OBJECT_NONE;
206  ray.self.light_prim = PRIM_NONE;
207 
208  /* Convert subsurface to volume coefficients.
209  * The single-scattering albedo is named alpha to avoid confusion with the surface albedo. */
210  const float3 albedo = INTEGRATOR_STATE(state, subsurface, albedo);
211  const float3 radius = INTEGRATOR_STATE(state, subsurface, radius);
212  const float anisotropy = INTEGRATOR_STATE(state, subsurface, anisotropy);
213 
214  float3 sigma_t, alpha;
215  float3 throughput = INTEGRATOR_STATE_WRITE(state, path, throughput);
216  subsurface_random_walk_coefficients(albedo, radius, anisotropy, &sigma_t, &alpha, &throughput);
217  float3 sigma_s = sigma_t * alpha;
218 
219  /* Theoretically it should be better to use the exact alpha for the channel we're sampling at
220  * each bounce, but in practice there doesn't seem to be a noticeable difference in exchange
221  * for making the code significantly more complex and slower (if direction sampling depends on
222  * the sampled channel, we need to compute its PDF per-channel and consider it for MIS later on).
223  *
224  * Since the strength of the guided sampling increases as alpha gets lower, using a value that
225  * is too low results in fireflies while one that's too high just gives a bit more noise.
226  * Therefore, the code here uses the highest of the three albedos to be safe. */
227  const float diffusion_length = diffusion_length_dwivedi(reduce_max(alpha));
228 
229  if (diffusion_length == 1.0f) {
230  /* With specific values of alpha the length might become 1, which in asymptotic makes phase to
231  * be infinite. After first bounce it will cause throughput to be 0. Do early output, avoiding
232  * numerical issues and extra unneeded work. */
233  return false;
234  }
235 
236  /* Precompute term for phase sampling. */
237  const float phase_log = logf((diffusion_length + 1.0f) / (diffusion_length - 1.0f));
238 
239  /* Modify state for RNGs, decorrelated from other paths. */
240  rng_state.rng_hash = cmj_hash(rng_state.rng_hash + rng_state.rng_offset, 0xdeadbeef);
241 
242  /* Random walk until we hit the surface again. */
243  bool hit = false;
244  bool have_opposite_interface = false;
245  float opposite_distance = 0.0f;
246 
247  /* TODO: Disable for `alpha > 0.999` or so? */
248  /* Our heuristic, a compromise between guiding and classic. */
249  const float guided_fraction = 1.0f - fmaxf(0.5f, powf(fabsf(anisotropy), 0.125f));
250 
251 #ifdef SUBSURFACE_RANDOM_WALK_SIMILARITY_LEVEL
252  float3 sigma_s_star = sigma_s * (1.0f - anisotropy);
253  float3 sigma_t_star = sigma_t - sigma_s + sigma_s_star;
254  float3 sigma_t_org = sigma_t;
255  float3 sigma_s_org = sigma_s;
256  const float anisotropy_org = anisotropy;
257  const float guided_fraction_org = guided_fraction;
258 #endif
259 
260  for (int bounce = 0; bounce < BSSRDF_MAX_BOUNCES; bounce++) {
261  /* Advance random number offset. */
262  rng_state.rng_offset += PRNG_BOUNCE_NUM;
263 
264 #ifdef SUBSURFACE_RANDOM_WALK_SIMILARITY_LEVEL
265  // shadow with local variables according to depth
266  float anisotropy, guided_fraction;
267  float3 sigma_s, sigma_t;
269  anisotropy = anisotropy_org;
270  guided_fraction = guided_fraction_org;
271  sigma_t = sigma_t_org;
272  sigma_s = sigma_s_org;
273  }
274  else {
275  anisotropy = 0.0f;
276  guided_fraction = 0.75f; // back to isotropic heuristic from Blender
277  sigma_t = sigma_t_star;
278  sigma_s = sigma_s_star;
279  }
280 #endif
281 
282  /* Sample color channel, use MIS with balance heuristic. */
283  float rphase = path_state_rng_1D(kg, &rng_state, PRNG_PHASE_CHANNEL);
284  float3 channel_pdf;
285  int channel = volume_sample_channel(alpha, throughput, rphase, &channel_pdf);
286  float sample_sigma_t = volume_channel_get(sigma_t, channel);
287  float randt = path_state_rng_1D(kg, &rng_state, PRNG_SCATTER_DISTANCE);
288 
289  /* We need the result of the ray-cast to compute the full guided PDF, so just remember the
290  * relevant terms to avoid recomputing them later. */
291  float backward_fraction = 0.0f;
292  float forward_pdf_factor = 0.0f;
293  float forward_stretching = 1.0f;
294  float backward_pdf_factor = 0.0f;
295  float backward_stretching = 1.0f;
296 
297  /* For the initial ray, we already know the direction, so just do classic distance sampling. */
298  if (bounce > 0) {
299  /* Decide whether we should use guided or classic sampling. */
300  bool guided = (path_state_rng_1D(kg, &rng_state, PRNG_LIGHT_TERMINATE) < guided_fraction);
301 
302  /* Determine if we want to sample away from the incoming interface.
303  * This only happens if we found a nearby opposite interface, and the probability for it
304  * depends on how close we are to it already.
305  * This probability term comes from the recorded presentation of [3]. */
306  bool guide_backward = false;
307  if (have_opposite_interface) {
308  /* Compute distance of the random walk between the tangent plane at the starting point
309  * and the assumed opposite interface (the parallel plane that contains the point we
310  * found in our ray query for the opposite side). */
311  float x = clamp(dot(ray.P - P, -N), 0.0f, opposite_distance);
312  backward_fraction = 1.0f /
313  (1.0f + expf((opposite_distance - 2.0f * x) / diffusion_length));
314  guide_backward = path_state_rng_1D(kg, &rng_state, PRNG_TERMINATE) < backward_fraction;
315  }
316 
317  /* Sample scattering direction. */
318  float scatter_u, scatter_v;
319  path_state_rng_2D(kg, &rng_state, PRNG_BSDF_U, &scatter_u, &scatter_v);
320  float cos_theta;
321  float hg_pdf;
322  if (guided) {
323  cos_theta = sample_phase_dwivedi(diffusion_length, phase_log, scatter_u);
324  /* The backwards guiding distribution is just mirrored along `sd->N`, so swapping the
325  * sign here is enough to sample from that instead. */
326  if (guide_backward) {
327  cos_theta = -cos_theta;
328  }
329  float3 newD = direction_from_cosine(N, cos_theta, scatter_v);
330  hg_pdf = single_peaked_henyey_greenstein(dot(ray.D, newD), anisotropy);
331  ray.D = newD;
332  }
333  else {
334  float3 newD = henyey_greenstrein_sample(ray.D, anisotropy, scatter_u, scatter_v, &hg_pdf);
335  cos_theta = dot(newD, N);
336  ray.D = newD;
337  }
338 
339  /* Compute PDF factor caused by phase sampling (as the ratio of guided / classic).
340  * Since phase sampling is channel-independent, we can get away with applying a factor
341  * to the guided PDF, which implicitly means pulling out the classic PDF term and letting
342  * it cancel with an equivalent term in the numerator of the full estimator.
343  * For the backward PDF, we again reuse the same probability distribution with a sign swap.
344  */
345  forward_pdf_factor = M_1_2PI_F * eval_phase_dwivedi(diffusion_length, phase_log, cos_theta) /
346  hg_pdf;
347  backward_pdf_factor = M_1_2PI_F *
348  eval_phase_dwivedi(diffusion_length, phase_log, -cos_theta) / hg_pdf;
349 
350  /* Prepare distance sampling.
351  * For the backwards case, this also needs the sign swapped since now directions against
352  * `sd->N` (and therefore with negative cos_theta) are preferred. */
353  forward_stretching = (1.0f - cos_theta / diffusion_length);
354  backward_stretching = (1.0f + cos_theta / diffusion_length);
355  if (guided) {
356  sample_sigma_t *= guide_backward ? backward_stretching : forward_stretching;
357  }
358  }
359 
360  /* Sample direction along ray. */
361  float t = -logf(1.0f - randt) / sample_sigma_t;
362 
363  /* On the first bounce, we use the ray-cast to check if the opposite side is nearby.
364  * If yes, we will later use backwards guided sampling in order to have a decent
365  * chance of connecting to it.
366  * TODO: Maybe use less than 10 times the mean free path? */
367  if (bounce == 0) {
368  ray.tmax = max(t, 10.0f / (reduce_min(sigma_t)));
369  }
370  else {
371  ray.tmax = t;
372  /* After the first bounce the object can intersect the same surface again */
373  ray.self.object = OBJECT_NONE;
374  ray.self.prim = PRIM_NONE;
375  }
376  scene_intersect_local(kg, &ray, &ss_isect, object, NULL, 1);
377  hit = (ss_isect.num_hits > 0);
378 
379  if (hit) {
380  ray.tmax = ss_isect.hits[0].t;
381  }
382 
383  if (bounce == 0) {
384  /* Check if we hit the opposite side. */
385  if (hit) {
386  have_opposite_interface = true;
387  opposite_distance = dot(ray.P + ray.tmax * ray.D - P, -N);
388  }
389  /* Apart from the opposite side check, we were supposed to only trace up to distance t,
390  * so check if there would have been a hit in that case. */
391  hit = ray.tmax < t;
392  }
393 
394  /* Use the distance to the exit point for the throughput update if we found one. */
395  if (hit) {
396  t = ray.tmax;
397  }
398 
399  /* Advance to new scatter location. */
400  ray.P += t * ray.D;
401 
402  float3 transmittance;
403  float3 pdf = subsurface_random_walk_pdf(sigma_t, t, hit, &transmittance);
404  if (bounce > 0) {
405  /* Compute PDF just like we do for classic sampling, but with the stretched sigma_t. */
406  float3 guided_pdf = subsurface_random_walk_pdf(forward_stretching * sigma_t, t, hit, NULL);
407 
408  if (have_opposite_interface) {
409  /* First step of MIS: Depending on geometry we might have two methods for guided
410  * sampling, so perform MIS between them. */
411  float3 back_pdf = subsurface_random_walk_pdf(backward_stretching * sigma_t, t, hit, NULL);
412  guided_pdf = mix(
413  guided_pdf * forward_pdf_factor, back_pdf * backward_pdf_factor, backward_fraction);
414  }
415  else {
416  /* Just include phase sampling factor otherwise. */
417  guided_pdf *= forward_pdf_factor;
418  }
419 
420  /* Now we apply the MIS balance heuristic between the classic and guided sampling. */
421  pdf = mix(pdf, guided_pdf, guided_fraction);
422  }
423 
424  /* Finally, we're applying MIS again to combine the three color channels.
425  * Altogether, the MIS computation combines up to nine different estimators:
426  * {classic, guided, backward_guided} x {r, g, b} */
427  throughput *= (hit ? transmittance : sigma_s * transmittance) / dot(channel_pdf, pdf);
428 
429  if (hit) {
430  /* If we hit the surface, we are done. */
431  break;
432  }
433  else if (throughput.x < VOLUME_THROUGHPUT_EPSILON &&
434  throughput.y < VOLUME_THROUGHPUT_EPSILON &&
435  throughput.z < VOLUME_THROUGHPUT_EPSILON) {
436  /* Avoid unnecessary work and precision issue when throughput gets really small. */
437  break;
438  }
439  }
440 
441  if (hit) {
442  kernel_assert(isfinite_safe(throughput));
443  INTEGRATOR_STATE_WRITE(state, path, throughput) = throughput;
444  }
445 
446  return hit;
447 }
448 
MINLINE float safe_sqrtf(float a)
_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
#define C
Definition: RandGen.cpp:25
__forceinline int reduce_max(const avxi &v)
Definition: avxi.h:692
__forceinline int reduce_min(const avxi &v)
Definition: avxi.h:688
ATTR_WARN_UNUSED_RESULT const BMVert * v
#define A
#define kernel_assert(cond)
Definition: cpu/compat.h:34
#define ccl_device_forceinline
Definition: cuda/compat.h:35
#define logf(x)
Definition: cuda/compat.h:105
#define sinf(x)
Definition: cuda/compat.h:102
#define cosf(x)
Definition: cuda/compat.h:101
#define ccl_device
Definition: cuda/compat.h:32
#define expf(x)
Definition: cuda/compat.h:106
#define ccl_private
Definition: cuda/compat.h:48
#define ccl_device_inline
Definition: cuda/compat.h:34
#define powf(x, y)
Definition: cuda/compat.h:103
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
double time
const KernelGlobalsCPU *ccl_restrict KernelGlobals
ccl_device_forceinline float differential_zero_compact()
Definition: differential.h:112
#define mix(a, b, c)
Definition: hash.h:17
#define VOLUME_THROUGHPUT_EPSILON
ccl_device float3 volume_color_transmittance(float3 sigma, float t)
ccl_device float3 henyey_greenstrein_sample(float3 D, float g, float randu, float randv, ccl_private float *pdf)
ccl_device float single_peaked_henyey_greenstein(float cos_theta, float g)
ccl_device float volume_channel_get(float3 value, int channel)
ccl_device int volume_sample_channel(float3 albedo, float3 throughput, float rand, ccl_private float3 *pdf)
const int state
ccl_device_inline uint cmj_hash(uint i, uint p)
@ PRNG_BOUNCE_NUM
Definition: kernel/types.h:172
@ PRNG_LIGHT_TERMINATE
Definition: kernel/types.h:168
@ PRNG_BSDF_U
Definition: kernel/types.h:164
@ PRNG_SCATTER_DISTANCE
Definition: kernel/types.h:171
@ PRNG_TERMINATE
Definition: kernel/types.h:169
@ PRNG_PHASE_CHANNEL
Definition: kernel/types.h:170
#define PRIM_NONE
Definition: kernel/types.h:41
#define OBJECT_NONE
Definition: kernel/types.h:40
#define BSSRDF_MAX_BOUNCES
Definition: kernel/types.h:32
static float P(float k)
Definition: math_interp.c:25
#define N
#define T
#define B
#define F
#define fmaxf(x, y)
Definition: metal/compat.h:228
#define atanf(x)
Definition: metal/compat.h:223
#define fabsf(x)
Definition: metal/compat.h:219
#define sqrtf(x)
Definition: metal/compat.h:243
#define make_float3(x, y, z)
Definition: metal/compat.h:204
T dot(const vec_base< T, Size > &a, const vec_base< T, Size > &b)
T clamp(const T &a, const T &min, const T &max)
static const pxr::TfToken g("g", pxr::TfToken::Immortal)
ccl_device_inline float path_state_rng_1D(KernelGlobals kg, ccl_private const RNGState *rng_state, int dimension)
Definition: path_state.h:299
ccl_device_inline void path_state_rng_2D(KernelGlobals kg, ccl_private const RNGState *rng_state, int dimension, ccl_private float *fx, ccl_private float *fy)
Definition: path_state.h:307
ccl_device_inline void sample_cos_hemisphere(const float3 N, float randu, float randv, ccl_private float3 *omega_in, ccl_private float *pdf)
IntegratorStateCPU *ccl_restrict IntegratorState
Definition: state.h:147
#define INTEGRATOR_STATE_WRITE(state, nested_struct, member)
Definition: state.h:155
#define INTEGRATOR_STATE(state, nested_struct, member)
Definition: state.h:154
uint rng_hash
Definition: path_state.h:278
uint rng_offset
Definition: path_state.h:279
float z
float y
float x
ccl_device_forceinline float diffusion_length_dwivedi(float alpha)
ccl_device_forceinline float3 direction_from_cosine(float3 D, float cos_theta, float randv)
ccl_device_forceinline float sample_phase_dwivedi(float v, float phase_log, float rand)
#define SUBSURFACE_RANDOM_WALK_SIMILARITY_LEVEL
ccl_device_inline bool subsurface_random_walk(KernelGlobals kg, IntegratorState state, RNGState rng_state, ccl_private Ray &ray, ccl_private LocalIntersection &ss_isect)
ccl_device void subsurface_random_walk_coefficients(const float3 albedo, const float3 radius, const float anisotropy, ccl_private float3 *sigma_t, ccl_private float3 *alpha, ccl_private float3 *throughput)
ccl_device_forceinline float3 subsurface_random_walk_pdf(float3 sigma_t, float t, bool hit, ccl_private float3 *transmittance)
ccl_device_forceinline float eval_phase_dwivedi(float v, float phase_log, float cos_theta)
CCL_NAMESPACE_BEGIN ccl_device void subsurface_random_walk_remap(const float albedo, const float d, float g, ccl_private float *sigma_t, ccl_private float *alpha)
static int blend(const Tex *tex, const float texvec[3], TexResult *texres)
float max
#define M_2PI_F
Definition: util/math.h:60
ccl_device_inline float3 safe_divide_color(float3 a, float3 b)
Definition: util/math.h:605
ccl_device_inline bool isfinite_safe(float f)
Definition: util/math.h:353
#define M_1_2PI_F
Definition: util/math.h:49
ccl_device_inline void make_orthonormals(const float3 N, ccl_private float3 *a, ccl_private float3 *b)
Definition: util/math.h:566
BLI_INLINE float D(const float *data, const int res[3], int x, int y, int z)
Definition: voxel.c:13