Blender V5.0
light_tree.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#include "scene/light_tree.h"
6#include "scene/mesh.h"
7#include "scene/object.h"
8
9#include "util/math_fast.h"
10#include "util/progress.h"
11
13
15{
16 if (this->is_empty()) {
17 return 0.0f;
18 }
19
20 const float theta_w = fminf(M_PI_F, theta_o + theta_e);
21 const float cos_theta_o = cosf(theta_o);
22 const float sin_theta_o = sinf(theta_o);
23
24 return M_2PI_F * (1 - cos_theta_o) +
25 M_PI_2_F * (2 * theta_w * sin_theta_o - cosf(theta_o - 2 * theta_w) -
26 2 * theta_o * sin_theta_o + cos_theta_o);
27}
28
30{
31 if (cone_a.is_empty()) {
32 return cone_b;
33 }
34 if (cone_b.is_empty()) {
35 return cone_a;
36 }
37
38 /* Set cone `a` to always have the greater `theta_o`. */
39 const OrientationBounds *a = &cone_a;
40 const OrientationBounds *b = &cone_b;
41 if (cone_b.theta_o > cone_a.theta_o) {
42 a = &cone_b;
43 b = &cone_a;
44 }
45
46 const float cos_a_b = dot(a->axis, b->axis);
47 const float theta_d = safe_acosf(cos_a_b);
48 const float theta_e = fmaxf(a->theta_e, b->theta_e);
49
50 /* Return axis and `theta_o` of `a` if it already contains `b`. */
51 /* This should also be called when `b` is empty. */
52 if (a->theta_o + 5e-4f >= fminf(M_PI_F, theta_d + b->theta_o)) {
53 return OrientationBounds({a->axis, a->theta_o, theta_e});
54 }
55
56 /* Compute new `theta_o` that contains both `a` and `b`. */
57 const float theta_o = (theta_d + a->theta_o + b->theta_o) * 0.5f;
58
59 if (theta_o >= M_PI_F) {
60 return OrientationBounds({a->axis, M_PI_F, theta_e});
61 }
62
63 /* Slerp between `a` and `b`. */
64 float3 new_axis;
65 if (cos_a_b < -0.9995f) {
66 /* Opposite direction, any orthogonal vector is fine. */
67 float3 unused;
68 make_orthonormals(a->axis, &new_axis, &unused);
69 }
70 else {
71 const float theta_r = theta_o - a->theta_o;
72 const float3 ortho = safe_normalize(b->axis - a->axis * cos_a_b);
73 new_axis = a->axis * cosf(theta_r) + ortho * sinf(theta_r);
74 }
75
76 return OrientationBounds({new_axis, theta_o, theta_e});
77}
78
80{
81 centroid = object->bounds.center();
82 light_set_membership = object->get_light_set_membership();
83}
84
86 const int prim_id,
87 const int object_id,
88 bool need_transformation)
90{
91 Object *object = scene->objects[object_id];
92
93 if (is_triangle()) {
94 float3 vertices[3];
95 Mesh *mesh = static_cast<Mesh *>(object->get_geometry());
96 const Mesh::Triangle triangle = mesh->get_triangle(prim_id);
97 Shader *shader = static_cast<Shader *>(mesh->get_used_shaders()[mesh->get_shader()[prim_id]]);
98
99 for (int i = 0; i < 3; i++) {
100 vertices[i] = mesh->get_verts()[triangle.v[i]];
101 }
102
103 if (need_transformation) {
105 const Transform &tfm = object->get_tfm();
106 for (int i = 0; i < 3; i++) {
107 vertices[i] = transform_point(&tfm, vertices[i]);
108 }
109 }
110
111 /* TODO: need a better way to handle this when textures are used. */
112 const float area = triangle_area(vertices[0], vertices[1], vertices[2]);
113 /* Use absolute value of emission_estimate so lights with negative strength are properly
114 * supported in the light tree. */
115 measure.energy = area * average(fabs(shader->emission_estimate));
116
117 /* NOTE: the original implementation used the bounding box centroid, but triangle centroid
118 * seems to work fine */
119 centroid = (vertices[0] + vertices[1] + vertices[2]) / 3.0f;
120
121 const bool is_front_only = (shader->emission_sampling == EMISSION_SAMPLING_FRONT);
122 const bool is_back_only = (shader->emission_sampling == EMISSION_SAMPLING_BACK);
123 if (is_front_only || is_back_only) {
124 /* One-sided. */
125 measure.bcone.axis = safe_normalize(
126 cross(vertices[1] - vertices[0], vertices[2] - vertices[0]));
127 if (is_back_only) {
128 measure.bcone.axis = -measure.bcone.axis;
129 }
130 if ((need_transformation || mesh->transform_applied) &&
131 transform_negative_scale(object->get_tfm()))
132 {
133 measure.bcone.axis = -measure.bcone.axis;
134 }
135 measure.bcone.theta_o = 0;
136 }
137 else {
138 /* Double sided: any vector in the plane. */
139 measure.bcone.axis = safe_normalize(vertices[0] - vertices[1]);
140 measure.bcone.theta_o = M_PI_2_F;
141 }
142 measure.bcone.theta_e = M_PI_2_F;
143
144 for (int i = 0; i < 3; i++) {
145 measure.bbox.grow(vertices[i]);
146 }
147
148 light_set_membership = object->get_light_set_membership();
149 }
150 else {
151 assert(is_light());
152 Light *lamp = static_cast<Light *>(object->get_geometry());
153 const LightType type = lamp->get_light_type();
154 const float size = lamp->get_size();
155 float3 strength = lamp->get_strength();
156
157 if (!lamp->get_normalize()) {
158 strength *= lamp->area(object->get_tfm());
159 }
160
161 centroid = transform_get_column(&object->get_tfm(), 3);
162 measure.bcone.axis = -safe_normalize(transform_get_column(&object->get_tfm(), 2));
163
164 if (type == LIGHT_AREA) {
165 measure.bcone.theta_o = 0;
166 measure.bcone.theta_e = lamp->get_spread() * 0.5f;
167
168 /* For an area light, sizeu and sizev determine the 2 dimensions of the area light,
169 * while axisu and axisv determine the orientation of the 2 dimensions.
170 * We want to add all 4 corners to our bounding box. */
171 const float3 axisu = transform_get_column(&object->get_tfm(), 0);
172 const float3 axisv = transform_get_column(&object->get_tfm(), 1);
173 const float3 half_extentu = 0.5f * lamp->get_sizeu() * axisu * size;
174 const float3 half_extentv = 0.5f * lamp->get_sizev() * axisv * size;
175 measure.bbox.grow(centroid + half_extentu + half_extentv);
176 measure.bbox.grow(centroid + half_extentu - half_extentv);
177 measure.bbox.grow(centroid - half_extentu + half_extentv);
178 measure.bbox.grow(centroid - half_extentu - half_extentv);
179
180 /* Convert irradiance to radiance. */
181 strength *= M_1_PI_F;
182 }
183 else if (type == LIGHT_POINT) {
184 measure.bcone.theta_o = M_PI_F;
185 measure.bcone.theta_e = M_PI_2_F;
186
187 /* Point and spot lights can emit light from any point within its radius. */
188 const float3 radius = make_float3(size);
189 measure.bbox.grow(centroid - radius);
190 measure.bbox.grow(centroid + radius);
191
192 strength *= 0.25f * M_1_PI_F; /* eval_fac scaling in `spot.h` and `point.h` */
193 }
194 else if (type == LIGHT_SPOT) {
195 measure.bcone.theta_o = 0;
196
197 float theta_e = min(lamp->get_spot_angle() * 0.5f, M_PI_2_F);
198 const float len_u = len(transform_get_column(&object->get_tfm(), 0));
199 const float len_v = len(transform_get_column(&object->get_tfm(), 1));
200 const float len_w = len(transform_get_column(&object->get_tfm(), 2));
201
202 /* As `theta_e` approaches `pi/2`, the behavior of `atan(tan(theta_e))` can become quite
203 * unpredictable as `tan(x)` has an asymptote at `x = pi/2`. To avoid this, we skip the back
204 * and forward conversion.
205 * The conversion is required to deal with scaled lights, but near `pi/2` the scaling does
206 * not make a big difference in the angle, so we can skip the conversion without worrying
207 * about overestimation. */
208 if (fabsf(M_PI_2_F - theta_e) < 1e-6f) {
209 theta_e = M_PI_2_F;
210 }
211 else {
212 theta_e = fast_atanf(fast_tanf(theta_e) * fmaxf(len_u, len_v) / len_w);
213 }
214 measure.bcone.theta_e = theta_e;
215
216 /* Point and spot lights can emit light from any point within its radius. */
217 const float3 radius = make_float3(size);
218 measure.bbox.grow(centroid - radius);
219 measure.bbox.grow(centroid + radius);
220
221 strength *= 0.25f * M_1_PI_F; /* eval_fac scaling in `spot.h` and `point.h` */
222 }
223 else if (type == LIGHT_BACKGROUND) {
224 /* Set an arbitrary direction for the background light. */
225 measure.bcone.axis = make_float3(0.0f, 0.0f, 1.0f);
226 /* TODO: this may depend on portal lights as well. */
227 measure.bcone.theta_o = M_PI_F;
228 measure.bcone.theta_e = 0;
229
230 /* integrate over cosine-weighted hemisphere */
231 strength *= lamp->get_average_radiance() * M_PI_F;
232 }
233 else if (type == LIGHT_DISTANT) {
234 measure.bcone.theta_o = 0;
235 measure.bcone.theta_e = 0.5f * lamp->get_angle();
236 }
237
238 if (lamp->get_shader()) {
239 strength *= lamp->get_shader()->emission_estimate;
240 }
241
242 /* Use absolute value of energy so lights with negative strength are properly supported in the
243 * light tree. */
244 measure.energy = average(fabs(strength));
245
246 light_set_membership = object->get_light_set_membership();
247 }
248}
249
250static void sort_leaf(const int start, const int end, LightTreeEmitter *emitters)
251{
252 /* Sort primitive by light link mask so that specialized trees can use a subset of these. */
253 if (end > start) {
254 std::sort(emitters + start,
255 emitters + end,
256 [](const LightTreeEmitter &a, const LightTreeEmitter &b) {
257 return a.light_set_membership < b.light_set_membership;
258 });
259 }
260}
261
262bool LightTree::triangle_usable_as_light(Mesh *mesh, const int prim_id)
263{
264 const int shader_index = mesh->get_shader()[prim_id];
265 if (shader_index < mesh->get_used_shaders().size()) {
266 Shader *shader = static_cast<Shader *>(mesh->get_used_shaders()[shader_index]);
268 return true;
269 }
270 }
271 return false;
272}
273
274void LightTree::add_mesh(Scene *scene, Mesh *mesh, const int object_id)
275{
276 const size_t mesh_num_triangles = mesh->num_triangles();
277 for (size_t i = 0; i < mesh_num_triangles; i++) {
278 if (triangle_usable_as_light(mesh, i)) {
279 emitters_.emplace_back(scene, i, object_id);
280 }
281 }
282}
283
285 DeviceScene *dscene,
286 Progress &progress,
287 const uint max_lights_in_leaf)
288 : progress_(progress), max_lights_in_leaf_(max_lights_in_leaf)
289{
290 KernelIntegrator *kintegrator = &dscene->data.integrator;
291
292 local_lights_.reserve(kintegrator->num_lights - kintegrator->num_distant_lights);
293 distant_lights_.reserve(kintegrator->num_distant_lights);
294
295 /* When we keep track of the light index, only contributing lights will be added to the device.
296 * Therefore, we want to keep track of the light's index on the device.
297 * However, we also need the light's index in the scene when we're constructing the tree. */
298 int device_light_index = 0;
299 for (Object *object : scene->objects) {
300 if (progress_.get_cancel()) {
301 return;
302 }
303
304 if (object->get_geometry()->is_light()) {
305 /* Regular lights. */
306 Light *light = static_cast<Light *>(object->get_geometry());
307 if (light->is_enabled) {
308 if (light->light_type == LIGHT_BACKGROUND || light->light_type == LIGHT_DISTANT) {
309 distant_lights_.emplace_back(scene, ~device_light_index, object->index);
310 }
311 else {
312 local_lights_.emplace_back(scene, ~device_light_index, object->index);
313 }
314
315 device_light_index++;
316 }
317 }
318 else {
319 /* Emissive triangles. */
320 light_link_receiver_used |= (uint64_t(1) << object->get_receiver_light_set());
321
322 if (!object->usable_as_light()) {
323 continue;
324 }
325
326 mesh_lights_.emplace_back(object, object->index);
327
328 /* Only count unique meshes. */
329 Mesh *mesh = static_cast<Mesh *>(object->get_geometry());
330 auto map_it = offset_map_.find(mesh);
331 if (map_it == offset_map_.end()) {
332 offset_map_[mesh] = num_triangles;
333 num_triangles += mesh->num_triangles();
334 }
335 }
336 }
337}
338
340{
341 if (local_lights_.empty() && distant_lights_.empty() && mesh_lights_.empty()) {
342 return nullptr;
343 }
344
345 const int num_mesh_lights = mesh_lights_.size();
346 int num_local_lights = local_lights_.size() + num_mesh_lights;
347 const int num_distant_lights = distant_lights_.size();
348
349 /* Create a node for each mesh light, and keep track of unique mesh lights. */
350 std::unordered_map<Mesh *, std::tuple<LightTreeNode *, int, int>> unique_mesh;
351 uint *object_offsets = dscene->object_lookup_offset.alloc(scene->objects.size());
352 emitters_.reserve(num_triangles + num_local_lights + num_distant_lights);
353 for (LightTreeEmitter &emitter : mesh_lights_) {
354 Object *object = scene->objects[emitter.object_id];
355 Mesh *mesh = static_cast<Mesh *>(object->get_geometry());
356 emitter.root = create_node(LightTreeMeasure::empty, 0);
357
358 auto map_it = unique_mesh.find(mesh);
359 if (map_it == unique_mesh.end()) {
360 const int start = emitters_.size();
361 add_mesh(scene, mesh, emitter.object_id);
362 const int end = emitters_.size();
363
364 unique_mesh[mesh] = std::make_tuple(emitter.root.get(), start, end);
365 emitter.root->object_id = emitter.object_id;
366 }
367 else {
368 emitter.root->make_instance(std::get<0>(map_it->second), emitter.object_id);
369 }
370 object_offsets[emitter.object_id] = offset_map_[mesh];
371 }
372
373 /* Build a subtree for each unique mesh light. */
374 parallel_for_each(unique_mesh, [this](auto &map_it) {
375 LightTreeNode *node = std::get<0>(map_it.second);
376 int const start = std::get<1>(map_it.second);
377 int const end = std::get<2>(map_it.second);
378 recursive_build(self, node, start, end, emitters_.data(), 0, 0);
379 node->type |= LIGHT_TREE_INSTANCE;
380 });
381 task_pool.wait_work();
382
383 /* Update measure. */
384 parallel_for_each(mesh_lights_, [&](LightTreeEmitter &emitter) {
385 Object *object = scene->objects[emitter.object_id];
386 Mesh *mesh = static_cast<Mesh *>(object->get_geometry());
387
388 LightTreeNode *reference = std::get<0>(unique_mesh.find(mesh)->second);
389 emitter.measure = emitter.root->measure = reference->measure;
390
391 /* Transform measure. The measure is only directly transformable if the transformation has
392 * uniform scaling, otherwise recount all the triangles in the mesh with transformation. */
393 /* NOTE: in theory only energy needs recalculating: #bbox is available via `object->bounds`,
394 * transformation of #bcone is possible. However, the computation involves eigendecomposition
395 * and solving a cubic equation (https://doi.org/10.1016/j.nima.2009.11.075 section 3.4), then
396 * the angle is derived from the major axis of the resulted right elliptic cone's base, which
397 * can be an overestimation. */
398 if (!mesh->transform_applied && !emitter.measure.transform(object->get_tfm())) {
399 emitter.measure.reset();
400 size_t const mesh_num_triangles = mesh->num_triangles();
401 for (size_t i = 0; i < mesh_num_triangles; i++) {
402 if (triangle_usable_as_light(mesh, i)) {
403 emitter.measure.add(LightTreeEmitter(scene, i, emitter.object_id, true).measure);
404 }
405 }
406 }
407 });
408
409 for (LightTreeEmitter &emitter : mesh_lights_) {
410 emitter.root->measure = emitter.measure;
411 }
412
413 /* Could be different from `num_triangles` if only some triangles of an object are emissive. */
414 const int num_emissive_triangles = emitters_.size();
415 num_local_lights += num_emissive_triangles;
416
417 /* Build the top level tree. */
419
420 /* All local lights and mesh lights are grouped to the left child as an inner node. */
421 std::move(local_lights_.begin(), local_lights_.end(), std::back_inserter(emitters_));
422 std::move(mesh_lights_.begin(), mesh_lights_.end(), std::back_inserter(emitters_));
423 recursive_build(
424 left, root_.get(), num_emissive_triangles, num_local_lights, emitters_.data(), 0, 1);
425 task_pool.wait_work();
426
427 if (progress_.get_cancel()) {
428 root_.reset();
429 return nullptr;
430 }
431
432 /* All distant lights are grouped to the right child as a leaf node. */
433 root_->get_inner().children[right] = create_node(LightTreeMeasure::empty, 1);
434 for (int i = 0; i < num_distant_lights; i++) {
435 root_->get_inner().children[right]->add(distant_lights_[i]);
436 }
437
438 sort_leaf(0, num_distant_lights, distant_lights_.data());
439 root_->get_inner().children[right]->make_distant(num_local_lights, num_distant_lights);
440
441 root_->measure = root_->get_inner().children[left]->measure +
442 root_->get_inner().children[right]->measure;
443 root_->light_link = root_->get_inner().children[left]->light_link +
444 root_->get_inner().children[right]->light_link;
445
446 /* Root nodes are never meant to be shared, even if the local and distant lights are from the
447 * same light linking set. Attempting to sharing it will make it so the specialized tree will
448 * try to use the same root as the default tree. */
449 root_->light_link.shareable = false;
450
451 std::move(distant_lights_.begin(), distant_lights_.end(), std::back_inserter(emitters_));
452
453 return root_.get();
454}
455
456void LightTree::recursive_build(const Child child,
457 LightTreeNode *inner,
458 const int start,
459 const int end,
460 LightTreeEmitter *emitters,
461 const uint bit_trail,
462 const int depth)
463{
464 if (progress_.get_cancel()) {
465 return;
466 }
467
468 LightTreeNode *node;
469 if (child == self) {
470 /* Building subtree. */
471 node = inner;
472 }
473 else {
474 inner->get_inner().children[child] = create_node(LightTreeMeasure::empty, bit_trail);
475 node = inner->get_inner().children[child].get();
476 }
477
478 /* Find the best place to split the emitters into 2 nodes.
479 * If the best split cost is no better than making a leaf node, make a leaf instead. */
480 int split_dim = -1;
481 int middle;
482 if (should_split(emitters, start, middle, end, node->measure, node->light_link, split_dim)) {
483
484 if (split_dim != -1) {
485 /* Partition the emitters between start and end based on the centroids. */
486 std::nth_element(emitters + start,
487 emitters + middle,
488 emitters + end,
489 [split_dim](const LightTreeEmitter &l, const LightTreeEmitter &r) {
490 return l.centroid[split_dim] < r.centroid[split_dim];
491 });
492 }
493
494 /* Recursively build the left branch. */
495 if (middle - start > MIN_EMITTERS_PER_THREAD) {
496 task_pool.push([this, node, start, middle, emitters, bit_trail, depth] {
497 recursive_build(left, node, start, middle, emitters, bit_trail, depth + 1);
498 });
499 }
500 else {
501 recursive_build(left, node, start, middle, emitters, bit_trail, depth + 1);
502 }
503
504 /* Recursively build the right branch. */
505 if (end - middle > MIN_EMITTERS_PER_THREAD) {
506 task_pool.push([this, node, middle, end, emitters, bit_trail, depth] {
507 recursive_build(right, node, middle, end, emitters, bit_trail | (1u << depth), depth + 1);
508 });
509 }
510 else {
511 recursive_build(right, node, middle, end, emitters, bit_trail | (1u << depth), depth + 1);
512 }
513 }
514 else {
515 sort_leaf(start, end, emitters);
516 node->make_leaf(start, end - start);
517 }
518}
519
520bool LightTree::should_split(LightTreeEmitter *emitters,
521 const int start,
522 int &middle,
523 const int end,
524 LightTreeMeasure &measure,
525 LightTreeLightLink &light_link,
526 int &split_dim)
527{
528 const int num_emitters = end - start;
529 if (num_emitters < 2) {
530 if (num_emitters) {
531 /* Do not try to split if there is only one emitter. */
532 measure = emitters[start].measure;
533 light_link = LightTreeLightLink(emitters[start].light_set_membership);
534 }
535 return false;
536 }
537
538 middle = (start + end) / 2;
539
540 BoundBox centroid_bbox = BoundBox::empty;
541 for (int i = start; i < end; i++) {
542 centroid_bbox.grow((emitters + i)->centroid);
543 }
544
545 const float3 extent = centroid_bbox.size();
546 const float max_extent = max4(extent.x, extent.y, extent.z, 0.0f);
547
548 /* Check each dimension to find the minimum splitting cost. */
549 float total_cost = 0.0f;
550 float min_cost = FLT_MAX;
551 for (int dim = 0; dim < 3; dim++) {
552 std::array<LightTreeBucket, LightTreeBucket::num_buckets> buckets;
553 float inv_extent;
554
555 if (centroid_bbox.size()[dim] == 0.0f) {
556 /* If the centroid bounding box is 0 along a given dimension and the node measure is
557 * already computed, skip it. */
558 if (dim != 0) {
559 continue;
560 }
561
562 /* Degenerate case, everything in the same bucket. */
563 inv_extent = FLT_MAX;
564 for (int i = start; i < end; i++) {
565 buckets[0].add(emitters[i]);
566 }
567 }
568 else {
569 /* Fill in buckets with emitters. */
570 inv_extent = 1 / (centroid_bbox.size()[dim]);
571 for (int i = start; i < end; i++) {
572 const LightTreeEmitter *emitter = emitters + i;
573
574 /* Place emitter into the appropriate bucket, where the centroid box is split into equal
575 * partitions. */
576 int bucket_idx = LightTreeBucket::num_buckets *
577 (emitter->centroid[dim] - centroid_bbox.min[dim]) * inv_extent;
578 bucket_idx = clamp(bucket_idx, 0, LightTreeBucket::num_buckets - 1);
579
580 buckets[bucket_idx].add(*emitter);
581 }
582 }
583
584 /* Precompute the left bucket measure cumulatively. */
585 std::array<LightTreeBucket, LightTreeBucket::num_buckets - 1> left_buckets;
586 left_buckets.front() = buckets.front();
587 for (int i = 1; i < LightTreeBucket::num_buckets - 1; i++) {
588 left_buckets[i] = left_buckets[i - 1] + buckets[i];
589 }
590
591 if (dim == 0) {
592 /* Calculate node measure by summing up the bucket measure. */
593 measure = left_buckets.back().measure + buckets.back().measure;
594 light_link = left_buckets.back().light_link + buckets.back().light_link;
595
596 /* Degenerate case with co-located emitters. */
597 if (is_zero(centroid_bbox.size())) {
598 break;
599 }
600
601 /* If the centroid bounding box is 0 along a given dimension, skip it. */
602 if (centroid_bbox.size()[dim] == 0.0f) {
603 continue;
604 }
605
606 total_cost = measure.calculate();
607 if (total_cost == 0.0f) {
608 break;
609 }
610 }
611
612 /* Precompute the right bucket measure cumulatively. */
613 std::array<LightTreeBucket, LightTreeBucket::num_buckets - 1> right_buckets;
614 right_buckets.back() = buckets.back();
615 for (int i = LightTreeBucket::num_buckets - 3; i >= 0; i--) {
616 right_buckets[i] = right_buckets[i + 1] + buckets[i + 1];
617 }
618
619 /* Calculate the cost of splitting at each point between partitions. */
620 const float regularization = max_extent * inv_extent;
621 for (int split = 0; split < LightTreeBucket::num_buckets - 1; split++) {
622 const float left_cost = left_buckets[split].measure.calculate();
623 const float right_cost = right_buckets[split].measure.calculate();
624 const float cost = regularization * (left_cost + right_cost);
625
626 if (cost < total_cost && cost < min_cost) {
627 min_cost = cost;
628 split_dim = dim;
629 middle = start + left_buckets[split].count;
630 }
631 }
632 }
633 return min_cost < total_cost || num_emitters > max_lights_in_leaf_;
634}
635
637{
638 LightTreeMeasure c(a);
639 c.add(b);
640 return c;
641}
642
644{
645 return LightTreeBucket(a.measure + b.measure, a.light_link + b.light_link, a.count + b.count);
646}
647
649{
651 c.add(b);
652 return c;
653}
654
MINLINE float safe_acosf(float a)
unsigned int uint
struct BoundBox BoundBox
static void split(const char *text, const char *seps, char ***str, int *count)
ATTR_WARN_UNUSED_RESULT const BMLoop * l
unsigned long long int uint64_t
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
device_vector< uint > object_lookup_offset
Definition devicescene.h:69
KernelData data
Definition devicescene.h:94
bool transform_applied
LightTree(Scene *scene, DeviceScene *dscene, Progress &progress, const uint max_lights_in_leaf)
unique_ptr< LightTreeNode > create_node(const LightTreeMeasure &measure, const uint &bit_trial)
Definition light_tree.h:421
size_t num_triangles
Definition light_tree.h:403
LightTreeNode * build(Scene *scene, DeviceScene *dscene)
size_t num_emitters() const
Definition light_tree.h:427
bool get_cancel() const
Definition progress.h:77
float3 emission_estimate
EmissionSampling emission_sampling
T * alloc(const size_t width, const size_t height=0)
size_t size() const
dot(value.rgb, luminance_coefficients)") DEFINE_VALUE("REDUCE(lhs
#define M_PI_2_F
#define M_1_PI_F
#define __forceinline
#define CCL_NAMESPACE_END
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
#define assert(assertion)
VecBase< float, 3 > cross(VecOp< float, 3 >, VecOp< float, 3 >) RET
constexpr T clamp(T, U, U) RET
VecBase< float, 3 > float3
@ LIGHT_TREE_INSTANCE
@ EMISSION_SAMPLING_NONE
@ EMISSION_SAMPLING_BACK
@ EMISSION_SAMPLING_FRONT
LightType
@ LIGHT_AREA
@ LIGHT_DISTANT
@ LIGHT_SPOT
@ LIGHT_BACKGROUND
@ LIGHT_POINT
static void sort_leaf(const int start, const int end, LightTreeEmitter *emitters)
__forceinline LightTreeMeasure operator+(const LightTreeMeasure &a, const LightTreeMeasure &b)
OrientationBounds merge(const OrientationBounds &cone_a, const OrientationBounds &cone_b)
ccl_device_inline T max4(const T &a, const T &b, const T &c, const T &d)
Definition math_base.h:200
ccl_device float fast_tanf(float x)
Definition math_fast.h:183
ccl_device float fast_atanf(const float x)
Definition math_fast.h:290
ccl_device_inline bool is_zero(const float2 a)
ccl_device_inline float2 safe_normalize(const float2 a)
ccl_device_inline float2 fabs(const float2 a)
ccl_device_inline float triangle_area(const ccl_private float3 &v1, const ccl_private float3 &v2, const ccl_private float3 &v3)
ccl_device_inline void make_orthonormals(const float3 N, ccl_private float3 *a, ccl_private float3 *b)
float average(point a)
Definition node_math.h:144
#define fabsf
#define M_2PI_F
#define fmaxf
#define sinf
#define fminf
#define M_PI_F
#define cosf
#define min(a, b)
Definition sort.cc:36
#define FLT_MAX
Definition stdcycles.h:14
__forceinline float3 size() const
Definition boundbox.h:122
__forceinline void grow(const float3 &pt)
Definition boundbox.h:35
float3 min
Definition boundbox.h:20
LightTreeLightLink light_link
Definition light_tree.h:225
static const int num_buckets
Definition light_tree.h:227
LightTreeMeasure measure
Definition light_tree.h:224
__forceinline bool is_triangle() const
Definition light_tree.h:210
unique_ptr< LightTreeNode > root
Definition light_tree.h:186
uint64_t light_set_membership
Definition light_tree.h:195
LightTreeMeasure measure
Definition light_tree.h:197
LightTreeEmitter(Object *object, const int object_id)
__forceinline bool is_light() const
Definition light_tree.h:215
bool transform(const Transform &tfm)
Definition light_tree.h:117
__forceinline void reset()
Definition light_tree.h:112
__forceinline float calculate()
Definition light_tree.h:101
__forceinline void add(const LightTreeMeasure &measure)
Definition light_tree.h:91
unique_ptr< LightTreeNode > children[2]
Definition light_tree.h:268
__forceinline Inner & get_inner()
Definition light_tree.h:301
void make_leaf(const int first_emitter_index, const int num_emitters)
Definition light_tree.h:321
LightTreeMeasure measure
Definition light_tree.h:250
LightTreeLightLink light_link
Definition light_tree.h:251
Shader * get_shader() const
float area(const Transform &tfm) const
size_t num_triangles() const
Definition scene/mesh.h:77
Triangle get_triangle(const size_t i) const
Definition scene/mesh.h:71
__forceinline bool is_empty() const
Definition light_tree.h:46
float calculate_measure() const
unique_ptr_vector< Object > objects
Definition scene.h:141
float z
Definition sky_math.h:136
float y
Definition sky_math.h:136
float x
Definition sky_math.h:136
i
Definition text_draw.cc:230
ccl_device_inline float3 transform_get_column(const Transform *t, const int column)
Definition transform.h:354
ccl_device_inline bool transform_negative_scale(const Transform &tfm)
Definition transform.h:391
ccl_device_inline float3 transform_point(const ccl_private Transform *t, const float3 a)
Definition transform.h:56
uint len