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