Blender V4.3
tree.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/* This code implements a modified version of the paper [Importance Sampling of Many Lights with
6 * Adaptive Tree Splitting](http://www.aconty.com/pdf/many-lights-hpg2018.pdf) by Alejandro Conty
7 * Estevez, Christopher Kulla.
8 * The original paper traverses both children when the variance of a node is too high (called
9 * splitting). However, Cycles does not support multiple lights per shading point. Therefore, we
10 * adjust the importance computation: instead of using a conservative measure (i.e., the maximal
11 * possible contribution a node could make to a shading point) as in the paper, we additionally
12 * compute the minimal possible contribution and choose uniformly between these two measures. Also,
13 * support for distant lights is added, which is not included in the paper.
14 */
15
16#pragma once
17
18#include "kernel/light/area.h"
19#include "kernel/light/common.h"
20#include "kernel/light/light.h"
21#include "kernel/light/spot.h"
23
25
26/* Consine of the angle subtended by the smallest enclosing sphere of the node bounding box. */
28 const float3 centroid,
29 const float3 P)
30{
31 float distance_to_center_sq = len_squared(P - centroid);
32 float radius_sq = len_squared(bbox.max - centroid);
33
34 /* If P is inside the bounding sphere, `theta_u` covers the whole sphere and return -1.0
35 * Otherwise compute cos(theta_u) by substituting our values into the cos_from_sin() formula on
36 * the basis that `sin(theta_u) = radius / distance_to_center`. */
37 return (distance_to_center_sq <= radius_sq) ?
38 -1.0f :
39 safe_sqrtf(1.0f - (radius_sq / distance_to_center_sq));
40}
41
42/* Compute vector v as in Fig .8. P_v is the corresponding point along the ray. */
44 const float3 centroid, const float3 P, const float3 D, const float3 bcone_axis, const float t)
45{
46 const float3 unnormalized_v0 = P - centroid;
47 const float3 unnormalized_v1 = unnormalized_v0 + D * fminf(t, 1e12f);
48 const float3 v0 = normalize(unnormalized_v0);
49 const float3 v1 = normalize(unnormalized_v1);
50
51 const float3 o0 = v0;
52 float3 o1, o2;
53 make_orthonormals_tangent(o0, v1, &o1, &o2);
54
55 const float dot_o0_a = dot(o0, bcone_axis);
56 const float dot_o1_a = dot(o1, bcone_axis);
57 const float inv_len = inversesqrtf(sqr(dot_o0_a) + sqr(dot_o1_a));
58 const float cos_phi0 = dot_o0_a * inv_len;
59
60 return (dot_o1_a < 0 || dot(v0, v1) > cos_phi0) ? (dot_o0_a > dot(v1, bcone_axis) ? v0 : v1) :
61 cos_phi0 * o0 + dot_o1_a * inv_len * o1;
62}
63
65{
66 return kemitter->light.id < 0;
67}
68
70{
71 return !is_light(kemitter) && kemitter->mesh_light.object_id == OBJECT_NONE;
72}
73
75{
76 return !is_light(kemitter) && kemitter->mesh_light.object_id != OBJECT_NONE;
77}
78
80{
81 /* The distant node is also considered o leaf node. */
82 return knode->type >= LIGHT_TREE_LEAF;
83}
84
85template<bool in_volume_segment>
87 const int object_id,
89 ccl_private float3 &N_or_D,
90 ccl_private float &t)
91{
92 const int object_flag = kernel_data_fetch(object_flag, object_id);
93 if (!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
94#ifdef __OBJECT_MOTION__
95 Transform itfm;
96 object_fetch_transform_motion_test(kg, object_id, 0.5f, &itfm);
97#else
99#endif
100 P = transform_point(&itfm, P);
101 if (in_volume_segment) {
102 /* Transform direction. */
103 float3 D_local = transform_direction(&itfm, N_or_D);
104 float scale;
105 N_or_D = normalize_len(D_local, &scale);
106
107 t *= scale;
108 }
109 else if (!is_zero(N_or_D)) {
110 /* Transform normal. */
111 const Transform tfm = object_fetch_transform(kg, object_id, OBJECT_TRANSFORM);
112 N_or_D = normalize(transform_direction_transposed(&tfm, N_or_D));
113 }
114 }
115}
116
117/* This is the general function for calculating the importance of either a cluster or an emitter.
118 * Both of the specialized functions obtain the necessary data before calling this function. */
119template<bool in_volume_segment>
121 const bool has_transmission,
122 const float3 point_to_centroid,
123 const float cos_theta_u,
124 const BoundingCone bcone,
125 const float max_distance,
126 const float min_distance,
127 const float energy,
128 const float theta_d,
129 ccl_private float &max_importance,
130 ccl_private float &min_importance)
131{
132 max_importance = 0.0f;
133 min_importance = 0.0f;
134
135 const float sin_theta_u = sin_from_cos(cos_theta_u);
136
137 /* cos(theta_i') in the paper, omitted for volume. */
138 float cos_min_incidence_angle = 1.0f;
139 float cos_max_incidence_angle = 1.0f;
140
141 if (!in_volume_segment) {
142 const float3 N = N_or_D;
143 const float cos_theta_i = has_transmission ? fabsf(dot(point_to_centroid, N)) :
144 dot(point_to_centroid, N);
145 const float sin_theta_i = sin_from_cos(cos_theta_i);
146
147 /* cos_min_incidence_angle = cos(max{theta_i - theta_u, 0}) = cos(theta_i') in the paper */
148 cos_min_incidence_angle = cos_theta_i >= cos_theta_u ?
149 1.0f :
150 cos_theta_i * cos_theta_u + sin_theta_i * sin_theta_u;
151
152 /* If the node is guaranteed to be behind the surface we're sampling, and the surface is
153 * opaque, then we can give the node an importance of 0 as it contributes nothing to the
154 * surface. This is more accurate than the bbox test if we are calculating the importance of
155 * an emitter with radius. */
156 if (!has_transmission && cos_min_incidence_angle < 0) {
157 return;
158 }
159
160 /* cos_max_incidence_angle = cos(min{theta_i + theta_u, pi}) */
161 cos_max_incidence_angle = fmaxf(cos_theta_i * cos_theta_u - sin_theta_i * sin_theta_u, 0.0f);
162 }
163
164 float cos_theta, sin_theta;
165 if (isequal(bcone.axis, -point_to_centroid)) {
166 /* When `bcone.axis == -point_to_centroid`, dot(bcone.axis, -point_to_centroid) doesn't always
167 * return 1 due to floating point precision issues. We account for that case here. */
168 cos_theta = 1.0f;
169 sin_theta = 0.0f;
170 }
171 else {
172 cos_theta = dot(bcone.axis, -point_to_centroid);
174 }
175
176 /* cos(theta - theta_u) */
177 const float cos_theta_minus_theta_u = cos_theta * cos_theta_u + sin_theta * sin_theta_u;
178
179 float cos_theta_o, sin_theta_o;
180 fast_sincosf(bcone.theta_o, &sin_theta_o, &cos_theta_o);
181
182 /* Minimum angle an emitter’s axis would form with the direction to the shading point,
183 * cos(theta') in the paper. */
184 float cos_min_outgoing_angle;
185 if ((cos_theta >= cos_theta_u) || (cos_theta_minus_theta_u >= cos_theta_o)) {
186 /* theta - theta_o - theta_u <= 0 */
187 kernel_assert((fast_acosf(cos_theta) - bcone.theta_o - fast_acosf(cos_theta_u)) < 1e-3f);
188 cos_min_outgoing_angle = 1.0f;
189 }
190 else if ((bcone.theta_o + bcone.theta_e > M_PI_F) ||
191 (cos_theta_minus_theta_u > cosf(bcone.theta_o + bcone.theta_e)))
192 {
193 /* theta' = theta - theta_o - theta_u < theta_e */
195 (fast_acosf(cos_theta) - bcone.theta_o - fast_acosf(cos_theta_u) - bcone.theta_e) < 5e-4f);
196 const float sin_theta_minus_theta_u = sin_from_cos(cos_theta_minus_theta_u);
197 cos_min_outgoing_angle = cos_theta_minus_theta_u * cos_theta_o +
198 sin_theta_minus_theta_u * sin_theta_o;
199 }
200 else {
201 /* Cluster is invisible. */
202 return;
203 }
204
205 /* TODO: find a good approximation for f_a. */
206 const float f_a = 1.0f;
207 /* Use `(theta_b - theta_a) / d` for volume, see Eq. (4) in the paper. */
208 max_importance = fabsf(f_a * cos_min_incidence_angle * energy * cos_min_outgoing_angle *
209 (in_volume_segment ? theta_d / min_distance : 1.0f / sqr(min_distance)));
210
211 /* TODO: compute proper min importance for volume. */
212 if (in_volume_segment) {
213 min_importance = 0.0f;
214 return;
215 }
216
217 /* cos(theta + theta_o + theta_u) if theta + theta_o + theta_u < theta_e, 0 otherwise */
218 float cos_max_outgoing_angle;
219 const float cos_theta_plus_theta_u = cos_theta * cos_theta_u - sin_theta * sin_theta_u;
220 if (bcone.theta_e - bcone.theta_o < 0 || cos_theta < 0 || cos_theta_u < 0 ||
221 cos_theta_plus_theta_u < cosf(bcone.theta_e - bcone.theta_o))
222 {
223 min_importance = 0.0f;
224 }
225 else {
226 const float sin_theta_plus_theta_u = sin_from_cos(cos_theta_plus_theta_u);
227 cos_max_outgoing_angle = cos_theta_plus_theta_u * cos_theta_o -
228 sin_theta_plus_theta_u * sin_theta_o;
229 min_importance = fabsf(f_a * cos_max_incidence_angle * energy * cos_max_outgoing_angle /
230 sqr(max_distance));
231 }
232}
233
234template<bool in_volume_segment>
236 ccl_global const KernelLightTreeEmitter *kemitter,
237 const float3 P,
238 ccl_private float3 &centroid,
240{
241 if (is_light(kemitter)) {
242 const ccl_global KernelLight *klight = &kernel_data_fetch(lights, ~(kemitter->light.id));
243 centroid = klight->co;
244
245 switch (klight->type) {
246 case LIGHT_SPOT:
247 dir = klight->spot.dir;
248 break;
249 case LIGHT_POINT:
250 /* Disk-oriented normal. */
251 dir = safe_normalize(P - centroid);
252 break;
253 case LIGHT_AREA:
254 dir = klight->area.dir;
255 break;
256 case LIGHT_BACKGROUND:
257 /* Arbitrary centroid and direction. */
258 centroid = make_float3(0.0f, 0.0f, 1.0f);
259 dir = make_float3(0.0f, 0.0f, -1.0f);
260 break;
261 case LIGHT_DISTANT:
262 dir = centroid;
263 break;
264 default:
265 return false;
266 }
267 }
268 else {
269 kernel_assert(is_triangle(kemitter));
270 const int object = kemitter->mesh_light.object_id;
271 float3 vertices[3];
272 triangle_vertices(kg, kemitter->triangle.id, vertices);
273 centroid = (vertices[0] + vertices[1] + vertices[2]) / 3.0f;
274
275 const bool is_front_only = (kemitter->triangle.emission_sampling == EMISSION_SAMPLING_FRONT);
276 const bool is_back_only = (kemitter->triangle.emission_sampling == EMISSION_SAMPLING_BACK);
277 if (is_front_only || is_back_only) {
278 dir = safe_normalize(cross(vertices[1] - vertices[0], vertices[2] - vertices[0]));
279 if (is_back_only) {
280 dir = -dir;
281 }
282 const int object_flag = kernel_data_fetch(object_flag, object);
283 if ((object_flag & SD_OBJECT_TRANSFORM_APPLIED) && (object_flag & SD_OBJECT_NEGATIVE_SCALE))
284 {
285 dir = -dir;
286 }
287 }
288 else {
289 /* Double-sided: any vector in the plane. */
290 dir = safe_normalize(vertices[0] - vertices[1]);
291 }
292 }
293 return true;
294}
295
296template<bool in_volume_segment>
298 const float3 P,
299 const float3 N_or_D,
300 const float t,
301 const bool has_transmission,
302 const ccl_global KernelLightTreeNode *knode,
303 ccl_private float &max_importance,
304 ccl_private float &min_importance)
305{
306 const BoundingCone bcone = knode->bcone;
307 const BoundingBox bbox = knode->bbox;
308
309 float3 point_to_centroid;
310 float cos_theta_u, distance, theta_d;
311 if (knode->type == LIGHT_TREE_DISTANT) {
312 point_to_centroid = -bcone.axis;
313 cos_theta_u = fast_cosf(bcone.theta_o + bcone.theta_e);
314 distance = 1.0f;
315 /* For distant lights, the integral in Eq. (4) gives the ray length. */
316 theta_d = t;
317 if (t == FLT_MAX) {
318 /* In world volume, distant light has no contribution. */
319 return;
320 }
321 }
322 else {
323 const float3 centroid = 0.5f * (bbox.min + bbox.max);
324
325 if (in_volume_segment) {
326 const float3 D = N_or_D;
327 const float closest_t = dot(centroid - P, D);
328 const float3 closest_point = P + D * clamp(closest_t, 0.0f, t);
329 /* Minimal distance of the ray to the cluster. */
330 distance = len(centroid - P - D * closest_t);
331 /* Estimate `theta_b - theta_a` using the centroid of the cluster and the complete ray
332 * segment in volume. */
333 theta_d = fast_atan2f(t - closest_t, distance) + fast_atan2f(closest_t, distance);
334 /* Vector that forms a minimal angle with the emitter centroid. */
335 point_to_centroid = -compute_v(centroid, P, D, bcone.axis, t);
336 cos_theta_u = light_tree_cos_bound_subtended_angle(bbox, centroid, closest_point);
337 }
338 else {
339 const float3 N = N_or_D;
340 const float3 bbox_extent = bbox.max - centroid;
341 const bool bbox_is_visible = has_transmission |
342 (dot(N, centroid - P) + dot(fabs(N), fabs(bbox_extent)) > 0);
343
344 /* If the node is guaranteed to be behind the surface we're sampling, and the surface is
345 * opaque, then we can give the node an importance of 0 as it contributes nothing to the
346 * surface. */
347 if (!bbox_is_visible) {
348 return;
349 }
350
351 point_to_centroid = normalize_len(centroid - P, &distance);
352 cos_theta_u = light_tree_cos_bound_subtended_angle(bbox, centroid, P);
353 theta_d = 1.0f;
354 }
355 /* Clamp distance to half the radius of the cluster when splitting is disabled. */
356 distance = fmaxf(0.5f * len(centroid - bbox.max), distance);
357 }
358 /* TODO: currently max_distance = min_distance, max_importance = min_importance for the
359 * nodes. Do we need better weights for complex scenes? */
361 has_transmission,
362 point_to_centroid,
363 cos_theta_u,
364 bcone,
365 distance,
366 distance,
367 knode->energy,
368 theta_d,
369 max_importance,
370 min_importance);
371}
372
373template<bool in_volume_segment>
375 const float3 P,
376 const float3 N_or_D,
377 const float t,
378 const bool has_transmission,
379 int emitter_index,
380 ccl_private float &max_importance,
381 ccl_private float &min_importance)
382{
383 max_importance = 0.0f;
384 min_importance = 0.0f;
385
386 const ccl_global KernelLightTreeEmitter *kemitter = &kernel_data_fetch(light_tree_emitters,
387 emitter_index);
388
389 if (is_mesh(kemitter)) {
390 const ccl_global KernelLightTreeNode *knode = &kernel_data_fetch(light_tree_nodes,
391 kemitter->mesh.node_id);
392
394 kg, P, N_or_D, t, has_transmission, knode, max_importance, min_importance);
395 return;
396 }
397
398 BoundingCone bcone;
399 bcone.theta_o = kemitter->theta_o;
400 bcone.theta_e = kemitter->theta_e;
401 float cos_theta_u, theta_d = 1.0f;
402 float2 distance; /* distance.x = max_distance, distance.y = min_distance */
403 float3 centroid, point_to_centroid, P_c = P;
404
405 if (!compute_emitter_centroid_and_dir<in_volume_segment>(kg, kemitter, P, centroid, bcone.axis))
406 {
407 return;
408 }
409
410 if (in_volume_segment) {
411 const float3 D = N_or_D;
412 /* Closest point from ray to the emitter centroid. */
413 const float closest_t = dot(centroid - P, D);
414 P_c += D * clamp(closest_t, 0.0f, t);
415 const float d = len(centroid - P - D * closest_t);
416 theta_d = fast_atan2f(t - closest_t, d) + fast_atan2f(closest_t, d);
417 }
418
419 /* Early out if the emitter is guaranteed to be invisible. */
420 bool is_visible;
421 float energy = kemitter->energy;
422 if (is_triangle(kemitter)) {
424 kg, kemitter, centroid, P_c, N_or_D, bcone, cos_theta_u, distance, point_to_centroid);
425 }
426 else {
427 kernel_assert(is_light(kemitter));
428 const ccl_global KernelLight *klight = &kernel_data_fetch(lights, ~(kemitter->light.id));
429 switch (klight->type) {
430 /* Function templates only modifies cos_theta_u when in_volume_segment = true. */
431 case LIGHT_SPOT:
433 klight, centroid, P_c, bcone, cos_theta_u, distance, point_to_centroid, energy);
434 break;
435 case LIGHT_POINT:
437 klight, centroid, P_c, cos_theta_u, distance, point_to_centroid);
438 bcone.theta_o = 0.0f;
439 break;
440 case LIGHT_AREA:
442 klight, centroid, P_c, N_or_D, bcone.axis, cos_theta_u, distance, point_to_centroid);
443 break;
444 case LIGHT_BACKGROUND:
446 centroid, t, cos_theta_u, distance, point_to_centroid, theta_d);
447 break;
448 case LIGHT_DISTANT:
450 centroid, bcone.theta_e, t, cos_theta_u, distance, point_to_centroid, theta_d);
451 break;
452 default:
453 return;
454 }
455 }
456
457 is_visible |= has_transmission;
458 if (!is_visible) {
459 return;
460 }
461
462 if (in_volume_segment) {
463 /* Vector that forms a minimal angle with the emitter centroid. */
464 point_to_centroid = -compute_v(centroid, P, N_or_D, bcone.axis, t);
465
466 if (is_light(kemitter)) {
467 const ccl_global KernelLight *klight = &kernel_data_fetch(lights, ~(kemitter->light.id));
468 if (klight->type == LIGHT_DISTANT) {
469 /* For distant light `theta_min` is 0, but due to numerical issues this is not always true.
470 * Therefore explicitly assign `-bcone.axis` to `point_to_centroid` in this case. */
471 point_to_centroid = -bcone.axis;
472 }
473 }
474 }
475
477 has_transmission,
478 point_to_centroid,
479 cos_theta_u,
480 bcone,
481 distance.x,
482 distance.y,
483 energy,
484 theta_d,
485 max_importance,
486 min_importance);
487}
488
489template<bool in_volume_segment>
491 const float3 P,
492 const float3 N_or_D,
493 const float t,
494 const bool has_transmission,
495 const ccl_global KernelLightTreeNode *knode,
496 ccl_private float &max_importance,
497 ccl_private float &min_importance)
498{
499 max_importance = 0.0f;
500 min_importance = 0.0f;
501
502 if (knode->num_emitters == 1) {
504 P,
505 N_or_D,
506 t,
507 has_transmission,
508 knode->leaf.first_emitter,
509 max_importance,
510 min_importance);
511 }
512 else if (knode->num_emitters != 0) {
514 kg, P, N_or_D, t, has_transmission, knode, max_importance, min_importance);
515 }
516}
517
518/* Select an element from the reservoir with probability proportional to its weight.
519 * Expect `selected_index` to be initialized to -1, and stays -1 if all the weights are invalid. */
520ccl_device void sample_reservoir(const int current_index,
521 const float current_weight,
522 ccl_private int &selected_index,
523 ccl_private float &selected_weight,
524 ccl_private float &total_weight,
525 ccl_private float &rand)
526{
527 if (!(current_weight > 0.0f)) {
528 return;
529 }
530 total_weight += current_weight;
531
532 /* When `-ffast-math` is used it is possible that the threshold is almost 1 but not quite.
533 * For this case we check the first valid element explicitly (instead of relying on the threshold
534 * to be 1, giving it certain probability). */
535 if (selected_index == -1) {
536 selected_index = current_index;
537 selected_weight = current_weight;
538 /* The threshold is expected to be 1 in this case with strict mathematics, so no need to divide
539 * the rand. In fact, division in such case could lead the rand to exceed 1 because of division
540 * by something smaller than 1. */
541 return;
542 }
543
544 float thresh = current_weight / total_weight;
545 if (rand <= thresh) {
546 selected_index = current_index;
547 selected_weight = current_weight;
548 rand = rand / thresh;
549 }
550 else {
551 rand = (rand - thresh) / (1.0f - thresh);
552 }
553
554 /* Ensure the `rand` is always within 0..1 range, which could be violated above when
555 * `-ffast-math` is used. */
556 rand = saturatef(rand);
557}
558
559/* Pick an emitter from a leaf node using reservoir sampling, keep two reservoirs for upper and
560 * lower bounds. */
561template<bool in_volume_segment>
563 ccl_private float &rand,
565 ccl_private float3 &N_or_D,
566 ccl_private float &t,
567 const bool has_transmission,
568 ccl_private int *node_index,
569 ccl_private float *pdf_factor)
570{
571 float selected_importance[2] = {0.0f, 0.0f};
572 float total_importance[2] = {0.0f, 0.0f};
573 int selected_index = -1;
574 const ccl_global KernelLightTreeNode *knode = &kernel_data_fetch(light_tree_nodes, *node_index);
575 *node_index = -1;
576
577 kernel_assert(knode->num_emitters <= sizeof(uint) * 8);
578 /* Mark emitters with valid importance. Used for reservoir when total minimum importance = 0. */
579 uint has_importance = 0;
580
581 const bool sample_max = (rand > 0.5f); /* Sampling using the maximum importance. */
582 if (knode->num_emitters > 1) {
583 rand = rand * 2.0f - float(sample_max);
584 }
585
586 for (int i = 0; i < knode->num_emitters; i++) {
587 int current_index = knode->leaf.first_emitter + i;
588 /* maximum importance = importance[0], minimum importance = importance[1] */
589 float importance[2];
591 kg, P, N_or_D, t, has_transmission, current_index, importance[0], importance[1]);
592
593 sample_reservoir(current_index,
594 importance[!sample_max],
595 selected_index,
596 selected_importance[!sample_max],
597 total_importance[!sample_max],
598 rand);
599 if (selected_index == current_index) {
600 selected_importance[sample_max] = importance[sample_max];
601 }
602 total_importance[sample_max] += importance[sample_max];
603
604 has_importance |= ((importance[0] > 0) << i);
605 }
606
607 if (!has_importance) {
608 return -1;
609 }
610
611 if (total_importance[1] == 0.0f) {
612 /* Uniformly sample emitters with positive maximum importance. */
613 if (sample_max) {
614 selected_importance[1] = 1.0f;
615 total_importance[1] = float(popcount(has_importance));
616 }
617 else {
618 selected_index = -1;
619 for (int i = 0; i < knode->num_emitters; i++) {
620 int current_index = knode->leaf.first_emitter + i;
621 sample_reservoir(current_index,
622 float(has_importance & 1),
623 selected_index,
624 selected_importance[1],
625 total_importance[1],
626 rand);
627 has_importance >>= 1;
628 }
629
630 float discard;
632 kg, P, N_or_D, t, has_transmission, selected_index, selected_importance[0], discard);
633 }
634 }
635
636 *pdf_factor *= 0.5f * (selected_importance[0] / total_importance[0] +
637 selected_importance[1] / total_importance[1]);
638
639 const ccl_global KernelLightTreeEmitter *kemitter = &kernel_data_fetch(light_tree_emitters,
640 selected_index);
641
642 if (is_mesh(kemitter)) {
643 /* Transform ray from world to local space. */
644 light_tree_to_local_space<in_volume_segment>(kg, kemitter->mesh.object_id, P, N_or_D, t);
645
646 *node_index = kemitter->mesh.node_id;
647 const ccl_global KernelLightTreeNode *knode = &kernel_data_fetch(light_tree_nodes,
648 *node_index);
649 if (knode->type == LIGHT_TREE_INSTANCE) {
650 /* Switch to the node with the subtree. */
651 *node_index = knode->instance.reference;
652 }
653 }
654
655 return selected_index;
656}
657
658template<bool in_volume_segment>
660 const float3 P,
661 const float3 N_or_D,
662 const float t,
663 const bool has_transmission,
664 const int left_index,
665 const int right_index,
666 ccl_private float &left_probability)
667{
668 const ccl_global KernelLightTreeNode *left = &kernel_data_fetch(light_tree_nodes, left_index);
669 const ccl_global KernelLightTreeNode *right = &kernel_data_fetch(light_tree_nodes, right_index);
670
671 float min_left_importance, max_left_importance, min_right_importance, max_right_importance;
673 kg, P, N_or_D, t, has_transmission, left, max_left_importance, min_left_importance);
675 kg, P, N_or_D, t, has_transmission, right, max_right_importance, min_right_importance);
676
677 const float total_max_importance = max_left_importance + max_right_importance;
678 if (total_max_importance == 0.0f) {
679 return false;
680 }
681 const float total_min_importance = min_left_importance + min_right_importance;
682
683 /* Average two probabilities of picking the left child node using lower and upper bounds. */
684 const float probability_max = max_left_importance / total_max_importance;
685 const float probability_min = total_min_importance > 0 ?
686 min_left_importance / total_min_importance :
687 0.5f * (float(max_left_importance > 0) +
688 float(max_right_importance == 0.0f));
689 left_probability = 0.5f * (probability_max + probability_min);
690 return true;
691}
692
693ccl_device int light_tree_root_node_index(KernelGlobals kg, const int object_receiver)
694{
695 if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_LINKING) {
696 const uint receiver_light_set =
697 (object_receiver != OBJECT_NONE) ?
698 kernel_data_fetch(objects, object_receiver).receiver_light_set :
699 0;
700 return kernel_data.light_link_sets[receiver_light_set].light_tree_root;
701 }
702
703 return 0;
704}
705
706/* Pick a random light from the light tree from a given shading point P, write to the picked light
707 * index and the probability of picking the light. */
708template<bool in_volume_segment>
710 const float rand,
711 const float3 P,
712 float3 N_or_D,
713 float t,
714 const int object_receiver,
715 const int shader_flags,
717{
718 if (!kernel_data.integrator.use_direct_light) {
719 return false;
720 }
721
722 const bool has_transmission = (shader_flags & SD_BSDF_HAS_TRANSMISSION);
723 float pdf_leaf = 1.0f;
724 float pdf_selection = 1.0f;
725 int selected_emitter = -1;
726 int node_index = light_tree_root_node_index(kg, object_receiver);
727 float rand_selection = rand;
728
729 float3 local_P = P;
730
731 /* Traverse the light tree until a leaf node is reached. */
732 while (true) {
733 const ccl_global KernelLightTreeNode *knode = &kernel_data_fetch(light_tree_nodes, node_index);
734
735 if (is_leaf(knode)) {
736 /* At a leaf node, we pick an emitter. */
738 kg, rand_selection, local_P, N_or_D, t, has_transmission, &node_index, &pdf_selection);
739
740 if (selected_emitter < 0) {
741 return false;
742 }
743
744 if (node_index < 0) {
745 break;
746 }
747
748 /* Continue with the picked mesh light. */
749 ls->object = kernel_data_fetch(light_tree_emitters, selected_emitter).mesh.object_id;
750 continue;
751 }
752
753 /* Inner node. */
754 const int left_index = knode->inner.left_child;
755 const int right_index = knode->inner.right_child;
756
757 float left_prob;
759 kg, local_P, N_or_D, t, has_transmission, left_index, right_index, left_prob))
760 {
761 return false; /* Both child nodes have zero importance. */
762 }
763
764 float discard;
765 float total_prob = left_prob;
766 node_index = left_index;
768 right_index, 1.0f - left_prob, node_index, discard, total_prob, rand_selection);
769 pdf_leaf *= (node_index == left_index) ? left_prob : (1.0f - left_prob);
770 }
771
772 ls->emitter_id = selected_emitter;
773 ls->pdf_selection = pdf_selection * pdf_leaf;
774
775 return true;
776}
777
778/* We need to be able to find the probability of selecting a given light for MIS. */
779template<bool in_volume_segment>
781 float3 P,
782 float3 N,
783 const float dt,
784 const int path_flag,
785 const int object_emitter,
786 const uint index_emitter,
787 const int object_receiver)
788{
789 const bool has_transmission = (path_flag & PATH_RAY_MIS_HAD_TRANSMISSION);
790
791 ccl_global const KernelLightTreeEmitter *kemitter = &kernel_data_fetch(light_tree_emitters,
792 index_emitter);
793 int subtree_root_index;
794 uint bit_trail, target_emitter;
795
796 if (is_triangle(kemitter)) {
797 /* If the target is an emissive triangle, first traverse the top level tree to find the mesh
798 * light emitter, then traverse the subtree. */
799 target_emitter = kernel_data_fetch(object_to_tree, object_emitter);
800 ccl_global const KernelLightTreeEmitter *kmesh = &kernel_data_fetch(light_tree_emitters,
801 target_emitter);
802 subtree_root_index = kmesh->mesh.node_id;
803 ccl_global const KernelLightTreeNode *kroot = &kernel_data_fetch(light_tree_nodes,
804 subtree_root_index);
805 bit_trail = kroot->bit_trail;
806
807 if (kroot->type == LIGHT_TREE_INSTANCE) {
808 subtree_root_index = kroot->instance.reference;
809 }
810 }
811 else {
812 subtree_root_index = -1;
813 bit_trail = kemitter->bit_trail;
814 target_emitter = index_emitter;
815 }
816
817 float pdf = 1.0f;
818 int node_index = light_tree_root_node_index(kg, object_receiver);
819
820 /* Traverse the light tree until we reach the target leaf node. */
821 while (true) {
822 const ccl_global KernelLightTreeNode *knode = &kernel_data_fetch(light_tree_nodes, node_index);
823
824 if (is_leaf(knode)) {
825 /* Iterate through leaf node to find the probability of sampling the target emitter. */
826 float target_max_importance = 0.0f;
827 float target_min_importance = 0.0f;
828 float total_max_importance = 0.0f;
829 float total_min_importance = 0.0f;
830 int num_has_importance = 0;
831 for (int i = 0; i < knode->num_emitters; i++) {
832 const int emitter = knode->leaf.first_emitter + i;
833 float max_importance, min_importance;
835 kg, P, N, dt, has_transmission, emitter, max_importance, min_importance);
836 num_has_importance += (max_importance > 0);
837 if (emitter == target_emitter) {
838 target_max_importance = max_importance;
839 target_min_importance = min_importance;
840 }
841 total_max_importance += max_importance;
842 total_min_importance += min_importance;
843 }
844
845 if (target_max_importance > 0.0f) {
846 pdf *= 0.5f * (target_max_importance / total_max_importance +
847 (total_min_importance > 0 ? target_min_importance / total_min_importance :
848 1.0f / num_has_importance));
849 }
850 else {
851 return 0.0f;
852 }
853
854 if (subtree_root_index != -1) {
855 /* Arrived at the mesh light. Continue with the subtree. */
856 float unused;
857 light_tree_to_local_space<in_volume_segment>(kg, object_emitter, P, N, unused);
858
859 node_index = subtree_root_index;
860 subtree_root_index = -1;
861 target_emitter = index_emitter;
862 bit_trail = kemitter->bit_trail;
863 continue;
864 }
865 else {
866 return pdf;
867 }
868 }
869
870 /* Inner node. */
871 const int left_index = knode->inner.left_child;
872 const int right_index = knode->inner.right_child;
873
874 float left_prob;
876 kg, P, N, dt, has_transmission, left_index, right_index, left_prob))
877 {
878 return 0.0f;
879 }
880
881 bit_trail >>= kernel_data_fetch(light_tree_nodes, node_index).bit_skip;
882 const bool go_left = (bit_trail & 1) == 0;
883 bit_trail >>= 1;
884
885 node_index = go_left ? left_index : right_index;
886 pdf *= go_left ? left_prob : (1.0f - left_prob);
887
888 if (pdf == 0) {
889 return 0.0f;
890 }
891 }
892}
893
894/* If the function is called in volume, retrieve the previous point in volume segment, and compute
895 * pdf from there. Otherwise compute from the current shading point. */
897 float3 P,
898 float3 N,
899 const float dt,
900 const int path_flag,
901 const int emitter_object,
902 const uint emitter_id,
903 const int object_receiver)
904{
905 if (path_flag & PATH_RAY_VOLUME_SCATTER) {
906 const float3 D_times_t = N;
907 const float3 D = normalize(D_times_t);
908 P = P - D_times_t;
910 kg, P, D, dt, path_flag, emitter_object, emitter_id, object_receiver);
911 }
912
914 kg, P, N, 0.0f, path_flag, emitter_object, emitter_id, object_receiver);
915}
916
MINLINE float safe_sqrtf(float a)
unsigned int uint
ccl_device_forceinline bool area_light_tree_parameters(const ccl_global KernelLight *klight, const float3 centroid, const float3 P, const float3 N, const float3 bcone_axis, ccl_private float &cos_theta_u, ccl_private float2 &distance, ccl_private float3 &point_to_centroid)
Definition area.h:496
ccl_device_inline float cos_theta(const float3 w)
ccl_device_inline float sin_theta(const float3 w)
SIMD_FORCE_INLINE btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
Definition btVector3.h:303
additional_info("compositor_sum_squared_difference_float_shared") .push_constant(Type output_img float dot(value.rgb, luminance_coefficients)") .define("LOAD(value)"
#define kernel_assert(cond)
#define kernel_data
const KernelGlobalsCPU *ccl_restrict KernelGlobals
#define kernel_data_fetch(name, index)
#define cosf(x)
#define ccl_device
#define ccl_private
#define ccl_device_inline
#define ccl_global
#define ccl_device_noinline
#define CCL_NAMESPACE_END
#define saturatef(x)
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
#define fmaxf(x, y)
#define fminf(x, y)
#define fabsf(x)
ccl_device_forceinline bool distant_light_tree_parameters(const float3 centroid, const float theta_e, const float t, ccl_private float &cos_theta_u, ccl_private float2 &distance, ccl_private float3 &point_to_centroid, ccl_private float &theta_d)
Definition distant.h:133
int len
draw_view in_light_buf[] float
ccl_device_inline void triangle_vertices(KernelGlobals kg, int prim, float3 P[3])
@ OBJECT_INVERSE_TRANSFORM
@ OBJECT_TRANSFORM
ccl_device_inline Transform object_fetch_transform(KernelGlobals kg, int object, enum ObjectTransform type)
ccl_device_inline Transform object_fetch_transform_motion_test(KernelGlobals kg, int object, float time, ccl_private Transform *itfm)
ccl_device_forceinline bool background_light_tree_parameters(const float3 centroid, const float t, ccl_private float &cos_theta_u, ccl_private float2 &distance, ccl_private float3 &point_to_centroid, ccl_private float &theta_d)
struct BoundingCone { packed_float3 axis; float theta_o; float theta_e;} BoundingCone
@ SD_BSDF_HAS_TRANSMISSION
@ LIGHT_TREE_INSTANCE
@ LIGHT_TREE_DISTANT
@ LIGHT_TREE_LEAF
@ PATH_RAY_MIS_HAD_TRANSMISSION
@ PATH_RAY_VOLUME_SCATTER
#define OBJECT_NONE
@ EMISSION_SAMPLING_BACK
@ EMISSION_SAMPLING_FRONT
@ SD_OBJECT_NEGATIVE_SCALE
@ SD_OBJECT_TRANSFORM_APPLIED
#define KERNEL_FEATURE_LIGHT_LINKING
@ LIGHT_AREA
@ LIGHT_DISTANT
@ LIGHT_SPOT
@ LIGHT_BACKGROUND
@ LIGHT_POINT
ccl_device_forceinline bool point_light_tree_parameters(const ccl_global KernelLight *klight, const float3 centroid, const float3 P, ccl_private float &cos_theta_u, ccl_private float2 &distance, ccl_private float3 &point_to_centroid)
ccl_device_forceinline bool triangle_light_tree_parameters(KernelGlobals kg, const ccl_global KernelLightTreeEmitter *kemitter, const float3 centroid, const float3 P, const float3 N, const BoundingCone bcone, ccl_private float &cos_theta_u, ccl_private float2 &distance, ccl_private float3 &point_to_centroid)
ccl_device void fast_sincosf(float x, ccl_private float *sine, ccl_private float *cosine)
Definition math_fast.h:141
ccl_device float fast_acosf(float x)
Definition math_fast.h:260
ccl_device float fast_atan2f(float y, float x)
Definition math_fast.h:310
ccl_device float fast_cosf(float x)
Definition math_fast.h:113
ccl_device_inline float len_squared(const float2 a)
ccl_device_inline bool is_zero(const float2 a)
ccl_device_inline float2 safe_normalize(const float2 a)
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_device_inline float2 fabs(const float2 a)
ccl_device_inline bool isequal(const float2 a, const float2 b)
#define N
#define M_PI_F
Definition mikk_util.hh:15
float distance(float a, float b)
ccl_device void make_orthonormals_tangent(const float3 N, const float3 T, ccl_private float3 *a, ccl_private float3 *b)
ccl_device_forceinline bool spot_light_tree_parameters(const ccl_global KernelLight *klight, const float3 centroid, const float3 P, const ccl_private BoundingCone &bcone, ccl_private float &cos_theta_u, ccl_private float2 &distance, ccl_private float3 &point_to_centroid, ccl_private float &energy)
Definition spot.h:286
#define FLT_MAX
Definition stdcycles.h:14
float x
Definition sky_float3.h:27
ccl_device_inline float3 transform_direction(ccl_private const Transform *t, const float3 a)
Definition transform.h:94
ccl_device_inline float3 transform_direction_transposed(ccl_private const Transform *t, const float3 a)
Definition transform.h:123
CCL_NAMESPACE_END CCL_NAMESPACE_BEGIN ccl_device_inline float3 transform_point(ccl_private const Transform *t, const float3 a)
Definition transform.h:63
CCL_NAMESPACE_BEGIN ccl_device float light_tree_cos_bound_subtended_angle(const BoundingBox bbox, const float3 centroid, const float3 P)
Definition tree.h:27
ccl_device_inline bool is_triangle(const ccl_global KernelLightTreeEmitter *kemitter)
Definition tree.h:74
ccl_device float3 compute_v(const float3 centroid, const float3 P, const float3 D, const float3 bcone_axis, const float t)
Definition tree.h:43
ccl_device void light_tree_emitter_importance(KernelGlobals kg, const float3 P, const float3 N_or_D, const float t, const bool has_transmission, int emitter_index, ccl_private float &max_importance, ccl_private float &min_importance)
Definition tree.h:374
ccl_device_inline bool is_light(const ccl_global KernelLightTreeEmitter *kemitter)
Definition tree.h:64
ccl_device int light_tree_cluster_select_emitter(KernelGlobals kg, ccl_private float &rand, ccl_private float3 &P, ccl_private float3 &N_or_D, ccl_private float &t, const bool has_transmission, ccl_private int *node_index, ccl_private float *pdf_factor)
Definition tree.h:562
ccl_device_noinline bool light_tree_sample(KernelGlobals kg, const float rand, const float3 P, float3 N_or_D, float t, const int object_receiver, const int shader_flags, ccl_private LightSample *ls)
Definition tree.h:709
ccl_device_inline bool is_mesh(const ccl_global KernelLightTreeEmitter *kemitter)
Definition tree.h:69
ccl_device void sample_reservoir(const int current_index, const float current_weight, ccl_private int &selected_index, ccl_private float &selected_weight, ccl_private float &total_weight, ccl_private float &rand)
Definition tree.h:520
ccl_device bool compute_emitter_centroid_and_dir(KernelGlobals kg, ccl_global const KernelLightTreeEmitter *kemitter, const float3 P, ccl_private float3 &centroid, ccl_private packed_float3 &dir)
Definition tree.h:235
ccl_device void light_tree_to_local_space(KernelGlobals kg, const int object_id, ccl_private float3 &P, ccl_private float3 &N_or_D, ccl_private float &t)
Definition tree.h:86
ccl_device bool get_left_probability(KernelGlobals kg, const float3 P, const float3 N_or_D, const float t, const bool has_transmission, const int left_index, const int right_index, ccl_private float &left_probability)
Definition tree.h:659
ccl_device void light_tree_importance(const float3 N_or_D, const bool has_transmission, const float3 point_to_centroid, const float cos_theta_u, const BoundingCone bcone, const float max_distance, const float min_distance, const float energy, const float theta_d, ccl_private float &max_importance, ccl_private float &min_importance)
Definition tree.h:120
ccl_device void light_tree_child_importance(KernelGlobals kg, const float3 P, const float3 N_or_D, const float t, const bool has_transmission, const ccl_global KernelLightTreeNode *knode, ccl_private float &max_importance, ccl_private float &min_importance)
Definition tree.h:490
ccl_device void light_tree_node_importance(KernelGlobals kg, const float3 P, const float3 N_or_D, const float t, const bool has_transmission, const ccl_global KernelLightTreeNode *knode, ccl_private float &max_importance, ccl_private float &min_importance)
Definition tree.h:297
ccl_device_inline bool is_leaf(const ccl_global KernelLightTreeNode *knode)
Definition tree.h:79
ccl_device float light_tree_pdf(KernelGlobals kg, float3 P, float3 N, const float dt, const int path_flag, const int object_emitter, const uint index_emitter, const int object_receiver)
Definition tree.h:780
ccl_device int light_tree_root_node_index(KernelGlobals kg, const int object_receiver)
Definition tree.h:693
ccl_device_inline uint popcount(uint x)
Definition util/math.h:855
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 inversesqrtf(float f)
Definition util/math.h:711
ccl_device_inline int clamp(int a, int mn, int mx)
Definition util/math.h:379