Blender V5.0
scene/light.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 "device/device.h"
6
7#include "scene/background.h"
8#include "scene/film.h"
9#include "scene/integrator.h"
10#include "scene/light.h"
11#include "scene/light_tree.h"
12#include "scene/mesh.h"
13#include "scene/object.h"
14#include "scene/scene.h"
15#include "scene/shader.h"
16#include "scene/shader_graph.h"
17#include "scene/shader_nodes.h"
18#include "scene/stats.h"
19
21
22#include "util/hash.h"
23#include "util/log.h"
24#include "util/path.h"
25#include "util/progress.h"
26
28
29static void shade_background_pixels(Device *device,
30 DeviceScene *dscene,
31 const int width,
32 const int height,
33 vector<float3> &pixels,
34 Progress &progress)
35{
36 /* Needs to be up to data for attribute access. */
37 device->const_copy_to("data", &dscene->data, sizeof(dscene->data));
38
39 const int size = width * height;
40 const int num_channels = 3;
41 pixels.resize(size);
42
43 /* Evaluate shader on device. */
44 ShaderEval shader_eval(device, progress);
45 shader_eval.eval(
47 size,
48 num_channels,
50 /* Fill coordinates for shading. */
51 KernelShaderEvalInput *d_input_data = d_input.data();
52
53 for (int y = 0; y < height; y++) {
54 for (int x = 0; x < width; x++) {
55 float const u = (x + 0.5f) / width;
56 float const v = (y + 0.5f) / height;
57
59 in.object = OBJECT_NONE;
60 in.prim = PRIM_NONE;
61 in.u = u;
62 in.v = v;
63 d_input_data[x + y * width] = in;
64 }
65 }
66
67 return size;
68 },
69 [&](device_vector<float> &d_output) {
70 /* Copy output to pixel buffer. */
71 float *d_output_data = d_output.data();
72
73 for (int y = 0; y < height; y++) {
74 for (int x = 0; x < width; x++) {
75 pixels[y * width + x].x = d_output_data[(y * width + x) * num_channels + 0];
76 pixels[y * width + x].y = d_output_data[(y * width + x) * num_channels + 1];
77 pixels[y * width + x].z = d_output_data[(y * width + x) * num_channels + 2];
78 }
79 }
80 });
81}
82
83/* Light */
84
86{
87 NodeType *type = NodeType::add("light", create, NodeType::NONE, Geometry::get_node_base_type());
88
89 static NodeEnum type_enum;
90 type_enum.insert("point", LIGHT_POINT);
91 type_enum.insert("distant", LIGHT_DISTANT);
92 type_enum.insert("background", LIGHT_BACKGROUND);
93 type_enum.insert("area", LIGHT_AREA);
94 type_enum.insert("spot", LIGHT_SPOT);
95 SOCKET_ENUM(light_type, "Type", type_enum, LIGHT_POINT);
96
97 SOCKET_COLOR(strength, "Strength", one_float3());
98
99 SOCKET_FLOAT(size, "Size", 0.0f);
100 SOCKET_FLOAT(angle, "Angle", 0.0f);
101
102 SOCKET_FLOAT(sizeu, "Size U", 1.0f);
103 SOCKET_FLOAT(sizev, "Size V", 1.0f);
104 SOCKET_BOOLEAN(ellipse, "Ellipse", false);
105 SOCKET_FLOAT(spread, "Spread", M_PI_F);
106
107 SOCKET_INT(map_resolution, "Map Resolution", 0);
108 SOCKET_FLOAT(average_radiance, "Average Radiance", 0.0f);
109
110 SOCKET_BOOLEAN(is_sphere, "Is Sphere", true);
111
112 SOCKET_FLOAT(spot_angle, "Spot Angle", M_PI_4_F);
113 SOCKET_FLOAT(spot_smooth, "Spot Smooth", 0.0f);
114
115 SOCKET_BOOLEAN(cast_shadow, "Cast Shadow", true);
116 SOCKET_BOOLEAN(use_mis, "Use Mis", false);
117 SOCKET_BOOLEAN(use_caustics, "Shadow Caustics", false);
118
119 SOCKET_INT(max_bounces, "Max Bounces", 1024);
120
121 SOCKET_BOOLEAN(is_portal, "Is Portal", false);
122 SOCKET_BOOLEAN(is_enabled, "Is Enabled", true);
123
124 SOCKET_BOOLEAN(normalize, "Normalize", true);
125
126 return type;
127}
128
129Light::Light() : Geometry(get_node_type(), Geometry::LIGHT)
130{
132}
133
135{
136 if (is_modified()) {
137 scene->light_manager->tag_update(scene, LightManager::LIGHT_MODIFIED);
138 }
139 else {
140 for (const Node *node : get_used_shaders()) {
141 if (node->is_modified()) {
142 /* If the light shader is modified, the number of lights in the scene might change.
143 * Tag light manager for update. */
144 scene->light_manager->tag_update(scene, LightManager::LIGHT_MODIFIED);
145 break;
146 }
147 }
148 }
149}
150
151bool Light::has_contribution(const Scene *scene, const Object *object)
152{
153 if (strength == zero_float3()) {
154 return false;
155 }
156 if (is_portal) {
157 return false;
158 }
159 if (light_type == LIGHT_BACKGROUND) {
160 /* Will be determined after finishing processing all the lights. */
161 return true;
162 }
163 if (light_type == LIGHT_AREA) {
164 if ((get_sizeu() * get_sizev() * get_size() == 0.0f) ||
165 is_zero(transform_get_column(&object->get_tfm(), 0)) ||
166 is_zero(transform_get_column(&object->get_tfm(), 1)))
167 {
168 /* Area light with a size of zero does not contribute to the scene. */
169 return false;
170 }
171 }
172
173 const Shader *effective_shader = (get_shader()) ? get_shader() : scene->default_light;
174 return !is_zero(effective_shader->emission_estimate);
175}
176
178{
179 return (used_shaders.empty()) ? nullptr : static_cast<Shader *>(used_shaders[0]);
180}
181
183{
184 /* To be implemented when this becomes actual geometry. */
185}
186
187void Light::apply_transform(const Transform & /*tfm*/, const bool /*apply_to_motion*/)
188{
189 /* To be implemented when this becomes actual geometry. */
190}
191
192void Light::get_uv_tiles(ustring /*map*/, unordered_set<int> & /*tiles*/)
193{
194 /* To be implemented when this becomes actual geometry. */
195}
196
201
202float Light::area(const Transform &tfm) const
203{
204 if (light_type == LIGHT_POINT || light_type == LIGHT_SPOT) {
205 /* Sphere area. */
206 const float area = 4.0f * M_PI_F * size * size;
207 return (area == 0.0f) ? 4.0f : area;
208 }
209 if (light_type == LIGHT_AREA) {
210 /* Rectangle area. */
211 const float3 axisu = transform_get_column(&tfm, 0);
212 const float3 axisv = transform_get_column(&tfm, 1);
213 float area = len(axisu * sizeu * size) * len(axisv * sizev * size);
214 if (ellipse) {
215 area *= M_PI_4_F;
216 }
217 return area;
218 }
219 if (light_type == LIGHT_DISTANT) {
220 /* Sun disk area. */
221 const float half_angle = angle / 2.0f;
222 return (half_angle > 0.0f) ? M_PI_F * sqr(sinf(half_angle)) : 1.0f;
223 }
224
225 return 1.0f;
226}
227
228/* Light Manager */
229
237
239{
240 for (Object *object : scene->objects) {
241 if (!object->get_geometry()->is_light()) {
242 continue;
243 }
244
245 Light *light = static_cast<Light *>(object->get_geometry());
246 if (light->light_type == LIGHT_BACKGROUND && light->is_enabled) {
247 return true;
248 }
249 }
250 return false;
251}
252
254{
255 /* Make all lights enabled by default, and perform some preliminary checks
256 * needed for finer-tuning of settings (for example, check whether we've
257 * got portals or not).
258 */
259 vector<Light *> background_lights;
260 size_t num_lights = 0;
261 bool has_portal = false;
262 for (Object *object : scene->objects) {
263 if (!object->get_geometry()->is_light()) {
264 continue;
265 }
266
267 Light *light = static_cast<Light *>(object->get_geometry());
268 light->is_enabled = light->has_contribution(scene, object);
269 has_portal |= light->is_portal;
270
271 if (light->light_type == LIGHT_BACKGROUND) {
272 background_lights.push_back(light);
273 }
274
275 num_lights += light->is_enabled;
276 }
277
278 LOG_INFO << "Total " << num_lights << " lights.";
279
280 bool background_enabled = false;
281 int background_resolution = 0;
282
283 if (!background_lights.empty()) {
284 /* Ignore background light if:
285 * - If unsupported on a device
286 * - If we don't need it (no HDRs etc.)
287 */
288 Shader *shader = scene->background->get_shader(scene);
289 for (Light *light : background_lights) {
290 light->is_enabled = has_portal || (light->use_mis && shader->has_surface_spatial_varying);
291 if (light->is_enabled) {
292 background_enabled = true;
293 background_resolution = light->map_resolution;
294 }
295 }
296
297 if (!background_enabled) {
298 LOG_INFO << "Background MIS has been disabled.";
299 }
300 }
301
302 if (last_background_enabled != background_enabled ||
303 last_background_resolution != background_resolution)
304 {
305 last_background_enabled = background_enabled;
306 last_background_resolution = background_resolution;
308 }
309}
310
312{
313 const uint visibility = object->get_visibility();
314 uint shader_flag = 0;
315
316 if (!(visibility & PATH_RAY_CAMERA)) {
317 shader_flag |= SHADER_EXCLUDE_CAMERA;
318 }
319 if (!(visibility & PATH_RAY_DIFFUSE)) {
320 shader_flag |= SHADER_EXCLUDE_DIFFUSE;
321 }
322 if (!(visibility & PATH_RAY_GLOSSY)) {
323 shader_flag |= SHADER_EXCLUDE_GLOSSY;
324 }
325 if (!(visibility & PATH_RAY_TRANSMIT)) {
326 shader_flag |= SHADER_EXCLUDE_TRANSMIT;
327 }
328 if (!(visibility & PATH_RAY_VOLUME_SCATTER)) {
329 shader_flag |= SHADER_EXCLUDE_SCATTER;
330 }
331 if (!(object->get_is_shadow_catcher())) {
332 shader_flag |= SHADER_EXCLUDE_SHADOW_CATCHER;
333 }
334
335 return shader_flag;
336}
337
339 DeviceScene *dscene,
340 Scene *scene,
341 Progress &progress)
342{
343 KernelIntegrator *kintegrator = &dscene->data.integrator;
344 if (kintegrator->use_light_tree) {
345 dscene->light_distribution.free();
346 return;
347 }
348
349 /* Update CDF over lights. */
350 progress.set_status("Updating Lights", "Computing distribution");
351
352 /* Counts emissive triangles in the scene. */
353 size_t num_triangles = 0;
354
355 const int num_lights = kintegrator->num_lights;
356 const size_t max_num_triangles = std::numeric_limits<int>::max() - 1 - kintegrator->num_lights;
357 for (Object *object : scene->objects) {
358 if (progress.get_cancel()) {
359 return;
360 }
361
362 if (!object->usable_as_light()) {
363 continue;
364 }
365
366 /* Count emissive triangles. */
367 Mesh *mesh = static_cast<Mesh *>(object->get_geometry());
368 const int mesh_num_triangles = static_cast<int>(mesh->num_triangles());
369
370 for (int i = 0; i < mesh_num_triangles; i++) {
371 const int shader_index = mesh->get_shader()[i];
372 Shader *shader = (shader_index < mesh->get_used_shaders().size()) ?
373 static_cast<Shader *>(mesh->get_used_shaders()[shader_index]) :
374 scene->default_surface;
375
377 num_triangles++;
378 }
379 }
380
381 if (num_triangles > max_num_triangles) {
382 progress.set_error(
383 "Number of emissive triangles exceeds the limit, consider using Light Tree or disabling "
384 "Emission Sampling on some emissive materials");
385 }
386 }
387
388 const size_t num_distribution = num_triangles + num_lights;
389
390 /* Distribution size. */
391 kintegrator->num_distribution = num_distribution;
392
393 LOG_INFO << "Use light distribution with " << num_distribution << " emitters.";
394
395 /* Emission area. */
396 KernelLightDistribution *distribution = dscene->light_distribution.alloc(num_distribution + 1);
397 float totarea = 0.0f;
398
399 /* Triangles. */
400 size_t offset = 0;
401
402 for (Object *object : scene->objects) {
403 if (progress.get_cancel()) {
404 return;
405 }
406
407 if (!object->usable_as_light()) {
408 continue;
409 }
410 /* Sum area. */
411 Mesh *mesh = static_cast<Mesh *>(object->get_geometry());
412 const bool transform_applied = mesh->transform_applied;
413 const Transform tfm = object->get_tfm();
414 const int shader_flag = light_object_shader_flags(object);
415
416 const size_t mesh_num_triangles = mesh->num_triangles();
417 for (size_t i = 0; i < mesh_num_triangles; i++) {
418 const int shader_index = mesh->get_shader()[i];
419 Shader *shader = (shader_index < mesh->get_used_shaders().size()) ?
420 static_cast<Shader *>(mesh->get_used_shaders()[shader_index]) :
421 scene->default_surface;
422
424 distribution[offset].totarea = totarea;
425 distribution[offset].prim = i + mesh->prim_offset;
426 distribution[offset].shader_flag = shader_flag;
427 distribution[offset].object_id = object->index;
428 offset++;
429
430 const Mesh::Triangle t = mesh->get_triangle(i);
431 if (!t.valid(mesh->get_verts().data())) {
432 continue;
433 }
434 float3 p1 = mesh->get_verts()[t.v[0]];
435 float3 p2 = mesh->get_verts()[t.v[1]];
436 float3 p3 = mesh->get_verts()[t.v[2]];
437
438 if (!transform_applied) {
439 p1 = transform_point(&tfm, p1);
440 p2 = transform_point(&tfm, p2);
441 p3 = transform_point(&tfm, p3);
442 }
443
444 totarea += triangle_area(p1, p2, p3);
445 }
446 }
447 }
448
449 const float trianglearea = totarea;
450
451 /* Lights. */
452 int light_index = 0;
453
454 if (num_lights > 0) {
455 const float lightarea = (totarea > 0.0f) ? totarea / num_lights : 1.0f;
456 for (Object *object : scene->objects) {
457 if (!object->get_geometry()->is_light()) {
458 continue;
459 }
460
461 Light *light = static_cast<Light *>(object->get_geometry());
462 if (!light->is_enabled) {
463 continue;
464 }
465
466 distribution[offset].totarea = totarea;
467 distribution[offset].prim = ~light_index;
468 distribution[offset].object_id = object->index;
469 distribution[offset].shader_flag = 0;
470 totarea += lightarea;
471
472 light_index++;
473 offset++;
474 }
475 }
476
477 /* normalize cumulative distribution functions */
478 distribution[num_distribution].totarea = totarea;
479 distribution[num_distribution].prim = 0;
480 distribution[num_distribution].object_id = OBJECT_NONE;
481 distribution[num_distribution].shader_flag = 0;
482
483 if (totarea > 0.0f) {
484 for (size_t i = 0; i < num_distribution; i++) {
485 distribution[i].totarea /= totarea;
486 }
487 distribution[num_distribution].totarea = 1.0f;
488 }
489
490 if (progress.get_cancel()) {
491 return;
492 }
493
494 /* Update integrator state. */
495 kintegrator->use_direct_light = (totarea > 0.0f);
496
497 /* Precompute pdfs for distribution sampling.
498 * Sample one, with 0.5 probability of light or triangle. */
499 kintegrator->distribution_pdf_triangles = 0.0f;
500 kintegrator->distribution_pdf_lights = 0.0f;
501
502 if (trianglearea > 0.0f) {
503 kintegrator->distribution_pdf_triangles = 1.0f / trianglearea;
504 if (num_lights) {
505 kintegrator->distribution_pdf_triangles *= 0.5f;
506 }
507 }
508
509 if (num_lights) {
510 kintegrator->distribution_pdf_lights = 1.0f / num_lights;
511 if (trianglearea > 0.0f) {
512 kintegrator->distribution_pdf_lights *= 0.5f;
513 }
514 }
515
516 /* Copy distribution to device. */
518}
519
520/* Arguments for functions to convert the light tree to the kernel representation. */
522 const Scene *scene;
528
529 /* Map from instance node to its node index. */
530 std::unordered_map<LightTreeNode *, int> instances;
531};
532
534 const LightTreeNode &node,
535 const int left_child,
536 const int right_child)
537{
538 /* Convert node to kernel representation. */
539 knode.energy = node.measure.energy;
540
541 knode.bbox.min = node.measure.bbox.min;
542 knode.bbox.max = node.measure.bbox.max;
543
544 knode.bcone.axis = node.measure.bcone.axis;
545 knode.bcone.theta_o = node.measure.bcone.theta_o;
546 knode.bcone.theta_e = node.measure.bcone.theta_e;
547
548 knode.bit_trail = node.bit_trail;
549 knode.bit_skip = 0;
550 knode.type = static_cast<LightTreeNodeType>(node.type);
551
552 if (node.is_leaf() || node.is_distant()) {
553 knode.num_emitters = node.get_leaf().num_emitters;
555 }
556 else if (node.is_inner()) {
557 knode.num_emitters = -1;
558 knode.inner.left_child = left_child;
559 knode.inner.right_child = right_child;
560 }
561}
562
563static int light_tree_flatten(LightTreeFlatten &flatten,
564 const LightTreeNode *node,
565 KernelLightTreeNode *knodes,
566 KernelLightTreeEmitter *kemitters,
567 int &next_node_index);
568
570 const LightTreeNode &node,
571 KernelLightTreeNode *knodes,
572 KernelLightTreeEmitter *kemitters,
573 int &next_node_index)
574{
575 /* Convert emitters to kernel representation. */
576 for (int i = 0; i < node.get_leaf().num_emitters; i++) {
577 const int emitter_index = i + node.get_leaf().first_emitter_index;
578 const LightTreeEmitter &emitter = flatten.emitters[emitter_index];
579 KernelLightTreeEmitter &kemitter = kemitters[emitter_index];
580
581 kemitter.energy = emitter.measure.energy;
582 kemitter.theta_o = emitter.measure.bcone.theta_o;
583 kemitter.theta_e = emitter.measure.bcone.theta_e;
584
585 if (emitter.is_triangle()) {
586 /* Triangle. */
587 Object *object = flatten.scene->objects[emitter.object_id];
588 Mesh *mesh = static_cast<Mesh *>(object->get_geometry());
589 Shader *shader = static_cast<Shader *>(
590 mesh->get_used_shaders()[mesh->get_shader()[emitter.prim_id]]);
591
592 kemitter.triangle.id = emitter.prim_id + mesh->prim_offset;
593 kemitter.shader_flag = light_object_shader_flags(object);
594 kemitter.object_id = emitter.object_id;
596 flatten.triangle_array[emitter.prim_id + flatten.object_lookup_offset[emitter.object_id]] =
597 emitter_index;
598 }
599 else if (emitter.is_light()) {
600 /* Light object. */
601 kemitter.light.id = emitter.light_id;
602 kemitter.shader_flag = 0;
603 kemitter.object_id = emitter.object_id;
604 flatten.light_array[~emitter.light_id] = emitter_index;
605 }
606 else {
607 /* Mesh instance. */
608 assert(emitter.is_mesh());
609 kemitter.mesh.object_id = emitter.object_id;
610 kemitter.shader_flag = 0;
611 kemitter.object_id = OBJECT_NONE;
612 flatten.mesh_array[emitter.object_id] = emitter_index;
613
614 /* Create instance node. One instance node will be the same as the
615 * reference node, and for that it will recursively build the subtree. */
616 LightTreeNode *instance_node = emitter.root.get();
617 LightTreeNode *reference_node = instance_node->get_reference();
618
619 auto map_it = flatten.instances.find(reference_node);
620 if (map_it == flatten.instances.end()) {
621 if (instance_node != reference_node) {
622 /* Flatten the node with the subtree first so the subsequent instances know the index.
623 */
624 std::swap(instance_node->type, reference_node->type);
625 std::swap(instance_node->variant_type, reference_node->variant_type);
626 }
627 instance_node->type &= ~LIGHT_TREE_INSTANCE;
628 }
629
631 flatten, instance_node, knodes, kemitters, next_node_index);
632
633 KernelLightTreeNode &kinstance_node = knodes[kemitter.mesh.node_id];
634 kinstance_node.bit_trail = node.bit_trail;
635
636 if (map_it != flatten.instances.end()) {
637 kinstance_node.instance.reference = map_it->second;
638 }
639 else {
640 flatten.instances[reference_node] = kemitter.mesh.node_id;
641 }
642 }
643 kemitter.bit_trail = node.bit_trail;
644 }
645}
646
648 const LightTreeNode *node,
649 KernelLightTreeNode *knodes,
650 KernelLightTreeEmitter *kemitters,
651 int &next_node_index)
652{
653 /* Convert both inner nodes and primitives to device representation. */
654 const int node_index = next_node_index++;
655 int left_child = -1;
656 int right_child = -1;
657
658 if (node->is_leaf() || node->is_distant()) {
659 light_tree_leaf_emitters_copy_and_flatten(flatten, *node, knodes, kemitters, next_node_index);
660 }
661 else if (node->is_inner()) {
662 left_child = light_tree_flatten(flatten,
663 node->get_inner().children[LightTree::left].get(),
664 knodes,
665 kemitters,
666 next_node_index);
667 right_child = light_tree_flatten(flatten,
668 node->get_inner().children[LightTree::right].get(),
669 knodes,
670 kemitters,
671 next_node_index);
672 }
673 else {
674 /* Instance node that is not inner or leaf, but just references another. */
675 assert(node->is_instance());
676 }
677
678 light_tree_node_copy_to_device(knodes[node_index], *node, left_child, right_child);
679
680 return node_index;
681}
682
684 const LightTreeNode *node,
685 KernelLightTreeNode *knodes,
686 KernelLightTreeEmitter *kemitters,
687 int &next_node_index)
688{
689 /* Convert only emitters to device representation. */
690 if (node->is_leaf() || node->is_distant()) {
691 light_tree_leaf_emitters_copy_and_flatten(flatten, *node, knodes, kemitters, next_node_index);
692 }
693 else {
694 assert(node->is_inner());
695
697 node->get_inner().children[LightTree::left].get(),
698 knodes,
699 kemitters,
700 next_node_index);
702 node->get_inner().children[LightTree::right].get(),
703 knodes,
704 kemitters,
705 next_node_index);
706 }
707}
708
709static std::pair<int, LightTreeMeasure> light_tree_specialize_nodes_flatten(
710 const LightTreeFlatten &flatten,
711 LightTreeNode *node,
712 const uint64_t light_link_mask,
713 const int depth,
715 int &next_node_index,
716 bool can_share = true)
717{
718 assert(!node->is_instance());
719
720 /* Convert inner nodes to device representation, specialized for light linking. */
721 int node_index;
722 int left_child = -1;
723 int right_child = -1;
724
726
727 if (depth == 0 && !(node->light_link.set_membership & light_link_mask)) {
728 /* Ensure there is always a root node. */
729 node_index = next_node_index++;
730 new_node.make_leaf(-1, 0);
731 }
732 else if (can_share && node->light_link.shareable && node->light_link.shared_node_index != -1) {
733 /* Share subtree already built for another light link set. */
734 return std::make_pair(node->light_link.shared_node_index, node->measure);
735 }
736 else if (node->is_leaf() || node->is_distant()) {
737 /* Specialize leaf node. */
738 node_index = next_node_index++;
739 int first_emitter = -1;
740 int num_emitters = 0;
741
742 for (int i = 0; i < node->get_leaf().num_emitters; i++) {
743 const LightTreeEmitter &emitter = flatten.emitters[node->get_leaf().first_emitter_index + i];
744 if (emitter.light_set_membership & light_link_mask) {
745 /* Assumes emitters are consecutive due to LighTree::sort_leaf. */
746 if (first_emitter == -1) {
747 first_emitter = node->get_leaf().first_emitter_index + i;
748 }
749 num_emitters++;
750 new_node.measure.add(emitter.measure);
751 }
752 }
753
754 assert(first_emitter != -1);
755
756 /* Preserve the type of the node, so that the kernel can do proper decision when sampling
757 * node with multiple distant lights in it. */
758 if (node->is_leaf()) {
759 new_node.make_leaf(first_emitter, num_emitters);
760 }
761 else {
762 new_node.make_distant(first_emitter, num_emitters);
763 }
764 }
765 else {
766 assert(node->is_inner());
767 assert(new_node.is_inner());
768
769 /* Specialize inner node. */
770 LightTreeNode *left_node = node->get_inner().children[LightTree::left].get();
771 LightTreeNode *right_node = node->get_inner().children[LightTree::right].get();
772
773 /* Skip nodes that have only one child. We have a single bit trail for each
774 * primitive, bit_skip is incremented in the child node to skip the bit for
775 * this parent node. */
776 LightTreeNode *only_node = nullptr;
777 if (!(left_node->light_link.set_membership & light_link_mask)) {
778 only_node = right_node;
779 }
780 else if (!(right_node->light_link.set_membership & light_link_mask)) {
781 only_node = left_node;
782 }
783 if (only_node) {
784 /* Can not share the node as its bit_skip will be modified.
785 * Also don't store shareable_index so other branches of the tree that do not skip any nodes
786 * do not share node created here. */
787 const auto [only_index, only_measure] = light_tree_specialize_nodes_flatten(
788 flatten, only_node, light_link_mask, depth + 1, knodes, next_node_index, false);
789
790 assert(only_index != -1);
791 knodes[only_index].bit_skip++;
792 return std::make_pair(only_index, only_measure);
793 }
794
795 /* Create inner node. */
796 node_index = next_node_index++;
797
798 const auto [left_index, left_measure] = light_tree_specialize_nodes_flatten(
799 flatten, left_node, light_link_mask, depth + 1, knodes, next_node_index);
800 const auto [right_index, right_measure] = light_tree_specialize_nodes_flatten(
801 flatten, right_node, light_link_mask, depth + 1, knodes, next_node_index);
802
803 new_node.measure = left_measure;
804 new_node.measure.add(right_measure);
805
806 left_child = left_index;
807 right_child = right_index;
808 }
809
810 /* Convert to kernel node. */
811 if (knodes.size() <= node_index) {
812 knodes.resize(node_index + 1);
813 }
814 light_tree_node_copy_to_device(knodes[node_index], new_node, left_child, right_child);
815
816 if (node->light_link.shareable) {
817 node->light_link.shared_node_index = node_index;
818 }
819
820 return std::make_pair(node_index, new_node.measure);
821}
822
824 DeviceScene *dscene,
825 Scene *scene,
826 Progress &progress)
827{
828 KernelIntegrator *kintegrator = &dscene->data.integrator;
829
830 if (!kintegrator->use_light_tree) {
831 return;
832 }
833
834 /* Update light tree. */
835 progress.set_status("Updating Lights", "Computing tree");
836
837 /* TODO: For now, we'll start with a smaller number of max lights in a node.
838 * More benchmarking is needed to determine what number works best. */
839 LightTree light_tree(scene, dscene, progress, 8);
840 LightTreeNode *root = light_tree.build(scene, dscene);
841 if (progress.get_cancel()) {
842 return;
843 }
844
845 /* Create arguments for recursive tree flatten. */
846 LightTreeFlatten flatten;
847 flatten.scene = scene;
848 flatten.emitters = light_tree.get_emitters();
850 /* We want to create separate arrays corresponding to triangles and lights,
851 * which will be used to index back into the light tree for PDF calculations. */
852 flatten.light_array = dscene->light_to_tree.alloc(kintegrator->num_lights);
853 flatten.mesh_array = dscene->object_to_tree.alloc(scene->objects.size());
854 flatten.triangle_array = dscene->triangle_to_tree.alloc(light_tree.num_triangles);
855
856 /* Allocate emitters */
857 const size_t num_emitters = light_tree.num_emitters();
858 KernelLightTreeEmitter *kemitters = dscene->light_tree_emitters.alloc(num_emitters);
859
860 /* Update integrator state. */
861 kintegrator->use_direct_light = num_emitters > 0;
862
863 /* Test if light linking is used. */
864 const bool use_light_linking = root && (light_tree.light_link_receiver_used != 1);
865 KernelLightLinkSet *klight_link_sets = dscene->data.light_link_sets;
866 memset(klight_link_sets, 0, sizeof(dscene->data.light_link_sets));
867
868 LOG_INFO << "Use light tree with " << num_emitters << " emitters and " << light_tree.num_nodes
869 << " nodes.";
870
871 if (!use_light_linking) {
872 /* Regular light tree without linking. */
873 KernelLightTreeNode *knodes = dscene->light_tree_nodes.alloc(light_tree.num_nodes);
874
875 if (root) {
876 int next_node_index = 0;
877 light_tree_flatten(flatten, root, knodes, kemitters, next_node_index);
878 }
879 }
880 else {
881 int next_node_index = 0;
882
883 vector<KernelLightTreeNode> light_link_nodes;
884
885 /* Write primitives, and any subtrees for instances. */
886 if (root) {
887 /* Reserve enough size of all instance subtrees, then shrink back to
888 * actual number of nodes used. */
889 light_link_nodes.resize(light_tree.num_nodes);
891 flatten, root, light_link_nodes.data(), kemitters, next_node_index);
892 light_link_nodes.resize(next_node_index);
893 }
894
895 /* Specialized light trees for linking. */
896 for (uint64_t tree_index = 0; tree_index < LIGHT_LINK_SET_MAX; tree_index++) {
897 const uint64_t tree_mask = uint64_t(1) << tree_index;
898 if (!(light_tree.light_link_receiver_used & tree_mask)) {
899 continue;
900 }
901
902 if (root) {
903 klight_link_sets[tree_index].light_tree_root =
905 flatten, root, tree_mask, 0, light_link_nodes, next_node_index)
906 .first;
907 }
908 }
909
910 /* Allocate and copy nodes into device array. */
911 KernelLightTreeNode *knodes = dscene->light_tree_nodes.alloc(light_link_nodes.size());
912 memcpy(knodes, light_link_nodes.data(), light_link_nodes.size() * sizeof(*knodes));
913
914 LOG_INFO << "Specialized light tree for light linking, with "
915 << light_link_nodes.size() - light_tree.num_nodes << " additional nodes.";
916 }
917
918 /* Copy arrays to device. */
925}
926
927static void background_cdf(int start,
928 const int end,
929 const int res_x,
930 const int res_y,
931 const vector<float3> *pixels,
932 float2 *cond_cdf)
933{
934 const int cdf_width = res_x + 1;
935 /* Conditional CDFs (rows, U direction). */
936 for (int i = start; i < end; i++) {
937 const float sin_theta = sinf(M_PI_F * (i + 0.5f) / res_y);
938 float3 env_color = (*pixels)[i * res_x];
939 float ave_luminance = average(fabs(env_color));
940
941 cond_cdf[i * cdf_width].x = ave_luminance * sin_theta;
942 cond_cdf[i * cdf_width].y = 0.0f;
943
944 for (int j = 1; j < res_x; j++) {
945 env_color = (*pixels)[i * res_x + j];
946 ave_luminance = average(fabs(env_color));
947
948 cond_cdf[i * cdf_width + j].x = ave_luminance * sin_theta;
949 cond_cdf[i * cdf_width + j].y = cond_cdf[i * cdf_width + j - 1].y +
950 cond_cdf[i * cdf_width + j - 1].x / res_x;
951 }
952
953 const float cdf_total = cond_cdf[i * cdf_width + res_x - 1].y +
954 cond_cdf[i * cdf_width + res_x - 1].x / res_x;
955
956 /* stuff the total into the brightness value for the last entry, because
957 * we are going to normalize the CDFs to 0.0 to 1.0 afterwards */
958 cond_cdf[i * cdf_width + res_x].x = cdf_total;
959
960 if (cdf_total > 0.0f) {
961 const float cdf_total_inv = 1.0f / cdf_total;
962 for (int j = 1; j < res_x; j++) {
963 cond_cdf[i * cdf_width + j].y *= cdf_total_inv;
964 }
965 }
966
967 cond_cdf[i * cdf_width + res_x].y = 1.0f;
968 }
969}
970
972 DeviceScene *dscene,
973 Scene *scene,
974 Progress &progress)
975{
976 KernelIntegrator *kintegrator = &dscene->data.integrator;
977 KernelBackground *kbackground = &dscene->data.background;
978 Light *background_light = nullptr;
979
980 bool background_mis = false;
981
982 /* find background light */
983 for (Object *object : scene->objects) {
984 if (!object->get_geometry()->is_light()) {
985 continue;
986 }
987
988 Light *light = static_cast<Light *>(object->get_geometry());
989 if (light->light_type == LIGHT_BACKGROUND && light->is_enabled) {
990 background_light = light;
991 background_mis |= light->use_mis;
992 }
993 }
994
995 kbackground->portal_weight = kintegrator->num_portals > 0 ? 1.0f : 0.0f;
996 kbackground->map_weight = background_mis ? 1.0f : 0.0f;
997 kbackground->sun_weight = 0.0f;
998
999 /* no background light found, signal renderer to skip sampling */
1000 if (!background_light || !background_light->is_enabled) {
1001 kbackground->map_res_x = 0;
1002 kbackground->map_res_y = 0;
1003 kbackground->use_mis = (kbackground->portal_weight > 0.0f);
1004 return;
1005 }
1006
1007 progress.set_status("Updating Lights", "Importance map");
1008
1009 int2 environment_res = make_int2(0, 0);
1010 Shader *shader = scene->background->get_shader(scene);
1011 int num_suns = 0;
1012 float sun_average_radiance = 0.0f;
1013 for (ShaderNode *node : shader->graph->nodes) {
1014 if (node->type == EnvironmentTextureNode::get_node_type()) {
1016 if (!env->handle.empty()) {
1017 const ImageMetaData metadata = env->handle.metadata();
1018 environment_res.x = max(environment_res.x, (int)metadata.width);
1019 environment_res.y = max(environment_res.y, (int)metadata.height);
1020 }
1021 }
1022 if (node->type == SkyTextureNode::get_node_type()) {
1023 SkyTextureNode *sky = (SkyTextureNode *)node;
1024 if (sky->get_sun_disc()) {
1025 /* Ensure that the input coordinates aren't transformed before they reach the node.
1026 * If that is the case, the logic used for sampling the Sun's location does not work
1027 * and we have to fall back to map-based sampling. */
1028 const ShaderInput *vec_in = sky->input("Vector");
1029 if (vec_in && vec_in->link && vec_in->link->parent) {
1030 ShaderNode *vec_src = vec_in->link->parent;
1031 if ((vec_src->type != TextureCoordinateNode::get_node_type()) ||
1032 (vec_in->link != vec_src->output("Generated")))
1033 {
1034 environment_res.x = max(environment_res.x, 4096);
1035 environment_res.y = max(environment_res.y, 2048);
1036 continue;
1037 }
1038 }
1039
1040 /* Determine Sun direction from lat/long and texture mapping. */
1041 const float latitude = sky->get_sun_elevation();
1042 const float longitude = sky->get_sun_rotation() + M_PI_2_F;
1044 cosf(latitude) * cosf(longitude), cosf(latitude) * sinf(longitude), sinf(latitude));
1045 const Transform sky_transform = transform_inverse(sky->tex_mapping.compute_transform());
1047
1048 /* Pack Sun direction and size. */
1049 const float half_angle = sky->get_sun_size() * 0.5f;
1050 kbackground->sun = make_float4(sun_direction, half_angle);
1051
1052 /* Empirical value */
1053 kbackground->sun_weight = 4.0f;
1054 sun_average_radiance = sky->get_sun_average_radiance();
1055 environment_res.x = max(environment_res.x, 512);
1056 environment_res.y = max(environment_res.y, 256);
1057 num_suns++;
1058 }
1059 }
1060 }
1061
1062 /* If there's more than one Sun, fall back to map sampling instead. */
1063 kbackground->use_sun_guiding = (num_suns == 1);
1064 if (!kbackground->use_sun_guiding) {
1065 kbackground->sun_weight = 0.0f;
1066 environment_res.x = max(environment_res.x, 4096);
1067 environment_res.y = max(environment_res.y, 2048);
1068 }
1069
1070 /* Enable MIS for background sampling if any strategy is active. */
1071 kbackground->use_mis = (kbackground->portal_weight + kbackground->map_weight +
1072 kbackground->sun_weight) > 0.0f;
1073
1074 /* get the resolution from the light's size (we stuff it in there) */
1075 int2 res = make_int2(background_light->map_resolution, background_light->map_resolution / 2);
1076 /* If the resolution isn't set manually, try to find an environment texture. */
1077 if (res.x == 0) {
1078 res = environment_res;
1079 if (res.x > 0 && res.y > 0) {
1080 LOG_INFO << "Automatically set World MIS resolution to " << res.x << " by " << res.y;
1081 }
1082 }
1083 /* If it's still unknown, just use the default. */
1084 if (res.x == 0 || res.y == 0) {
1085 res = make_int2(1024, 512);
1086 LOG_INFO << "Setting World MIS resolution to default";
1087 }
1088 kbackground->map_res_x = res.x;
1089 kbackground->map_res_y = res.y;
1090
1091 vector<float3> pixels;
1092 shade_background_pixels(device, dscene, res.x, res.y, pixels, progress);
1093
1094 if (progress.get_cancel()) {
1095 return;
1096 }
1097
1098 /* build row distributions and column distribution for the infinite area environment light */
1099 const int cdf_width = res.x + 1;
1100 float2 *marg_cdf = dscene->light_background_marginal_cdf.alloc(res.y + 1);
1101 float2 *cond_cdf = dscene->light_background_conditional_cdf.alloc(cdf_width * res.y);
1102
1103 const double time_start = time_dt();
1104
1105 /* Create CDF in parallel. */
1106 const int rows_per_task = divide_up(10240, res.x);
1107 parallel_for(blocked_range<size_t>(0, res.y, rows_per_task),
1108 [&](const blocked_range<size_t> &r) {
1109 background_cdf(r.begin(), r.end(), res.x, res.y, &pixels, cond_cdf);
1110 });
1111
1112 /* marginal CDFs (column, V direction, sum of rows) */
1113 marg_cdf[0].x = cond_cdf[res.x].x;
1114 marg_cdf[0].y = 0.0f;
1115
1116 for (int i = 1; i < res.y; i++) {
1117 marg_cdf[i].x = cond_cdf[i * cdf_width + res.x].x;
1118 marg_cdf[i].y = marg_cdf[i - 1].y + marg_cdf[i - 1].x / res.y;
1119 }
1120
1121 const float cdf_total = marg_cdf[res.y - 1].y + marg_cdf[res.y - 1].x / res.y;
1122 marg_cdf[res.y].x = cdf_total;
1123
1124 const float map_average_radiance = cdf_total * M_PI_2_F;
1125 if (sun_average_radiance > 0.0f) {
1126 /* The weighting here is just a heuristic that was empirically determined.
1127 * The Sun's average radiance is much higher than the map's average radiance,
1128 * but we don't want to weight the background light too much because
1129 * visibility is not accounted for anyway. */
1130 background_light->set_average_radiance(0.8f * map_average_radiance +
1131 0.2f * sun_average_radiance);
1132 }
1133 else {
1134 background_light->set_average_radiance(map_average_radiance);
1135 }
1136
1137 if (cdf_total > 0.0f) {
1138 for (int i = 1; i < res.y; i++) {
1139 marg_cdf[i].y /= cdf_total;
1140 }
1141 }
1142
1143 marg_cdf[res.y].y = 1.0f;
1144
1145 LOG_DEBUG << "Background MIS build time " << time_dt() - time_start;
1146
1147 /* update device */
1150}
1151
1153{
1154 /* Counts lights in the scene. */
1155 size_t num_lights = 0;
1156 size_t num_portals = 0;
1157 size_t num_background_lights = 0;
1158 size_t num_distant_lights = 0;
1159 bool use_light_mis = false;
1160
1161 for (Object *object : scene->objects) {
1162 if (!object->get_geometry()->is_light()) {
1163 continue;
1164 }
1165
1166 Light *light = static_cast<Light *>(object->get_geometry());
1167 if (light->is_enabled) {
1168 num_lights++;
1169
1170 if (light->light_type == LIGHT_DISTANT) {
1171 num_distant_lights++;
1172 }
1173 else if (light->light_type == LIGHT_POINT || light->light_type == LIGHT_SPOT) {
1174 use_light_mis |= (light->size > 0.0f && light->use_mis);
1175 }
1176 else if (light->light_type == LIGHT_AREA) {
1177 use_light_mis |= light->use_mis;
1178 }
1179 else if (light->light_type == LIGHT_BACKGROUND) {
1180 num_distant_lights++;
1181 num_background_lights++;
1182 }
1183 }
1184 if (light->is_portal) {
1185 num_portals++;
1186 }
1187 }
1188
1189 /* Update integrator settings. */
1190 KernelIntegrator *kintegrator = &dscene->data.integrator;
1191 kintegrator->use_light_tree = scene->integrator->get_use_light_tree();
1192 kintegrator->num_lights = num_lights;
1193 kintegrator->num_distant_lights = num_distant_lights;
1194 kintegrator->num_background_lights = num_background_lights;
1195 kintegrator->use_light_mis = use_light_mis;
1196
1197 kintegrator->num_portals = num_portals;
1198 kintegrator->portal_offset = num_lights;
1199
1200 /* Create KernelLight for every portal and enabled light in the scene. */
1201 KernelLight *klights = dscene->lights.alloc(num_lights + num_portals);
1202
1203 int light_index = 0;
1204 int portal_index = num_lights;
1205
1206 for (Object *object : scene->objects) {
1207 if (!object->get_geometry()->is_light()) {
1208 continue;
1209 }
1210
1211 Light *light = static_cast<Light *>(object->get_geometry());
1212 const float3 axisu = transform_get_column(&object->get_tfm(), 0);
1213 const float3 axisv = transform_get_column(&object->get_tfm(), 1);
1214 const float3 dir = -transform_get_column(&object->get_tfm(), 2);
1215 const float3 co = transform_get_column(&object->get_tfm(), 3);
1216
1217 /* Consider moving portals update to their own function
1218 * keeping this one more manageable. */
1219 if (light->is_portal) {
1220 assert(light->light_type == LIGHT_AREA);
1221
1222 const float3 extentu = axisu * (light->sizeu * light->size);
1223 const float3 extentv = axisv * (light->sizev * light->size);
1224
1225 float len_u;
1226 float len_v;
1227 const float3 axis_u = normalize_len(extentu, &len_u);
1228 const float3 axis_v = normalize_len(extentv, &len_v);
1229 const float area = light->area(object->get_tfm());
1230 float invarea = (area != 0.0f) ? 1.0f / area : 1.0f;
1231 if (light->ellipse) {
1232 /* Negative inverse area indicates ellipse. */
1233 invarea = -invarea;
1234 }
1235
1236 klights[portal_index].co = co;
1237 klights[portal_index].area.axis_u = axis_u;
1238 klights[portal_index].area.len_u = len_u;
1239 klights[portal_index].area.axis_v = axis_v;
1240 klights[portal_index].area.len_v = len_v;
1241 klights[portal_index].area.invarea = invarea;
1242 klights[portal_index].area.dir = safe_normalize(dir);
1243 klights[portal_index].object_id = object->index;
1244
1245 portal_index++;
1246 continue;
1247 }
1248
1249 if (!light->is_enabled) {
1250 continue;
1251 }
1252
1253 Shader *shader = (light->get_shader()) ? light->get_shader() : scene->default_light;
1254 int shader_id = scene->shader_manager->get_shader_id(shader);
1255
1256 if (!light->cast_shadow) {
1257 shader_id &= ~SHADER_CAST_SHADOW;
1258 }
1259
1260 shader_id |= light_object_shader_flags(object);
1261
1262 klights[light_index].type = light->light_type;
1263 klights[light_index].strength[0] = light->strength.x;
1264 klights[light_index].strength[1] = light->strength.y;
1265 klights[light_index].strength[2] = light->strength.z;
1266
1267 if (light->light_type == LIGHT_POINT || light->light_type == LIGHT_SPOT) {
1268 shader_id &= ~SHADER_AREA_LIGHT;
1269
1270 const float radius = light->size;
1271 const float invarea = (light->normalize) ? 1.0f / light->area(object->get_tfm()) : 1.0f;
1272
1273 /* Convert radiant flux to radiance or radiant intensity. */
1274 const float eval_fac = invarea * M_1_PI_F;
1275
1276 if (light->use_mis && radius > 0.0f) {
1277 shader_id |= SHADER_USE_MIS;
1278 }
1279
1280 klights[light_index].co = co;
1281 klights[light_index].spot.radius = radius;
1282 klights[light_index].spot.eval_fac = eval_fac;
1283 klights[light_index].spot.is_sphere = light->get_is_sphere() && radius != 0.0f;
1284 }
1285 else if (light->light_type == LIGHT_DISTANT) {
1286 shader_id &= ~SHADER_AREA_LIGHT;
1287
1288 const float angle = light->angle / 2.0f;
1289
1290 if (light->use_mis && angle > 0.0f) {
1291 shader_id |= SHADER_USE_MIS;
1292 }
1293
1294 const float one_minus_cosangle = 2.0f * sqr(sinf(0.5f * angle));
1295 const float pdf = (angle > 0.0f) ? (M_1_2PI_F / one_minus_cosangle) : 1.0f;
1296
1297 klights[light_index].co = safe_normalize(dir);
1298 klights[light_index].distant.angle = angle;
1299 klights[light_index].distant.one_minus_cosangle = one_minus_cosangle;
1300 klights[light_index].distant.pdf = pdf;
1301 klights[light_index].distant.eval_fac = (light->normalize) ?
1302 1.0f / light->area(object->get_tfm()) :
1303 1.0f;
1304 klights[light_index].distant.half_inv_sin_half_angle = (angle == 0.0f) ?
1305 0.0f :
1306 0.5f / sinf(0.5f * angle);
1307 }
1308 else if (light->light_type == LIGHT_BACKGROUND) {
1309 const uint visibility = scene->background->get_visibility();
1310
1311 dscene->data.background.light_index = light_index;
1312
1313 shader_id &= ~SHADER_AREA_LIGHT;
1314 shader_id |= SHADER_USE_MIS;
1315
1316 if (!(visibility & PATH_RAY_DIFFUSE)) {
1317 shader_id |= SHADER_EXCLUDE_DIFFUSE;
1318 }
1319 if (!(visibility & PATH_RAY_GLOSSY)) {
1320 shader_id |= SHADER_EXCLUDE_GLOSSY;
1321 }
1322 if (!(visibility & PATH_RAY_TRANSMIT)) {
1323 shader_id |= SHADER_EXCLUDE_TRANSMIT;
1324 }
1325 if (!(visibility & PATH_RAY_VOLUME_SCATTER)) {
1326 shader_id |= SHADER_EXCLUDE_SCATTER;
1327 }
1328 }
1329 else if (light->light_type == LIGHT_AREA) {
1330 const float light_size = light->size;
1331 const float3 extentu = axisu * (light->sizeu * light_size);
1332 const float3 extentv = axisv * (light->sizev * light_size);
1333
1334 float len_u;
1335 float len_v;
1336 const float3 axis_u = normalize_len(extentu, &len_u);
1337 const float3 axis_v = normalize_len(extentv, &len_v);
1338 const float area = light->area(object->get_tfm());
1339 float invarea = light->normalize ? 1.0f / area : 1.0f;
1340 if (light->ellipse) {
1341 /* Negative inverse area indicates ellipse. */
1342 invarea = -invarea;
1343 }
1344
1345 const float half_spread = 0.5f * fmaxf(light->spread, 0.0f);
1346 const float tan_half_spread = light->spread == M_PI_F ? FLT_MAX : tanf(half_spread);
1347 /* Normalization computed using:
1348 * integrate cos(x) * (1 - tan(x) / tan(a)) * sin(x) from x = 0 to a, a being half_spread.
1349 * Divided by tan_half_spread to simplify the attenuation computation in `area.h`. */
1350 /* Using third-order Taylor expansion at small angles for better accuracy. */
1351 const float normalize_spread = (half_spread > 0.0f) ?
1352 (half_spread > 0.05f ?
1353 1.0f / (tan_half_spread - half_spread) :
1354 3.0f / powf(half_spread, 3.0f)) :
1355 FLT_MAX;
1356
1357 if (light->use_mis && area != 0.0f && light->spread > 0.0f) {
1358 shader_id |= SHADER_USE_MIS;
1359 }
1360
1361 klights[light_index].co = co;
1362 klights[light_index].area.axis_u = axis_u;
1363 klights[light_index].area.len_u = len_u;
1364 klights[light_index].area.axis_v = axis_v;
1365 klights[light_index].area.len_v = len_v;
1366 klights[light_index].area.invarea = invarea;
1367 klights[light_index].area.dir = safe_normalize(dir);
1368 klights[light_index].area.tan_half_spread = tan_half_spread;
1369 klights[light_index].area.normalize_spread = normalize_spread;
1370 }
1371 if (light->light_type == LIGHT_SPOT) {
1372 const float cos_half_spot_angle = cosf(light->spot_angle * 0.5f);
1373 const float spot_smooth = 1.0f / ((1.0f - cos_half_spot_angle) * light->spot_smooth);
1374 const float tan_half_spot_angle = tanf(light->spot_angle * 0.5f);
1375
1376 const float len_w_sq = len_squared(dir);
1377 const float len_u_sq = len_squared(axisu);
1378 const float len_v_sq = len_squared(axisv);
1379 const float tan_sq = sqr(tan_half_spot_angle);
1380
1381 klights[light_index].spot.dir = safe_normalize(dir);
1382 klights[light_index].spot.cos_half_spot_angle = cos_half_spot_angle;
1383 klights[light_index].spot.half_cot_half_spot_angle = 0.5f / tan_half_spot_angle;
1384 klights[light_index].spot.spot_smooth = spot_smooth;
1385 /* Choose the angle which spans a larger cone. */
1386 klights[light_index].spot.cos_half_larger_spread = inversesqrtf(
1387 1.0f + tan_sq * fmaxf(len_u_sq, len_v_sq) / len_w_sq);
1388 /* radius / sin(half_angle_small) */
1389 klights[light_index].spot.ray_segment_dp =
1390 light->size * sqrtf(1.0f + len_w_sq / (tan_sq * fminf(len_u_sq, len_v_sq)));
1391 }
1392
1393 klights[light_index].shader_id = shader_id;
1394 klights[light_index].object_id = object->index;
1395
1396 klights[light_index].max_bounces = light->max_bounces;
1397 klights[light_index].use_caustics = light->use_caustics;
1398
1399 light_index++;
1400 }
1401
1402 LOG_INFO << "Number of lights sent to the device: " << num_lights;
1403
1404 dscene->lights.copy_to_device();
1405}
1406
1408 DeviceScene *dscene,
1409 Scene *scene,
1410 Progress &progress)
1411{
1412 if (!need_update()) {
1413 return;
1414 }
1415
1416 const scoped_callback_timer timer([scene](double time) {
1417 if (scene->update_stats) {
1418 scene->update_stats->light.times.add_entry({"device_update", time});
1419 }
1420 });
1421
1422 /* Detect which lights are enabled, also determines if we need to update the background. */
1423 test_enabled_lights(scene);
1424
1425 device_free(device, dscene, need_update_background);
1426
1427 device_update_lights(dscene, scene);
1428 if (progress.get_cancel()) {
1429 return;
1430 }
1431
1433 device_update_background(device, dscene, scene, progress);
1434 if (progress.get_cancel()) {
1435 return;
1436 }
1437 }
1438
1439 device_update_distribution(device, dscene, scene, progress);
1440 if (progress.get_cancel()) {
1441 return;
1442 }
1443
1444 device_update_tree(device, dscene, scene, progress);
1445 if (progress.get_cancel()) {
1446 return;
1447 }
1448
1449 device_update_ies(dscene);
1450 if (progress.get_cancel()) {
1451 return;
1452 }
1453
1455 need_update_background = false;
1456}
1457
1459 DeviceScene *dscene,
1460 const bool free_background)
1461{
1462 dscene->light_tree_nodes.free();
1463 dscene->light_tree_emitters.free();
1464 dscene->light_to_tree.free();
1465 dscene->object_to_tree.free();
1466 dscene->object_lookup_offset.free();
1467 dscene->triangle_to_tree.free();
1468
1469 dscene->light_distribution.free();
1470 dscene->lights.free();
1471 if (free_background) {
1474 }
1475 dscene->ies_lights.free();
1476}
1477
1478void LightManager::tag_update(Scene * /*scene*/, uint32_t flag)
1479{
1480 update_flags |= flag;
1481}
1482
1484{
1485 return update_flags != UPDATE_NONE;
1486}
1487
1488int LightManager::add_ies_from_file(const string &filename)
1489{
1490 string content;
1491
1492 /* If the file can't be opened, call with an empty line */
1493 if (filename.empty() || !path_read_text(filename, content)) {
1494 content = "\n";
1495 }
1496
1497 return add_ies(content);
1498}
1499
1500int LightManager::add_ies(const string &content)
1501{
1502 const uint hash = hash_string(content.c_str());
1503
1504 const thread_scoped_lock ies_lock(ies_mutex);
1505
1506 /* Check whether this IES already has a slot. */
1507 size_t slot;
1508 for (slot = 0; slot < ies_slots.size(); slot++) {
1509 if (ies_slots[slot]->hash == hash) {
1510 ies_slots[slot]->users++;
1511 return slot;
1512 }
1513 }
1514
1515 /* Try to find an empty slot for the new IES. */
1516 for (slot = 0; slot < ies_slots.size(); slot++) {
1517 if (ies_slots[slot]->users == 0 && ies_slots[slot]->hash == 0) {
1518 break;
1519 }
1520 }
1521
1522 /* If there's no free slot, add one. */
1523 if (slot == ies_slots.size()) {
1524 ies_slots.push_back(make_unique<IESSlot>());
1525 }
1526
1527 ies_slots[slot]->ies.load(content);
1528 ies_slots[slot]->users = 1;
1529 ies_slots[slot]->hash = hash;
1530
1533
1534 return slot;
1535}
1536
1537void LightManager::remove_ies(const int slot)
1538{
1539 const thread_scoped_lock ies_lock(ies_mutex);
1540
1541 if (slot < 0 || slot >= ies_slots.size()) {
1542 assert(false);
1543 return;
1544 }
1545
1546 assert(ies_slots[slot]->users > 0);
1547 ies_slots[slot]->users--;
1548
1549 /* If the slot has no more users, update the device to remove it. */
1550 if (ies_slots[slot]->users == 0) {
1553 }
1554}
1555
1557{
1558 /* Clear empty slots. */
1559 for (const unique_ptr<IESSlot> &slot : ies_slots) {
1560 if (slot->users == 0) {
1561 slot->hash = 0;
1562 slot->ies.clear();
1563 }
1564 }
1565
1566 /* Shrink the slot table by removing empty slots at the end. */
1567 int slot_end;
1568 for (slot_end = ies_slots.size(); slot_end; slot_end--) {
1569 if (ies_slots[slot_end - 1]->users > 0) {
1570 /* If the preceding slot has users, we found the new end of the table. */
1571 break;
1572 }
1573 }
1574 ies_slots.resize(slot_end);
1575
1576 if (!ies_slots.empty()) {
1577 int packed_size = 0;
1578 for (const unique_ptr<IESSlot> &slot : ies_slots) {
1579 packed_size += slot->ies.packed_size();
1580 }
1581
1582 /* ies_lights starts with an offset table that contains the offset of every slot,
1583 * or -1 if the slot is invalid.
1584 * Following that table, the packed valid IES lights are stored. */
1585 float *data = dscene->ies_lights.alloc(ies_slots.size() + packed_size);
1586
1587 int offset = ies_slots.size();
1588 for (int i = 0; i < ies_slots.size(); i++) {
1589 const int size = ies_slots[i]->ies.packed_size();
1590 if (size > 0) {
1591 data[i] = __int_as_float(offset);
1592 ies_slots[i]->ies.pack(data + offset);
1593 offset += size;
1594 }
1595 else {
1596 data[i] = __int_as_float(-1);
1597 }
1598 }
1599
1600 dscene->ies_lights.copy_to_device();
1601 }
1602}
1603
unsigned int uint
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:117
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert * v
ccl_device_inline float sin_theta(const float3 w)
unsigned long long int uint64_t
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
Shader * get_shader(const Scene *scene)
device_vector< KernelLightTreeEmitter > light_tree_emitters
Definition devicescene.h:66
device_vector< KernelLightTreeNode > light_tree_nodes
Definition devicescene.h:65
device_vector< uint > object_to_tree
Definition devicescene.h:68
device_vector< float2 > light_background_marginal_cdf
Definition devicescene.h:61
device_vector< uint > object_lookup_offset
Definition devicescene.h:69
device_vector< float > ies_lights
Definition devicescene.h:86
device_vector< float2 > light_background_conditional_cdf
Definition devicescene.h:62
device_vector< KernelLightDistribution > light_distribution
Definition devicescene.h:59
device_vector< uint > triangle_to_tree
Definition devicescene.h:70
KernelData data
Definition devicescene.h:94
device_vector< uint > light_to_tree
Definition devicescene.h:67
device_vector< KernelLight > lights
Definition devicescene.h:60
virtual void const_copy_to(const char *name, void *host, const size_t size)=0
bool transform_applied
size_t prim_offset
Geometry(const NodeType *node_type, const Type type)
bool empty() const
ImageMetaData metadata()
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress)
void device_update_ies(DeviceScene *dscene)
void device_update_tree(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress)
vector< unique_ptr< IESSlot > > ies_slots
int add_ies_from_file(const string &filename)
void device_update_lights(DeviceScene *dscene, Scene *scene)
void test_enabled_lights(Scene *scene)
uint32_t update_flags
void device_free(Device *device, DeviceScene *dscene, const bool free_background=true)
void remove_ies(const int slot)
void device_update_distribution(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress)
bool need_update_background
int add_ies(const string &content)
bool need_update() const
void tag_update(Scene *scene, const uint32_t flag)
void device_update_background(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress)
int last_background_resolution
thread_mutex ies_mutex
bool has_background_light(Scene *scene)
bool last_background_enabled
std::atomic< int > num_nodes
Definition light_tree.h:402
const LightTreeEmitter * get_emitters() const
Definition light_tree.h:432
uint64_t light_link_receiver_used
Definition light_tree.h:406
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
void set_status(const string &status_, const string &substatus_="")
Definition progress.h:248
void set_error(const string &error_message_)
Definition progress.h:98
bool eval(const ShaderEvalType type, const int max_num_inputs, const int num_channels, const std::function< int(device_vector< KernelShaderEvalInput > &)> &fill_input, const std::function< void(device_vector< float > &)> &read_output)
ShaderOutput * link
ShaderInput * input(const char *name)
ShaderOutput * output(const char *name)
ShaderNode * parent
bool has_surface_spatial_varying
float3 emission_estimate
EmissionSampling emission_sampling
NODE_DECLARE unique_ptr< ShaderGraph > graph
float get_sun_size()
float get_sun_average_radiance()
Transform compute_transform()
TextureMapping tex_mapping
T * alloc(const size_t width, const size_t height=0)
size_t size() const
#define LIGHT_LINK_SET_MAX
#define M_PI_2_F
#define PRIM_NONE
#define M_PI_4_F
#define OBJECT_NONE
#define M_1_PI_F
#define M_1_2PI_F
#define powf(x, y)
#define CCL_NAMESPACE_END
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
#define __int_as_float(x)
ccl_device_forceinline int2 make_int2(const int x, const int y)
int users
#define assert(assertion)
#define in
VecBase< float, D > normalize(VecOp< float, D >) RET
static uint hash_string(const char *str)
Definition hash.h:637
PrimitiveType
@ PRIMITIVE_LAMP
LightTreeNodeType
@ LIGHT_TREE_INSTANCE
@ PATH_RAY_TRANSMIT
@ PATH_RAY_VOLUME_SCATTER
@ PATH_RAY_GLOSSY
@ PATH_RAY_DIFFUSE
@ PATH_RAY_CAMERA
@ EMISSION_SAMPLING_NONE
@ SHADER_EXCLUDE_SHADOW_CATCHER
@ SHADER_EXCLUDE_CAMERA
@ SHADER_EXCLUDE_DIFFUSE
@ SHADER_USE_MIS
@ SHADER_EXCLUDE_SCATTER
@ SHADER_EXCLUDE_GLOSSY
@ SHADER_AREA_LIGHT
@ SHADER_EXCLUDE_TRANSMIT
@ SHADER_CAST_SHADOW
@ LIGHT_AREA
@ LIGHT_DISTANT
@ LIGHT_SPOT
@ LIGHT_BACKGROUND
@ LIGHT_POINT
#define LOG_DEBUG
Definition log.h:107
#define LOG_INFO
Definition log.h:106
ccl_device_inline float inversesqrtf(const float f)
Definition math_base.h:529
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 float2 fabs(const float2 a)
ccl_device_inline float3 one_float3()
Definition math_float3.h:26
CCL_NAMESPACE_BEGIN ccl_device_inline float3 zero_float3()
Definition math_float3.h:17
ccl_device_inline float triangle_area(const ccl_private float3 &v1, const ccl_private float3 &v2, const ccl_private float3 &v3)
float average(point a)
Definition node_math.h:144
#define SOCKET_FLOAT(name, ui_name, default_value,...)
Definition node_type.h:211
#define SOCKET_INT(name, ui_name, default_value,...)
Definition node_type.h:205
#define NODE_DEFINE(structname)
Definition node_type.h:152
#define SOCKET_COLOR(name, ui_name, default_value,...)
Definition node_type.h:213
#define SOCKET_BOOLEAN(name, ui_name, default_value,...)
Definition node_type.h:203
#define SOCKET_ENUM(name, ui_name, values, default_value,...)
Definition node_type.h:227
#define hash
Definition noise_c.cc:154
bool path_read_text(const string &path, string &text)
Definition path.cpp:739
#define sqr
#define sqrtf
#define fmaxf
#define sinf
#define tanf
#define make_float4
#define fminf
#define M_PI_F
#define cosf
static void light_tree_emitters_copy_and_flatten(LightTreeFlatten &flatten, const LightTreeNode *node, KernelLightTreeNode *knodes, KernelLightTreeEmitter *kemitters, int &next_node_index)
static uint light_object_shader_flags(Object *object)
static CCL_NAMESPACE_BEGIN void shade_background_pixels(Device *device, DeviceScene *dscene, const int width, const int height, vector< float3 > &pixels, Progress &progress)
static int light_tree_flatten(LightTreeFlatten &flatten, const LightTreeNode *node, KernelLightTreeNode *knodes, KernelLightTreeEmitter *kemitters, int &next_node_index)
static void light_tree_leaf_emitters_copy_and_flatten(LightTreeFlatten &flatten, const LightTreeNode &node, KernelLightTreeNode *knodes, KernelLightTreeEmitter *kemitters, int &next_node_index)
static void light_tree_node_copy_to_device(KernelLightTreeNode &knode, const LightTreeNode &node, const int left_child, const int right_child)
static void background_cdf(int start, const int end, const int res_x, const int res_y, const vector< float3 > *pixels, float2 *cond_cdf)
static std::pair< int, LightTreeMeasure > light_tree_specialize_nodes_flatten(const LightTreeFlatten &flatten, LightTreeNode *node, const uint64_t light_link_mask, const int depth, vector< KernelLightTreeNode > &knodes, int &next_node_index, bool can_share=true)
@ SHADER_EVAL_BACKGROUND
Definition shader_eval.h:20
float3 sun_direction(float sun_cos_theta)
Definition sky_math.h:457
#define FLT_MAX
Definition stdcycles.h:14
float3 max
Definition boundbox.h:20
float3 min
Definition boundbox.h:20
packed_float3 axis_u
packed_float3 axis_v
packed_float3 dir
packed_float3 min
packed_float3 max
packed_float3 axis
struct KernelLightTreeEmitter::@100244224035147311323362061026206066304156105230::@145257001270125053357336343156215202056055243242 light
struct KernelLightTreeEmitter::@100244224035147311323362061026206066304156105230::@155115103153173066061151154125014102203306247176 mesh
EmissionSampling emission_sampling
struct KernelLightTreeEmitter::@100244224035147311323362061026206066304156105230::@126172035204211036214107167014276257320000170324 triangle
struct KernelLightTreeNode::@075060275333356206225201163255143122031204113015::@064327011010203173153234374026232040346041241257 instance
LightTreeNodeType type
KernelBoundingBox bbox
struct KernelLightTreeNode::@075060275333356206225201163255143122031204113015::@121232343267032302300332005257270111102366024356 inner
KernelBoundingCone bcone
struct KernelLightTreeNode::@075060275333356206225201163255143122031204113015::@354167317357124241334100100220231122277063225056 leaf
float strength[3]
KernelSpotLight spot
packed_float3 co
KernelDistantLight distant
KernelAreaLight area
float half_cot_half_spot_angle
packed_float3 dir
float cos_half_larger_spread
__forceinline bool is_mesh() const
Definition light_tree.h:205
__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
__forceinline bool is_light() const
Definition light_tree.h:215
const uint * object_lookup_offset
const LightTreeEmitter * emitters
std::unordered_map< LightTreeNode *, int > instances
const Scene * scene
OrientationBounds bcone
Definition light_tree.h:66
__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
__forceinline bool is_leaf() const
Definition light_tree.h:365
void make_leaf(const int first_emitter_index, const int num_emitters)
Definition light_tree.h:321
LightTreeNode * get_reference()
Definition light_tree.h:351
LightTreeMeasure measure
Definition light_tree.h:250
std::variant< Leaf, Inner, Instance > variant_type
Definition light_tree.h:275
void make_distant(const int first_emitter_index, const int num_emitters)
Definition light_tree.h:331
__forceinline bool is_inner() const
Definition light_tree.h:370
LightTreeLightLink light_link
Definition light_tree.h:251
__forceinline bool is_instance() const
Definition light_tree.h:360
__forceinline Leaf & get_leaf()
Definition light_tree.h:291
__forceinline bool is_distant() const
Definition light_tree.h:375
bool has_contribution(const Scene *scene, const Object *object)
void tag_update(Scene *scene)
void get_uv_tiles(ustring map, unordered_set< int > &tiles) override
void compute_bounds() override
void apply_transform(const Transform &tfm, const bool apply_to_motion) override
PrimitiveType primitive_type() const override
Shader * get_shader() const
float area(const Transform &tfm) const
bool valid(const float3 *verts) const
size_t num_triangles() const
Definition scene/mesh.h:77
Triangle get_triangle(const size_t i) const
Definition scene/mesh.h:71
void insert(const char *x, const int y)
Definition node_enum.h:21
static NodeType * add(const char *name, CreateFunc create, Type type=NONE, const NodeType *base=nullptr)
const NodeType * type
Definition graph/node.h:178
void dereference_all_used_nodes()
bool is_modified() const
Node(const NodeType *type, ustring name=ustring())
bool usable_as_light() const
unique_ptr< LightManager > light_manager
Definition scene.h:146
Shader * default_surface
Definition scene.h:157
unique_ptr< SceneUpdateStats > update_stats
Definition scene.h:175
Background * background
Definition scene.h:129
unique_ptr< ShaderManager > shader_manager
Definition scene.h:148
unique_ptr_vector< Object > objects
Definition scene.h:141
Integrator * integrator
Definition scene.h:130
Shader * default_light
Definition scene.h:159
float x
float y
i
Definition text_draw.cc:230
max
Definition text_draw.cc:251
std::unique_lock< std::mutex > thread_scoped_lock
Definition thread.h:28
CCL_NAMESPACE_BEGIN double time_dt()
Definition time.cpp:47
ccl_device_inline float3 transform_get_column(const Transform *t, const int column)
Definition transform.h:354
ccl_device_inline Transform transform_inverse(const Transform tfm)
Definition transform.h:525
ccl_device_inline float3 transform_direction(const ccl_private Transform *t, const float3 a)
Definition transform.h:127
ccl_device_inline float3 transform_point(const ccl_private Transform *t, const float3 a)
Definition transform.h:56
ccl_device_inline size_t divide_up(const size_t x, const size_t y)
Definition types_base.h:52
wmTimer * timer
uint len
uint8_t flag
Definition wm_window.cc:145