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