Blender  V3.3
mnee.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright 2011-2022 Blender Foundation */
3 
4 #ifdef __MNEE__
5 
6 # include "kernel/light/sample.h"
7 
8 /*
9  * Manifold Next Event Estimation
10  *
11  * This code adds manifold next event estimation through refractive surface(s) as a new sampling
12  * technique for direct lighting, i.e. finding the point on the refractive surface(s) along the
13  * path to a light sample, which satisfies fermat's principle for a given microfacet normal and
14  * the path's end points. This technique involves walking on the "specular manifold" using a pseudo
15  * newton solver. Such a manifold is defined by the specular constraint matrix from the manifold
16  * exploration framework [2]. For each refractive interface, this constraint is defined by
17  * enforcing that the generalized half-vector projection onto the interface local tangent plane is
18  * null. The newton solver guides the walk by linearizing the manifold locally before reprojecting
19  * the linear solution onto the refractive surface. See paper [1] for more details about
20  * the technique itself and [3] for the half-vector light transport formulation, from which it is
21  * derived.
22  *
23  * [1] Manifold Next Event Estimation
24  * Johannes Hanika, Marc Droske, and Luca Fascione. 2015.
25  * Comput. Graph. Forum 34, 4 (July 2015), 87–97.
26  * https://jo.dreggn.org/home/2015_mnee.pdf
27  *
28  * [2] Manifold exploration: a Markov Chain Monte Carlo technique for rendering scenes with
29  * difficult specular transport Wenzel Jakob and Steve Marschner. 2012. ACM Trans. Graph. 31, 4,
30  * Article 58 (July 2012), 13 pages.
31  * https://www.cs.cornell.edu/projects/manifolds-sg12/
32  *
33  * [3] The Natural-Constraint Representation of the Path Space for Efficient Light Transport
34  * Simulation Anton S. Kaplanyan, Johannes Hanika, and Carsten Dachsbacher. 2014. ACM Trans. Graph.
35  * 33, 4, Article 102 (July 2014), 13 pages.
36  * https://cg.ivd.kit.edu/english/HSLT.php
37  */
38 
39 # define MNEE_MAX_ITERATIONS 64
40 # define MNEE_MAX_INTERSECTION_COUNT 10
41 # define MNEE_SOLVER_THRESHOLD 0.001f
42 # define MNEE_MINIMUM_STEP_SIZE 0.0001f
43 # define MNEE_MAX_CAUSTIC_CASTERS 6
44 # define MNEE_MIN_DISTANCE 0.001f
45 # define MNEE_MIN_PROGRESS_DISTANCE 0.0001f
46 # define MNEE_MIN_DETERMINANT 0.0001f
47 # define MNEE_PROJECTION_DISTANCE_MULTIPLIER 2.f
48 
50 
51 /* Manifold struct containing the local differential geometry quantity */
52 typedef ccl_private struct ManifoldVertex {
53  /* Position and partials */
54  float3 p;
55  float3 dp_du;
56  float3 dp_dv;
57 
58  /* Normal and partials */
59  float3 n;
60  float3 ng;
61  float3 dn_du;
62  float3 dn_dv;
63 
64  /* geometric info */
65  float2 uv;
66  int object;
67  int prim;
68  int shader;
69 
70  /* closure info */
71  float eta;
73  float2 n_offset;
74 
75  /* constraint and its derivative matrices */
76  float2 constraint;
77  float4 a;
78  float4 b;
79  float4 c;
80 } ManifoldVertex;
81 
82 /* Multiplication of a 2x2 matrix encoded in a row-major order float4 by a vector */
83 ccl_device_inline float2 mat22_mult(const float4 a, const float2 b)
84 {
85  return make_float2(a.x * b.x + a.y * b.y, a.z * b.x + a.w * b.y);
86 }
87 
88 /* Multiplication of 2x2 matrices encoded in a row-major order float4 */
89 ccl_device_inline float4 mat22_mult(const float4 a, const float4 b)
90 {
91  return make_float4(
92  a.x * b.x + a.y * b.z, a.x * b.y + a.y * b.w, a.z * b.x + a.w * b.z, a.z * b.y + a.w * b.w);
93 }
94 
95 /* Determinant of a 2x2 matrix encoded in a row-major order float4 */
96 ccl_device_inline float mat22_determinant(const float4 m)
97 {
98  return m.x * m.w - m.y * m.z;
99 }
100 
101 /* Inverse of a 2x2 matrix encoded in a row-major order float4 */
102 ccl_device_inline float mat22_inverse(const float4 m, ccl_private float4 &m_inverse)
103 {
104  float det = mat22_determinant(m);
105  if (fabsf(det) < MNEE_MIN_DETERMINANT)
106  return 0.f;
107  m_inverse = make_float4(m.w, -m.y, -m.z, m.x) / det;
108  return det;
109 }
110 
111 /* Update light sample */
112 ccl_device_forceinline void mnee_update_light_sample(KernelGlobals kg,
113  const float3 P,
115 {
116  /* correct light sample position/direction and pdf
117  * NOTE: preserve pdf in area measure */
118  const ccl_global KernelLight *klight = &kernel_data_fetch(lights, ls->lamp);
119 
120  if (ls->type == LIGHT_POINT || ls->type == LIGHT_SPOT) {
121  ls->D = normalize_len(ls->P - P, &ls->t);
122  ls->Ng = -ls->D;
123 
124  float2 uv = map_to_sphere(ls->Ng);
125  ls->u = uv.x;
126  ls->v = uv.y;
127 
128  float invarea = klight->spot.invarea;
129  ls->eval_fac = (0.25f * M_1_PI_F) * invarea;
130  ls->pdf = invarea;
131 
132  if (ls->type == LIGHT_SPOT) {
133  /* spot light attenuation */
134  float3 dir = make_float3(klight->spot.dir[0], klight->spot.dir[1], klight->spot.dir[2]);
135  ls->eval_fac *= spot_light_attenuation(
136  dir, klight->spot.spot_angle, klight->spot.spot_smooth, ls->Ng);
137  }
138  }
139  else if (ls->type == LIGHT_AREA) {
140  float invarea = fabsf(klight->area.invarea);
141  ls->D = normalize_len(ls->P - P, &ls->t);
142  ls->pdf = invarea;
143  if (klight->area.tan_spread > 0.f) {
144  ls->eval_fac = 0.25f * invarea;
145  ls->eval_fac *= light_spread_attenuation(
146  ls->D, ls->Ng, klight->area.tan_spread, klight->area.normalize_spread);
147  }
148  }
149 
150  ls->pdf *= kernel_data.integrator.pdf_lights;
151 }
152 
153 /* Manifold vertex setup from ray and intersection data */
154 ccl_device_forceinline void mnee_setup_manifold_vertex(KernelGlobals kg,
155  ccl_private ManifoldVertex *vtx,
157  const float eta,
158  const float2 n_offset,
159  ccl_private const Ray *ray,
160  ccl_private const Intersection *isect,
161  ccl_private ShaderData *sd_vtx)
162 {
163  sd_vtx->object = (isect->object == OBJECT_NONE) ? kernel_data_fetch(prim_object, isect->prim) :
164  isect->object;
165 
166  sd_vtx->type = isect->type;
167  sd_vtx->flag = 0;
168  sd_vtx->object_flag = kernel_data_fetch(object_flag, sd_vtx->object);
169 
170  /* Matrices and time. */
171  shader_setup_object_transforms(kg, sd_vtx, ray->time);
172  sd_vtx->time = ray->time;
173 
174  sd_vtx->prim = isect->prim;
175  sd_vtx->ray_length = isect->t;
176 
177  sd_vtx->u = isect->u;
178  sd_vtx->v = isect->v;
179 
180  sd_vtx->shader = kernel_data_fetch(tri_shader, sd_vtx->prim);
181 
182  float3 verts[3];
183  float3 normals[3];
184  if (sd_vtx->type & PRIMITIVE_TRIANGLE) {
185  /* Load triangle vertices and normals. */
186  triangle_vertices_and_normals(kg, sd_vtx->prim, verts, normals);
187 
188  /* Compute refined position (same code as in triangle_point_from_uv). */
189  sd_vtx->P = (1.f - isect->u - isect->v) * verts[0] + isect->u * verts[1] + isect->v * verts[2];
190  if (!(sd_vtx->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
191  const Transform tfm = object_get_transform(kg, sd_vtx);
192  sd_vtx->P = transform_point(&tfm, sd_vtx->P);
193  }
194  }
195  else { /* if (sd_vtx->type & PRIMITIVE_MOTION_TRIANGLE) */
196  /* Load triangle vertices and normals. */
198  kg, sd_vtx->object, sd_vtx->prim, sd_vtx->time, verts, normals);
199 
200  /* Compute refined position. */
201  sd_vtx->P = motion_triangle_point_from_uv(
202  kg, sd_vtx, isect->object, isect->prim, isect->u, isect->v, verts);
203  }
204 
205  /* Instance transform. */
206  if (!(sd_vtx->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
207  object_position_transform_auto(kg, sd_vtx, &verts[0]);
208  object_position_transform_auto(kg, sd_vtx, &verts[1]);
209  object_position_transform_auto(kg, sd_vtx, &verts[2]);
210  object_normal_transform_auto(kg, sd_vtx, &normals[0]);
211  object_normal_transform_auto(kg, sd_vtx, &normals[1]);
212  object_normal_transform_auto(kg, sd_vtx, &normals[2]);
213  }
214 
215  /* Tangent space (position derivatives) WRT barycentric (u, v). */
216  float3 dp_du = verts[1] - verts[0];
217  float3 dp_dv = verts[2] - verts[0];
218 
219  /* Geometric normal. */
220  vtx->ng = normalize(cross(dp_du, dp_dv));
221  if (sd_vtx->object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED)
222  vtx->ng = -vtx->ng;
223 
224  /* Shading normals: Interpolate normals between vertices. */
225  float n_len;
226  vtx->n = normalize_len(normals[0] * (1.0f - sd_vtx->u - sd_vtx->v) + normals[1] * sd_vtx->u +
227  normals[2] * sd_vtx->v,
228  &n_len);
229 
230  /* Shading normal derivatives WRT barycentric (u, v)
231  * we calculate the derivative of n = |u*n0 + v*n1 + (1-u-v)*n2| using:
232  * d/du [f(u)/|f(u)|] = [d/du f(u)]/|f(u)| - f(u)/|f(u)|^3 <f(u), d/du f(u)>. */
233  const float inv_n_len = 1.f / n_len;
234  float3 dn_du = inv_n_len * (normals[1] - normals[0]);
235  float3 dn_dv = inv_n_len * (normals[2] - normals[0]);
236  dn_du -= vtx->n * dot(vtx->n, dn_du);
237  dn_dv -= vtx->n * dot(vtx->n, dn_dv);
238 
239  /* Orthonormalize (dp_du,dp_dv) using a linear transformation, which
240  * we use on (dn_du,dn_dv) as well so the new (u,v) are consistent. */
241  const float inv_len_dp_du = 1.f / len(dp_du);
242  dp_du *= inv_len_dp_du;
243  dn_du *= inv_len_dp_du;
244 
245  const float dpdu_dot_dpdv = dot(dp_du, dp_dv);
246  dp_dv -= dpdu_dot_dpdv * dp_du;
247  dn_dv -= dpdu_dot_dpdv * dn_du;
248 
249  const float inv_len_dp_dv = 1.f / len(dp_dv);
250  dp_dv *= inv_len_dp_dv;
251  dn_dv *= inv_len_dp_dv;
252 
253  /* Find consistent tangent frame for every point on the surface. */
254  make_orthonormals(vtx->ng, &vtx->dp_du, &vtx->dp_dv);
255  /* Apply the equivalent rotation to the normal derivatives. */
256  const float cos_theta = dot(dp_du, vtx->dp_du);
257  const float sin_theta = -dot(dp_dv, vtx->dp_du);
258  vtx->dn_du = cos_theta * dn_du - sin_theta * dn_dv;
259  vtx->dn_dv = sin_theta * dn_du + cos_theta * dn_dv;
260 
261  /* Manifold vertex position. */
262  vtx->p = sd_vtx->P;
263 
264  /* Initialize constraint and its derivates. */
265  vtx->a = vtx->c = zero_float4();
266  vtx->b = make_float4(1.f, 0.f, 0.f, 1.f);
267  vtx->constraint = zero_float2();
268  vtx->n_offset = n_offset;
269 
270  /* Closure information. */
271  vtx->bsdf = bsdf;
272  vtx->eta = eta;
273 
274  /* Geometric information. */
275  vtx->uv = make_float2(isect->u, isect->v);
276  vtx->object = sd_vtx->object;
277  vtx->prim = sd_vtx->prim;
278  vtx->shader = sd_vtx->shader;
279 }
280 
281 /* Compute constraint derivatives. */
282 ccl_device_forceinline bool mnee_compute_constraint_derivatives(
283  int vertex_count,
284  ccl_private ManifoldVertex *vertices,
285  ccl_private const float3 &surface_sample_pos,
286  const bool light_fixed_direction,
287  const float3 light_sample)
288 {
289  for (int vi = 0; vi < vertex_count; vi++) {
290  ccl_private ManifoldVertex &v = vertices[vi];
291 
292  /* Direction toward surface sample. */
293  float3 wi = (vi == 0) ? surface_sample_pos - v.p : vertices[vi - 1].p - v.p;
294  float ili = len(wi);
295  if (ili < MNEE_MIN_DISTANCE)
296  return false;
297  ili = 1.f / ili;
298  wi *= ili;
299 
300  /* Direction toward light sample. */
301  float3 wo = (vi == vertex_count - 1) ?
302  (light_fixed_direction ? light_sample : light_sample - v.p) :
303  vertices[vi + 1].p - v.p;
304  float ilo = len(wo);
305  if (ilo < MNEE_MIN_DISTANCE)
306  return false;
307  ilo = 1.f / ilo;
308  wo *= ilo;
309 
310  /* Invert ior if coming from inside. */
311  float eta = v.eta;
312  if (dot(wi, v.ng) < .0f)
313  eta = 1.f / eta;
314 
315  /* Half vector. */
316  float3 H = -(wi + eta * wo);
317  float ilh = 1.f / len(H);
318  H *= ilh;
319 
320  ilo *= eta * ilh;
321  ili *= ilh;
322 
323  /* Local shading frame. */
324  float dp_du_dot_n = dot(v.dp_du, v.n);
325  float3 s = v.dp_du - dp_du_dot_n * v.n;
326  float inv_len_s = 1.f / len(s);
327  s *= inv_len_s;
328  float3 t = cross(v.n, s);
329 
330  float3 dH_du, dH_dv;
331 
332  /* Constraint derivatives WRT previous vertex. */
333  if (vi > 0) {
334  ccl_private ManifoldVertex &v_prev = vertices[vi - 1];
335  dH_du = (v_prev.dp_du - wi * dot(wi, v_prev.dp_du)) * ili;
336  dH_dv = (v_prev.dp_dv - wi * dot(wi, v_prev.dp_dv)) * ili;
337  dH_du -= H * dot(dH_du, H);
338  dH_dv -= H * dot(dH_dv, H);
339  dH_du = -dH_du;
340  dH_dv = -dH_dv;
341 
342  v.a = make_float4(dot(dH_du, s), dot(dH_dv, s), dot(dH_du, t), dot(dH_dv, t));
343  }
344 
345  /* Constraint derivatives WRT current vertex. */
346  if (vi == vertex_count - 1 && light_fixed_direction) {
347  dH_du = ili * (-v.dp_du + wi * dot(wi, v.dp_du));
348  dH_dv = ili * (-v.dp_dv + wi * dot(wi, v.dp_dv));
349  }
350  else {
351  dH_du = -v.dp_du * (ili + ilo) + wi * (dot(wi, v.dp_du) * ili) +
352  wo * (dot(wo, v.dp_du) * ilo);
353  dH_dv = -v.dp_dv * (ili + ilo) + wi * (dot(wi, v.dp_dv) * ili) +
354  wo * (dot(wo, v.dp_dv) * ilo);
355  }
356  dH_du -= H * dot(dH_du, H);
357  dH_dv -= H * dot(dH_dv, H);
358  dH_du = -dH_du;
359  dH_dv = -dH_dv;
360 
361  float3 ds_du = -inv_len_s * (dot(v.dp_du, v.dn_du) * v.n + dp_du_dot_n * v.dn_du);
362  float3 ds_dv = -inv_len_s * (dot(v.dp_du, v.dn_dv) * v.n + dp_du_dot_n * v.dn_dv);
363  ds_du -= s * dot(s, ds_du);
364  ds_dv -= s * dot(s, ds_dv);
365  float3 dt_du = cross(v.dn_du, s) + cross(v.n, ds_du);
366  float3 dt_dv = cross(v.dn_dv, s) + cross(v.n, ds_dv);
367 
368  v.b = make_float4(dot(dH_du, s) + dot(H, ds_du),
369  dot(dH_dv, s) + dot(H, ds_dv),
370  dot(dH_du, t) + dot(H, dt_du),
371  dot(dH_dv, t) + dot(H, dt_dv));
372 
373  /* Constraint derivatives WRT next vertex. */
374  if (vi < vertex_count - 1) {
375  ccl_private ManifoldVertex &v_next = vertices[vi + 1];
376  dH_du = (v_next.dp_du - wo * dot(wo, v_next.dp_du)) * ilo;
377  dH_dv = (v_next.dp_dv - wo * dot(wo, v_next.dp_dv)) * ilo;
378  dH_du -= H * dot(dH_du, H);
379  dH_dv -= H * dot(dH_dv, H);
380  dH_du = -dH_du;
381  dH_dv = -dH_dv;
382 
383  v.c = make_float4(dot(dH_du, s), dot(dH_dv, s), dot(dH_du, t), dot(dH_dv, t));
384  }
385 
386  /* Constraint vector WRT. the local shading frame. */
387  v.constraint = make_float2(dot(s, H), dot(t, H)) - v.n_offset;
388  }
389  return true;
390 }
391 
392 /* Invert (block) constraint derivative matrix and solve linear system so we can map dh back to dx:
393  * dh / dx = A
394  * dx = inverse(A) x dh
395  * to use for specular specular manifold walk
396  * (See for example http://faculty.washington.edu/finlayso/ebook/algebraic/advanced/LUtri.htm
397  * for block tridiagonal matrix based linear system solve) */
398 ccl_device_forceinline bool mnee_solve_matrix_h_to_x(int vertex_count,
399  ccl_private ManifoldVertex *vertices,
400  ccl_private float2 *dx)
401 {
402  float4 Li[MNEE_MAX_CAUSTIC_CASTERS];
403  float2 C[MNEE_MAX_CAUSTIC_CASTERS];
404 
405  /* Block tridiagonal LU factorization. */
406  float4 Lk = vertices[0].b;
407  if (mat22_inverse(Lk, Li[0]) == 0.f)
408  return false;
409 
410  C[0] = vertices[0].constraint;
411 
412  for (int k = 1; k < vertex_count; k++) {
413  float4 A = mat22_mult(vertices[k].a, Li[k - 1]);
414 
415  Lk = vertices[k].b - mat22_mult(A, vertices[k - 1].c);
416  if (mat22_inverse(Lk, Li[k]) == 0.f)
417  return false;
418 
419  C[k] = vertices[k].constraint - mat22_mult(A, C[k - 1]);
420  }
421 
422  dx[vertex_count - 1] = mat22_mult(Li[vertex_count - 1], C[vertex_count - 1]);
423  for (int k = vertex_count - 2; k > -1; k--)
424  dx[k] = mat22_mult(Li[k], C[k] - mat22_mult(vertices[k].c, dx[k + 1]));
425 
426  return true;
427 }
428 
429 /* Newton solver to walk on specular manifold. */
430 ccl_device_forceinline bool mnee_newton_solver(KernelGlobals kg,
431  ccl_private const ShaderData *sd,
432  ccl_private ShaderData *sd_vtx,
433  ccl_private const LightSample *ls,
434  int vertex_count,
435  ccl_private ManifoldVertex *vertices)
436 {
437  float2 dx[MNEE_MAX_CAUSTIC_CASTERS];
438  ManifoldVertex tentative[MNEE_MAX_CAUSTIC_CASTERS];
439 
440  Ray projection_ray;
441  projection_ray.self.light_object = OBJECT_NONE;
442  projection_ray.self.light_prim = PRIM_NONE;
443  projection_ray.dP = differential_make_compact(sd->dP);
444  projection_ray.dD = differential_zero_compact();
445  projection_ray.tmin = 0.0f;
446  projection_ray.time = sd->time;
447  Intersection projection_isect;
448 
449  const bool light_fixed_direction = (ls->t == FLT_MAX);
450  const float3 light_sample = light_fixed_direction ? ls->D : ls->P;
451 
452  /* We start gently, potentially ramping up to beta = 1, since target configurations
453  * far from the seed path can send the proposed solution further than the linearized
454  * local differential geometric quantities are meant for (especially dn/du and dn/dv). */
455  float beta = .1f;
456  bool reduce_stepsize = false;
457  bool resolve_constraint = true;
458  for (int iteration = 0; iteration < MNEE_MAX_ITERATIONS; iteration++) {
459  if (resolve_constraint) {
460  /* Calculate constraint and its derivatives for vertices. */
461  if (!mnee_compute_constraint_derivatives(
462  vertex_count, vertices, sd->P, light_fixed_direction, light_sample))
463  return false;
464 
465  /* Calculate constraint norm. */
466  float constraint_norm = 0.f;
467  for (int vi = 0; vi < vertex_count; vi++)
468  constraint_norm = fmaxf(constraint_norm, len(vertices[vi].constraint));
469 
470  /* Return if solve successful. */
471  if (constraint_norm < MNEE_SOLVER_THRESHOLD)
472  return true;
473 
474  /* Invert derivative matrix. */
475  if (!mnee_solve_matrix_h_to_x(vertex_count, vertices, dx))
476  return false;
477  }
478 
479  /* Construct tentative new vertices and project back onto surface. */
480  for (int vi = 0; vi < vertex_count; vi++) {
481  ccl_private ManifoldVertex &mv = vertices[vi];
482 
483  /* Tentative new position on linearized manifold (tangent plane). */
484  float3 tentative_p = mv.p - beta * (dx[vi].x * mv.dp_du + dx[vi].y * mv.dp_dv);
485 
486  /* For certain configs, the first solve ends up below the receiver. */
487  if (vi == 0) {
488  const float3 wo = tentative_p - sd->P;
489  if (dot(sd->Ng, wo) <= 0.f) {
490  /* Change direction for the 1st interface. */
491  tentative_p = mv.p + beta * (dx[vi].x * mv.dp_du + dx[vi].y * mv.dp_dv);
492  }
493  }
494 
495  /* Project tentative point from tangent plane back to surface
496  * we ignore all other intersections since this tentative path could lead
497  * valid to a valid path even if occluded. */
498  if (vi == 0) {
499  projection_ray.self.object = sd->object;
500  projection_ray.self.prim = sd->prim;
501  projection_ray.P = sd->P;
502  }
503  else {
504  ccl_private const ManifoldVertex &pv = vertices[vi - 1];
505  projection_ray.self.object = pv.object;
506  projection_ray.self.prim = pv.prim;
507  projection_ray.P = pv.p;
508  }
509  projection_ray.D = normalize_len(tentative_p - projection_ray.P, &projection_ray.tmax);
510  projection_ray.tmax *= MNEE_PROJECTION_DISTANCE_MULTIPLIER;
511 
512  bool projection_success = false;
513  for (int isect_count = 0; isect_count < MNEE_MAX_INTERSECTION_COUNT; isect_count++) {
514  bool hit = scene_intersect(kg, &projection_ray, PATH_RAY_TRANSMIT, &projection_isect);
515  if (!hit)
516  break;
517 
518  int hit_object = (projection_isect.object == OBJECT_NONE) ?
519  kernel_data_fetch(prim_object, projection_isect.prim) :
520  projection_isect.object;
521 
522  if (hit_object == mv.object) {
523  projection_success = true;
524  break;
525  }
526 
527  projection_ray.self.object = projection_isect.object;
528  projection_ray.self.prim = projection_isect.prim;
529  projection_ray.tmin = intersection_t_offset(projection_isect.t);
530  }
531  if (!projection_success) {
532  reduce_stepsize = true;
533  break;
534  }
535 
536  /* Initialize tangent frame, which will be used as reference. */
537  ccl_private ManifoldVertex &tv = tentative[vi];
538  tv.p = mv.p;
539  tv.dp_du = mv.dp_du;
540  tv.dp_dv = mv.dp_dv;
541 
542  /* Setup corrected manifold vertex. */
543  mnee_setup_manifold_vertex(
544  kg, &tv, mv.bsdf, mv.eta, mv.n_offset, &projection_ray, &projection_isect, sd_vtx);
545 
546  /* Fail newton solve if we are not making progress, probably stuck trying to move off the
547  * edge of the mesh. */
548  const float distance = len(tv.p - mv.p);
549  if (distance < MNEE_MIN_PROGRESS_DISTANCE)
550  return false;
551  }
552 
553  /* Check that tentative path is still transmissive. */
554  if (!reduce_stepsize) {
555  for (int vi = 0; vi < vertex_count; vi++) {
556  ccl_private ManifoldVertex &tv = tentative[vi];
557 
558  /* Direction toward surface sample. */
559  const float3 wi = (vi == 0 ? sd->P : tentative[vi - 1].p) - tv.p;
560  /* Direction toward light sample. */
561  const float3 wo = (vi == vertex_count - 1) ? light_fixed_direction ? ls->D : ls->P - tv.p :
562  tentative[vi + 1].p - tv.p;
563 
564  if (dot(tv.n, wi) * dot(tv.n, wo) >= 0.f) {
565  reduce_stepsize = true;
566  break;
567  }
568  }
569  }
570 
571  if (reduce_stepsize) {
572  /* Adjust step if can't land on right surface. */
573  reduce_stepsize = false;
574  resolve_constraint = false;
575  beta *= .5f;
576 
577  /* Fail newton solve if the stepsize is too small. */
578  if (beta < MNEE_MINIMUM_STEP_SIZE)
579  return false;
580 
581  continue;
582  }
583 
584  /* Copy tentative vertices to main vertex list. */
585  for (int vi = 0; vi < vertex_count; vi++)
586  vertices[vi] = tentative[vi];
587 
588  /* Increase the step to get back to 1. */
589  resolve_constraint = true;
590  beta = min(1.f, 2.f * beta);
591  }
592 
593  return false;
594 }
595 
596 /* Sample bsdf in half-vector measure. */
598 mnee_sample_bsdf_dh(ClosureType type, float alpha_x, float alpha_y, float sample_u, float sample_v)
599 {
600  float alpha2;
601  float cos_phi, sin_phi;
602 
603  if (alpha_x == alpha_y) {
604  float phi = sample_v * M_2PI_F;
605  fast_sincosf(phi, &sin_phi, &cos_phi);
606  alpha2 = alpha_x * alpha_x;
607  }
608  else {
609  float phi = atanf(alpha_y / alpha_x * tanf(M_2PI_F * sample_v + M_PI_2_F));
610  if (sample_v > .5f)
611  phi += M_PI_F;
612  fast_sincosf(phi, &sin_phi, &cos_phi);
613  float alpha_x2 = alpha_x * alpha_x;
614  float alpha_y2 = alpha_y * alpha_y;
615  alpha2 = 1.f / (cos_phi * cos_phi / alpha_x2 + sin_phi * sin_phi / alpha_y2);
616  }
617 
618  /* Map sampled angles to micro-normal direction h. */
619  float tan2_theta = alpha2;
621  tan2_theta *= -logf(1.0f - sample_u);
622  }
623  else { /* type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID assumed */
624  tan2_theta *= sample_u / (1.0f - sample_u);
625  }
626  float cos2_theta = 1.0f / (1.0f + tan2_theta);
627  float sin_theta = safe_sqrtf(1.0f - cos2_theta);
628  return make_float2(cos_phi * sin_theta, sin_phi * sin_theta);
629 }
630 
631 /* Evaluate product term inside eq.6 at solution interface vi
632  * divided by corresponding sampled pdf:
633  * fr(vi)_do / pdf_dh(vi) x |do/dh| x |n.wo / n.h|
634  * We assume here that the pdf (in half-vector measure) is the same as
635  * the one calculation when sampling the microfacet normals from the
636  * specular chain above: this allows us to simplify the bsdf weight */
637 ccl_device_forceinline float3 mnee_eval_bsdf_contribution(ccl_private ShaderClosure *closure,
638  float3 wi,
639  float3 wo)
640 {
642 
643  float cosNO = dot(bsdf->N, wi);
644  float cosNI = dot(bsdf->N, wo);
645 
646  float3 Ht = normalize(-(bsdf->ior * wo + wi));
647  float cosHO = dot(Ht, wi);
648 
649  float alpha2 = bsdf->alpha_x * bsdf->alpha_y;
650  float cosThetaM = dot(bsdf->N, Ht);
651 
652  float G;
654  /* Eq. 26, 27: now calculate G1(i,m) and G1(o,m). */
655  G = bsdf_beckmann_G1(bsdf->alpha_x, cosNO) * bsdf_beckmann_G1(bsdf->alpha_x, cosNI);
656  }
657  else { /* bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID assumed */
658  /* Eq. 34: now calculate G1(i,m) and G1(o,m). */
659  G = (2.f / (1.f + safe_sqrtf(1.f + alpha2 * (1.f - cosNO * cosNO) / (cosNO * cosNO)))) *
660  (2.f / (1.f + safe_sqrtf(1.f + alpha2 * (1.f - cosNI * cosNI) / (cosNI * cosNI))));
661  }
662 
663  /*
664  * bsdf_do = (1 - F) * D_do * G * |h.wi| / (n.wi * n.wo)
665  * pdf_dh = D_dh * cosThetaM
666  * D_do = D_dh * |dh/do|
667  *
668  * contribution = bsdf_do * |do/dh| * |n.wo / n.h| / pdf_dh
669  * = (1 - F) * G * |h.wi / (n.wi * n.h^2)|
670  */
671  return bsdf->weight * G * fabsf(cosHO / (cosNO * sqr(cosThetaM)));
672 }
673 
674 /* Compute transfer matrix determinant |T1| = |dx1/dxn| (and |dh/dx| in the process) */
675 ccl_device_forceinline bool mnee_compute_transfer_matrix(ccl_private const ShaderData *sd,
676  ccl_private const LightSample *ls,
677  int vertex_count,
678  ccl_private ManifoldVertex *vertices,
679  ccl_private float *dx1_dxlight,
680  ccl_private float *dh_dx)
681 {
682  /* Simplified block tridiagonal LU factorization. */
683  float4 Li;
684  float4 U[MNEE_MAX_CAUSTIC_CASTERS - 1];
685 
686  float4 Lk = vertices[0].b;
687  float Lk_det = mat22_inverse(Lk, Li);
688  if (Lk_det == 0.f)
689  return false;
690 
691  float det_dh_dx = Lk_det;
692 
693  for (int k = 1; k < vertex_count; k++) {
694  U[k - 1] = mat22_mult(Li, vertices[k - 1].c);
695 
696  Lk = vertices[k].b - mat22_mult(vertices[k].a, U[k - 1]);
697  Lk_det = mat22_inverse(Lk, Li);
698  if (Lk_det == 0.f)
699  return false;
700 
701  det_dh_dx *= Lk_det;
702  }
703 
704  /* Fill out constraint derivatives WRT light vertex param. */
705 
706  /* Local shading frame at last free vertex. */
707  int mi = vertex_count - 1;
708  ccl_private const ManifoldVertex &m = vertices[mi];
709 
710  float3 s = normalize(m.dp_du - dot(m.dp_du, m.n) * m.n);
711  float3 t = cross(m.n, s);
712 
713  /* Local differential geometry. */
714  float3 dp_du, dp_dv;
715  make_orthonormals(ls->Ng, &dp_du, &dp_dv);
716 
717  /* Direction toward surface sample. */
718  float3 wi = vertex_count == 1 ? sd->P - m.p : vertices[mi - 1].p - m.p;
719  float ili = 1.f / len(wi);
720  wi *= ili;
721 
722  /* Invert ior if coming from inside. */
723  float eta = m.eta;
724  if (dot(wi, m.ng) < .0f)
725  eta = 1.f / eta;
726 
727  float dxn_dwn;
728  float4 dc_dlight;
729 
730  if (ls->t == FLT_MAX) {
731  /* Constant direction toward light sample. */
732  float3 wo = ls->D;
733 
734  /* Half vector. */
735  float3 H = -(wi + eta * wo);
736  float ilh = 1.f / len(H);
737  H *= ilh;
738 
739  float ilo = -eta * ilh;
740 
741  float cos_theta = dot(wo, m.n);
742  float sin_theta = safe_sqrtf(1.f - sqr(cos_theta));
743  float cos_phi = dot(wo, s);
744  float sin_phi = safe_sqrtf(1.f - sqr(cos_phi));
745 
746  /* Wo = (cos_phi * sin_theta) * s + (sin_phi * sin_theta) * t + cos_theta * n. */
747  float3 dH_dtheta = ilo * (cos_theta * (cos_phi * s + sin_phi * t) - sin_theta * m.n);
748  float3 dH_dphi = ilo * sin_theta * (-sin_phi * s + cos_phi * t);
749  dH_dtheta -= H * dot(dH_dtheta, H);
750  dH_dphi -= H * dot(dH_dphi, H);
751 
752  /* Constraint derivatives WRT light direction expressed
753  * in spherical coordinates (theta, phi). */
754  dc_dlight = make_float4(
755  dot(dH_dtheta, s), dot(dH_dphi, s), dot(dH_dtheta, t), dot(dH_dphi, t));
756 
757  /* Jacobian to convert dtheta x dphi to dw measure. */
758  dxn_dwn = 1.f / fmaxf(MNEE_MIN_DISTANCE, fabsf(sin_theta));
759  }
760  else {
761  /* Direction toward light sample. */
762  float3 wo = ls->P - m.p;
763  float ilo = 1.f / len(wo);
764  wo *= ilo;
765 
766  /* Half vector. */
767  float3 H = -(wi + eta * wo);
768  float ilh = 1.f / len(H);
769  H *= ilh;
770 
771  ilo *= eta * ilh;
772 
773  float3 dH_du = (dp_du - wo * dot(wo, dp_du)) * ilo;
774  float3 dH_dv = (dp_dv - wo * dot(wo, dp_dv)) * ilo;
775  dH_du -= H * dot(dH_du, H);
776  dH_dv -= H * dot(dH_dv, H);
777  dH_du = -dH_du;
778  dH_dv = -dH_dv;
779 
780  dc_dlight = make_float4(dot(dH_du, s), dot(dH_dv, s), dot(dH_du, t), dot(dH_dv, t));
781 
782  /* Neutral value since dc_dlight is already in the desired vertex area measure. */
783  dxn_dwn = 1.f;
784  }
785 
786  /* Compute transfer matrix. */
787  float4 Tp = -mat22_mult(Li, dc_dlight);
788  for (int k = vertex_count - 2; k > -1; k--)
789  Tp = -mat22_mult(U[k], Tp);
790 
791  *dx1_dxlight = fabsf(mat22_determinant(Tp)) * dxn_dwn;
792  *dh_dx = fabsf(det_dh_dx);
793  return true;
794 }
795 
796 /* Calculate the path contribution. */
797 ccl_device_forceinline bool mnee_path_contribution(KernelGlobals kg,
800  ccl_private ShaderData *sd_mnee,
802  int vertex_count,
803  ccl_private ManifoldVertex *vertices,
804  ccl_private BsdfEval *throughput)
805 {
806  float wo_len;
807  float3 wo = normalize_len(vertices[0].p - sd->P, &wo_len);
808 
809  /* Initialize throughput and evaluate receiver bsdf * |n.wo|. */
810  shader_bsdf_eval(kg, sd, wo, false, throughput, ls->shader);
811 
812  /* Update light sample with new position / direct.ion
813  * and keep pdf in vertex area measure */
814  mnee_update_light_sample(kg, vertices[vertex_count - 1].p, ls);
815 
816  /* Save state path bounce info in case a light path node is used in the refractive interface or
817  * light shader graph. */
818  const int transmission_bounce = INTEGRATOR_STATE(state, path, transmission_bounce);
819  const int diffuse_bounce = INTEGRATOR_STATE(state, path, diffuse_bounce);
820  const int bounce = INTEGRATOR_STATE(state, path, bounce);
821 
822  /* Set diffuse bounce info . */
823  INTEGRATOR_STATE_WRITE(state, path, diffuse_bounce) = diffuse_bounce + 1;
824 
825  /* Evaluate light sample
826  * in case the light has a node-based shader:
827  * 1. sd_mnee will be used to store light data, which is why we need to do
828  * this evaluation here. sd_mnee needs to contain the solution's last
829  * interface data at the end of the call for the shadow ray setup to work.
830  * 2. ls needs to contain the last interface data for the light shader to
831  * evaluate properly */
832 
833  /* Set bounce info in case a light path node is used in the light shader graph. */
834  INTEGRATOR_STATE_WRITE(state, path, transmission_bounce) = transmission_bounce + vertex_count -
835  1;
836  INTEGRATOR_STATE_WRITE(state, path, bounce) = bounce + vertex_count;
837 
838  float3 light_eval = light_sample_shader_eval(kg, state, sd_mnee, ls, sd->time);
839  bsdf_eval_mul(throughput, light_eval / ls->pdf);
840 
841  /* Generalized geometry term. */
842 
843  float dh_dx;
844  float dx1_dxlight;
845  if (!mnee_compute_transfer_matrix(sd, ls, vertex_count, vertices, &dx1_dxlight, &dh_dx))
846  return false;
847 
848  /* Receiver bsdf eval above already contains |n.wo|. */
849  const float dw0_dx1 = fabsf(dot(wo, vertices[0].n)) / sqr(wo_len);
850 
851  /* Clamp since it has a tendency to be unstable. */
852  const float G = fminf(dw0_dx1 * dx1_dxlight, 2.f);
853  bsdf_eval_mul(throughput, G);
854 
855  /* Specular reflectance. */
856 
857  /* Probe ray / isect. */
858  Ray probe_ray;
859  probe_ray.self.light_object = ls->object;
860  probe_ray.self.light_prim = ls->prim;
861  probe_ray.tmin = 0.0f;
862  probe_ray.dP = differential_make_compact(sd->dP);
863  probe_ray.dD = differential_zero_compact();
864  probe_ray.time = sd->time;
865  Intersection probe_isect;
866 
867  probe_ray.self.object = sd->object;
868  probe_ray.self.prim = sd->prim;
869  probe_ray.P = sd->P;
870 
871  float3 wi;
872  float wi_len;
873  for (int vi = 0; vi < vertex_count; vi++) {
874  ccl_private const ManifoldVertex &v = vertices[vi];
875 
876  /* Check visibility. */
877  probe_ray.D = normalize_len(v.p - probe_ray.P, &probe_ray.tmax);
878  if (scene_intersect(kg, &probe_ray, PATH_RAY_TRANSMIT, &probe_isect)) {
879  int hit_object = (probe_isect.object == OBJECT_NONE) ?
880  kernel_data_fetch(prim_object, probe_isect.prim) :
881  probe_isect.object;
882  /* Test whether the ray hit the appropriate object at its intended location. */
883  if (hit_object != v.object || fabsf(probe_ray.tmax - probe_isect.t) > MNEE_MIN_DISTANCE)
884  return false;
885  }
886  probe_ray.self.object = v.object;
887  probe_ray.self.prim = v.prim;
888  probe_ray.P = v.p;
889 
890  /* Set view looking dir. */
891  wi = -wo;
892  wi_len = wo_len;
893 
894  /* Setup shader data for vertex vi. */
896  sd_mnee,
897  v.p,
898  v.n,
899  wi,
900  v.shader,
901  v.object,
902  v.prim,
903  v.uv.x,
904  v.uv.y,
905  wi_len,
906  sd->time,
907  false,
908  LAMP_NONE);
909 
910  /* Set bounce info in case a light path node is used in the refractive interface
911  * shader graph. */
912  INTEGRATOR_STATE_WRITE(state, path, transmission_bounce) = transmission_bounce + vi;
913  INTEGRATOR_STATE_WRITE(state, path, bounce) = bounce + 1 + vi;
914 
915  /* Evaluate shader nodes at solution vi. */
916  shader_eval_surface<KERNEL_FEATURE_NODE_MASK_SURFACE_SHADOW>(
917  kg, state, sd_mnee, NULL, PATH_RAY_DIFFUSE, true);
918 
919  /* Set light looking dir. */
920  wo = (vi == vertex_count - 1) ? (ls->t == FLT_MAX ? ls->D : ls->P - v.p) :
921  vertices[vi + 1].p - v.p;
922  wo = normalize_len(wo, &wo_len);
923 
924  /* Evaluate product term inside eq.6 at solution interface. vi
925  * divided by corresponding sampled pdf:
926  * fr(vi)_do / pdf_dh(vi) x |do/dh| x |n.wo / n.h| */
927  float3 bsdf_contribution = mnee_eval_bsdf_contribution(v.bsdf, wi, wo);
928  bsdf_eval_mul(throughput, bsdf_contribution);
929  }
930 
931  /* Restore original state path bounce info. */
932  INTEGRATOR_STATE_WRITE(state, path, transmission_bounce) = transmission_bounce;
933  INTEGRATOR_STATE_WRITE(state, path, diffuse_bounce) = diffuse_bounce;
934  INTEGRATOR_STATE_WRITE(state, path, bounce) = bounce;
935 
936  return true;
937 }
938 
939 /* Manifold next event estimation path sampling. */
940 ccl_device_forceinline int kernel_path_mnee_sample(KernelGlobals kg,
943  ccl_private ShaderData *sd_mnee,
944  ccl_private const RNGState *rng_state,
946  ccl_private BsdfEval *throughput)
947 {
948  /*
949  * 1. send seed ray from shading point to light sample position (or along sampled light
950  * direction), making sure it intersects a caustic caster at least once, ignoring all other
951  * intersections (the final path could be valid even though objects could occlude the light
952  * this seed point), building an array of manifold vertices.
953  */
954 
955  /* Setup probe ray. */
956  Ray probe_ray;
957  probe_ray.self.object = sd->object;
958  probe_ray.self.prim = sd->prim;
959  probe_ray.self.light_object = ls->object;
960  probe_ray.self.light_prim = ls->prim;
961  probe_ray.P = sd->P;
962  probe_ray.tmin = 0.0f;
963  if (ls->t == FLT_MAX) {
964  /* Distant / env light. */
965  probe_ray.D = ls->D;
966  probe_ray.tmax = ls->t;
967  }
968  else {
969  /* Other lights, avoid self-intersection. */
970  probe_ray.D = ls->P - probe_ray.P;
971  probe_ray.D = normalize_len(probe_ray.D, &probe_ray.tmax);
972  }
973  probe_ray.dP = differential_make_compact(sd->dP);
974  probe_ray.dD = differential_zero_compact();
975  probe_ray.time = sd->time;
976  Intersection probe_isect;
977 
978  ManifoldVertex vertices[MNEE_MAX_CAUSTIC_CASTERS];
979 
980  int vertex_count = 0;
981  for (int isect_count = 0; isect_count < MNEE_MAX_INTERSECTION_COUNT; isect_count++) {
982  bool hit = scene_intersect(kg, &probe_ray, PATH_RAY_TRANSMIT, &probe_isect);
983  if (!hit)
984  break;
985 
986  const int object_flags = intersection_get_object_flags(kg, &probe_isect);
987  if (object_flags & SD_OBJECT_CAUSTICS_CASTER) {
988 
989  /* Do we have enough slots. */
990  if (vertex_count >= MNEE_MAX_CAUSTIC_CASTERS)
991  return 0;
992 
993  /* Reject caster if it is not a triangles mesh. */
994  if (!(probe_isect.type & PRIMITIVE_TRIANGLE))
995  return 0;
996 
997  ccl_private ManifoldVertex &mv = vertices[vertex_count++];
998 
999  /* Setup shader data on caustic caster and evaluate context. */
1000  shader_setup_from_ray(kg, sd_mnee, &probe_ray, &probe_isect);
1001 
1002  /* Reject caster if smooth normals are not available: Manifold exploration assumes local
1003  * differential geometry can be created at any point on the surface which is not possible if
1004  * normals are not smooth. */
1005  if (!(sd_mnee->shader & SHADER_SMOOTH_NORMAL))
1006  return 0;
1007 
1008  /* Last bool argument is the MNEE flag (for TINY_MAX_CLOSURE cap in kernel_shader.h). */
1009  shader_eval_surface<KERNEL_FEATURE_NODE_MASK_SURFACE_SHADOW>(
1010  kg, state, sd_mnee, NULL, PATH_RAY_DIFFUSE, true);
1011 
1012  /* Get and sample refraction bsdf */
1013  bool found_transimissive_microfacet_bsdf = false;
1014  for (int ci = 0; ci < sd_mnee->num_closure; ci++) {
1015  ccl_private ShaderClosure *bsdf = &sd_mnee->closure[ci];
1020  bsdf->type == CLOSURE_BSDF_REFRACTION_ID ||
1021  bsdf->type == CLOSURE_BSDF_SHARP_GLASS_ID) {
1022  /* Note that CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID and
1023  * CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID are treated as
1024  * CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID further below. */
1025 
1026  found_transimissive_microfacet_bsdf = true;
1027  ccl_private MicrofacetBsdf *microfacet_bsdf = (ccl_private MicrofacetBsdf *)bsdf;
1028 
1029  /* Figure out appropriate index of refraction ratio. */
1030  const float eta = (sd_mnee->flag & SD_BACKFACING) ? 1.0f / microfacet_bsdf->ior :
1031  microfacet_bsdf->ior;
1032 
1033  float2 h = zero_float2();
1034  if (microfacet_bsdf->alpha_x > 0.f && microfacet_bsdf->alpha_y > 0.f) {
1035  /* Sample transmissive microfacet bsdf. */
1036  float bsdf_u, bsdf_v;
1037  path_state_rng_2D(kg, rng_state, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
1038  h = mnee_sample_bsdf_dh(
1039  bsdf->type, microfacet_bsdf->alpha_x, microfacet_bsdf->alpha_y, bsdf_u, bsdf_v);
1040  }
1041 
1042  /* Setup differential geometry on vertex. */
1043  mnee_setup_manifold_vertex(kg, &mv, bsdf, eta, h, &probe_ray, &probe_isect, sd_mnee);
1044  break;
1045  }
1046  }
1047  if (!found_transimissive_microfacet_bsdf)
1048  return 0;
1049  }
1050 
1051  probe_ray.self.object = probe_isect.object;
1052  probe_ray.self.prim = probe_isect.prim;
1053  probe_ray.tmin = intersection_t_offset(probe_isect.t);
1054  };
1055 
1056  /* Mark the manifold walk invalid to keep mollification on by default. */
1057  INTEGRATOR_STATE_WRITE(state, path, mnee) &= ~PATH_MNEE_VALID;
1058 
1059  if (vertex_count == 0)
1060  return 0;
1061 
1062  /* Check whether the transmission depth limit is reached before continuing. */
1063  if ((INTEGRATOR_STATE(state, path, transmission_bounce) + vertex_count - 1) >=
1064  kernel_data.integrator.max_transmission_bounce)
1065  return 0;
1066 
1067  /* Check whether the diffuse depth limit is reached before continuing. */
1068  if ((INTEGRATOR_STATE(state, path, diffuse_bounce) + 1) >=
1069  kernel_data.integrator.max_diffuse_bounce)
1070  return 0;
1071 
1072  /* Check whether the overall depth limit is reached before continuing. */
1073  if ((INTEGRATOR_STATE(state, path, bounce) + vertex_count) >= kernel_data.integrator.max_bounce)
1074  return 0;
1075 
1076  /* Mark the manifold walk valid to turn off mollification regardless of how successful the walk
1077  * is: this is noticeable when another mnee is performed deeper in the path, for an internally
1078  * reflected ray for example. If mollification was active for the reflection, a clear
1079  * discontinuity is visible between direct and indirect contributions */
1081 
1082  /* 2. Walk on the specular manifold to find vertices on the
1083  * casters that satisfy snell's law for each interface
1084  */
1085  if (mnee_newton_solver(kg, sd, sd_mnee, ls, vertex_count, vertices)) {
1086  /* 3. If a solution exists, calculate contribution of the corresponding path */
1087  if (!mnee_path_contribution(kg, state, sd, sd_mnee, ls, vertex_count, vertices, throughput))
1088  return 0;
1089 
1090  return vertex_count;
1091  }
1092 
1093  return 0;
1094 }
1095 
1097 
1098 #endif /* __MNEE__ */
MINLINE float safe_sqrtf(float a)
void map_to_sphere(float *r_u, float *r_v, float x, float y, float z)
Definition: math_geom.c:4932
_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 type
_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
float float4[4]
#define C
Definition: RandGen.cpp:25
ccl_device_inline void bsdf_eval_mul(ccl_private BsdfEval *eval, float value)
Definition: accumulate.h:58
ATTR_WARN_UNUSED_RESULT const BMVert * v
#define A
ccl_device_inline float bsdf_beckmann_G1(float alpha, float cos_n)
unsigned int U
Definition: btGjkEpa3.h:78
ccl_device float spot_light_attenuation(float3 dir, float spot_angle, float spot_smooth, float3 N)
Definition: common.h:123
ccl_device float light_spread_attenuation(const float3 D, const float3 lightNg, const float tan_spread, const float normalize_spread)
Definition: common.h:140
#define ccl_device_forceinline
Definition: cuda/compat.h:35
#define logf(x)
Definition: cuda/compat.h:105
#define ccl_private
Definition: cuda/compat.h:48
#define ccl_device_inline
Definition: cuda/compat.h:34
#define tanf(x)
Definition: cuda/compat.h:104
#define ccl_global
Definition: cuda/compat.h:43
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
ccl_device_forceinline int intersection_get_object_flags(KernelGlobals kg, ccl_private const Intersection *ccl_restrict isect)
ccl_device_forceinline float intersection_t_offset(const float t)
CCL_NAMESPACE_BEGIN ccl_device_noinline_cpu float3 light_sample_shader_eval(KernelGlobals kg, IntegratorState state, ccl_private ShaderData *ccl_restrict emission_sd, ccl_private LightSample *ccl_restrict ls, float time)
#define kernel_data
const KernelGlobalsCPU *ccl_restrict KernelGlobals
#define kernel_data_fetch(name, index)
ccl_device_forceinline float differential_make_compact(const differential3 D)
Definition: differential.h:117
ccl_device_forceinline float differential_zero_compact()
Definition: differential.h:112
int len
Definition: draw_manager.c:108
static float verts[][3]
CCL_NAMESPACE_END CCL_NAMESPACE_BEGIN ccl_device_inline float3 transform_point(ccl_private const Transform *t, const float3 a)
ccl_device_intersect bool scene_intersect(KernelGlobals kg, ccl_private const Ray *ray, const uint visibility, ccl_private Intersection *isect)
const int state
ccl_device_inline Transform object_get_transform(KernelGlobals kg, ccl_private const ShaderData *sd)
#define object_normal_transform_auto
#define object_position_transform_auto
ccl_device float shader_bsdf_eval(KernelGlobals kg, ccl_private ShaderData *sd, const float3 omega_in, const bool is_transmission, ccl_private BsdfEval *bsdf_eval, const uint light_shader_flags)
ccl_device_inline bool light_sample(KernelGlobals kg, const int lamp, const float randu, const float randv, const float3 P, const uint32_t path_flag, ccl_private LightSample *ls)
ClosureType
@ CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID
@ CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID
@ CLOSURE_BSDF_SHARP_GLASS_ID
@ CLOSURE_BSDF_REFRACTION_ID
@ CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID
@ CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID
@ PATH_MNEE_VALID
Definition: kernel/types.h:293
@ SD_BACKFACING
Definition: kernel/types.h:738
@ PRIMITIVE_TRIANGLE
Definition: kernel/types.h:551
@ PRNG_BSDF_U
Definition: kernel/types.h:164
#define PRIM_NONE
Definition: kernel/types.h:41
@ PATH_RAY_TRANSMIT
Definition: kernel/types.h:196
@ PATH_RAY_DIFFUSE
Definition: kernel/types.h:197
#define OBJECT_NONE
Definition: kernel/types.h:40
ShaderData
Definition: kernel/types.h:925
@ SHADER_SMOOTH_NORMAL
Definition: kernel/types.h:435
@ SD_OBJECT_TRANSFORM_APPLIED
Definition: kernel/types.h:808
@ SD_OBJECT_NEGATIVE_SCALE_APPLIED
Definition: kernel/types.h:810
@ SD_OBJECT_CAUSTICS_CASTER
Definition: kernel/types.h:822
ShaderClosure
Definition: kernel/types.h:726
@ LIGHT_AREA
Definition: kernel/types.h:459
@ LIGHT_SPOT
Definition: kernel/types.h:460
@ LIGHT_POINT
Definition: kernel/types.h:456
#define LAMP_NONE
Definition: kernel/types.h:42
ccl_device void fast_sincosf(float x, ccl_private float *sine, ccl_private float *cosine)
Definition: math_fast.h:134
ccl_device_inline float2 zero_float2()
Definition: math_float2.h:62
ccl_device_inline float2 normalize_len(const float2 &a, float *t)
ccl_device_inline float4 zero_float4()
Definition: math_float4.h:92
static float P(float k)
Definition: math_interp.c:25
#define G(x, y, z)
#define H(x, y, z)
#define fmaxf(x, y)
Definition: metal/compat.h:228
#define make_float2(x, y)
Definition: metal/compat.h:203
#define atanf(x)
Definition: metal/compat.h:223
#define fminf(x, y)
Definition: metal/compat.h:229
#define make_float4(x, y, z, w)
Definition: metal/compat.h:205
#define fabsf(x)
Definition: metal/compat.h:219
#define make_float3(x, y, z)
Definition: metal/compat.h:204
ccl_device_inline void motion_triangle_vertices_and_normals(KernelGlobals kg, int object, int prim, float time, float3 verts[3], float3 normals[3])
CCL_NAMESPACE_BEGIN ccl_device_inline float3 motion_triangle_point_from_uv(KernelGlobals kg, ccl_private ShaderData *sd, const int isect_object, const int isect_prim, const float u, const float v, float3 verts[3])
static unsigned c
Definition: RandGen.cpp:83
static unsigned a[3]
Definition: RandGen.cpp:78
T dot(const vec_base< T, Size > &a, const vec_base< T, Size > &b)
vec_base< T, 3 > cross(const vec_base< T, 3 > &a, const vec_base< T, 3 > &b)
T distance(const T &a, const T &b)
vec_base< T, Size > normalize(const vec_base< T, Size > &v)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
MutableSpan< float3 > normals
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 shader_setup_from_sample(KernelGlobals kg, ccl_private ShaderData *ccl_restrict sd, const float3 P, const float3 Ng, const float3 I, int shader, int object, int prim, float u, float v, float t, float time, bool object_space, int lamp)
Definition: shader_data.h:134
CCL_NAMESPACE_BEGIN ccl_device_inline void shader_setup_from_ray(KernelGlobals kg, ccl_private ShaderData *ccl_restrict sd, ccl_private const Ray *ccl_restrict ray, ccl_private const Intersection *ccl_restrict isect)
Definition: shader_data.h:28
#define min(a, b)
Definition: sort.c:35
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
float tmax
Definition: kernel/types.h:527
float tmin
Definition: kernel/types.h:526
float dD
Definition: kernel/types.h:534
float3 P
Definition: kernel/types.h:524
float time
Definition: kernel/types.h:528
float dP
Definition: kernel/types.h:533
RaySelfPrimitives self
Definition: kernel/types.h:530
float3 D
Definition: kernel/types.h:525
float x
Definition: types_float2.h:15
float y
Definition: types_float2.h:15
ccl_device_inline void triangle_vertices_and_normals(KernelGlobals kg, int prim, float3 P[3], float3 N[3])
Definition: triangle.h:75
#define M_PI_2_F
Definition: util/math.h:37
ccl_device_inline float sqr(float a)
Definition: util/math.h:746
#define M_2PI_F
Definition: util/math.h:60
#define M_1_PI_F
Definition: util/math.h:43
#define M_PI_F
Definition: util/math.h:34
ccl_device_inline float beta(float x, float y)
Definition: util/math.h:775
ccl_device_inline void make_orthonormals(const float3 N, ccl_private float3 *a, ccl_private float3 *b)
Definition: util/math.h:566