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