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