Blender V4.5
scene/shader.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/camera.h"
9#include "scene/integrator.h"
10#include "scene/light.h"
11#include "scene/mesh.h"
12#include "scene/object.h"
13#include "scene/osl.h"
14#include "scene/procedural.h"
15#include "scene/scene.h"
16#include "scene/shader.h"
17#include "scene/shader_graph.h"
18#include "scene/shader_nodes.h"
19#include "scene/svm.h"
20#include "scene/tables.h"
21
22#include "util/log.h"
23#include "util/murmurhash.h"
24#include "util/transform.h"
25
26#ifdef WITH_OCIO
27# include <OpenColorIO/OpenColorIO.h>
28namespace OCIO = OCIO_NAMESPACE;
29#endif
30
31#include "scene/shader.tables"
32
34
36
37/* Shader */
38
40{
41 NodeType *type = NodeType::add("shader", create);
42
43 static NodeEnum emission_sampling_method_enum;
44 emission_sampling_method_enum.insert("none", EMISSION_SAMPLING_NONE);
45 emission_sampling_method_enum.insert("auto", EMISSION_SAMPLING_AUTO);
46 emission_sampling_method_enum.insert("front", EMISSION_SAMPLING_FRONT);
47 emission_sampling_method_enum.insert("back", EMISSION_SAMPLING_BACK);
48 emission_sampling_method_enum.insert("front_back", EMISSION_SAMPLING_FRONT_BACK);
49 SOCKET_ENUM(emission_sampling_method,
50 "Emission Sampling Method",
51 emission_sampling_method_enum,
53
54 SOCKET_BOOLEAN(use_transparent_shadow, "Use Transparent Shadow", true);
55 SOCKET_BOOLEAN(use_bump_map_correction, "Bump Map Correction", true);
56 SOCKET_BOOLEAN(heterogeneous_volume, "Heterogeneous Volume", true);
57
58 static NodeEnum volume_sampling_method_enum;
59 volume_sampling_method_enum.insert("distance", VOLUME_SAMPLING_DISTANCE);
60 volume_sampling_method_enum.insert("equiangular", VOLUME_SAMPLING_EQUIANGULAR);
61 volume_sampling_method_enum.insert("multiple_importance", VOLUME_SAMPLING_MULTIPLE_IMPORTANCE);
62 SOCKET_ENUM(volume_sampling_method,
63 "Volume Sampling Method",
64 volume_sampling_method_enum,
66
67 static NodeEnum volume_interpolation_method_enum;
68 volume_interpolation_method_enum.insert("linear", VOLUME_INTERPOLATION_LINEAR);
69 volume_interpolation_method_enum.insert("cubic", VOLUME_INTERPOLATION_CUBIC);
70 SOCKET_ENUM(volume_interpolation_method,
71 "Volume Interpolation Method",
72 volume_interpolation_method_enum,
74
75 SOCKET_FLOAT(volume_step_rate, "Volume Step Rate", 1.0f);
76
77 static NodeEnum displacement_method_enum;
78 displacement_method_enum.insert("bump", DISPLACE_BUMP);
79 displacement_method_enum.insert("true", DISPLACE_TRUE);
80 displacement_method_enum.insert("both", DISPLACE_BOTH);
81 SOCKET_ENUM(displacement_method, "Displacement Method", displacement_method_enum, DISPLACE_BUMP);
82
83 SOCKET_INT(pass_id, "Pass ID", 0);
84
85 return type;
86}
87
88Shader::Shader() : Node(get_node_type())
89{
90 pass_id = 0;
91
92 graph = nullptr;
93
94 has_surface = false;
97 has_surface_bssrdf = false;
98 has_volume = false;
99 has_displacement = false;
101 has_bump_from_surface = false;
102 has_bssrdf_bump = false;
106 has_volume_connected = false;
108
112
113 displacement_method = DISPLACE_BUMP;
114
115 id = -1;
116
117 need_update_uvs = true;
120}
121
123{
124 /* Only supports a few nodes for now, not arbitrary shader graphs. */
125 ShaderNode *node = (output) ? output->parent : nullptr;
126
127 if (node == nullptr) {
128 return zero_float3();
129 }
130 if (node->type == EmissionNode::get_node_type() ||
131 node->type == BackgroundNode::get_node_type() ||
132 node->type == PrincipledBsdfNode::get_node_type())
133 {
134 const bool is_principled = (node->type == PrincipledBsdfNode::get_node_type());
135 /* Emission and Background node. */
136 ShaderInput *color_in = node->input(is_principled ? "Emission Color" : "Color");
137 ShaderInput *strength_in = node->input(is_principled ? "Emission Strength" : "Strength");
138
139 if (is_principled) {
140 /* Too many parameters (coat, sheen, alpha) influence Emission for the Principled BSDF. */
141 is_constant = false;
142 }
143
144 float3 estimate = one_float3();
145
146 if (color_in->link) {
147 is_constant = false;
148 }
149 else {
150 estimate *= node->get_float3(color_in->socket_type);
151 }
152
153 if (strength_in->link) {
154 is_constant = false;
155 estimate *= output_estimate_emission(strength_in->link, is_constant);
156 }
157 else {
158 estimate *= node->get_float(strength_in->socket_type);
159 }
160
161 return estimate;
162 }
163 if (node->type == LightFalloffNode::get_node_type() ||
164 node->type == IESLightNode::get_node_type())
165 {
166 /* Get strength from Light Falloff and IES texture node. */
167 ShaderInput *strength_in = node->input("Strength");
168 is_constant = false;
169
170 return (strength_in->link) ? output_estimate_emission(strength_in->link, is_constant) :
171 make_float3(node->get_float(strength_in->socket_type));
172 }
173 if (node->type == AddClosureNode::get_node_type()) {
174 /* Add Closure. */
175 ShaderInput *closure1_in = node->input("Closure1");
176 ShaderInput *closure2_in = node->input("Closure2");
177
178 const float3 estimate1 = (closure1_in->link) ?
179 output_estimate_emission(closure1_in->link, is_constant) :
180 zero_float3();
181 const float3 estimate2 = (closure2_in->link) ?
182 output_estimate_emission(closure2_in->link, is_constant) :
183 zero_float3();
184
185 return estimate1 + estimate2;
186 }
187 if (node->type == MixClosureNode::get_node_type()) {
188 /* Mix Closure. */
189 ShaderInput *fac_in = node->input("Fac");
190 ShaderInput *closure1_in = node->input("Closure1");
191 ShaderInput *closure2_in = node->input("Closure2");
192
193 const float3 estimate1 = (closure1_in->link) ?
194 output_estimate_emission(closure1_in->link, is_constant) :
195 zero_float3();
196 const float3 estimate2 = (closure2_in->link) ?
197 output_estimate_emission(closure2_in->link, is_constant) :
198 zero_float3();
199
200 if (fac_in->link) {
201 is_constant = false;
202 return estimate1 + estimate2;
203 }
204
205 const float fac = node->get_float(fac_in->socket_type);
206 return (1.0f - fac) * estimate1 + fac * estimate2;
207 }
208
209 /* Other nodes, potentially OSL nodes with arbitrary code for which all we can
210 * determine is if it has emission or not. */
211 const bool has_emission = node->has_surface_emission();
212 float3 estimate;
213
214 if (output->type() == SocketType::CLOSURE) {
215 if (has_emission) {
216 estimate = one_float3();
217 is_constant = false;
218 }
219 else {
220 estimate = zero_float3();
221 }
222
223 for (const ShaderInput *in : node->inputs) {
224 if (in->type() == SocketType::CLOSURE && in->link) {
225 estimate += output_estimate_emission(in->link, is_constant);
226 }
227 }
228 }
229 else {
230 estimate = one_float3();
231 is_constant = false;
232 }
233
234 return estimate;
235}
236
238{
239 /* If the shader has AOVs, they need to be evaluated, so we can't skip the shader. */
241
242 for (ShaderNode *node : graph->nodes) {
244 emission_is_constant = false;
245 }
246 }
247
248 ShaderInput *surf = graph->output()->input("Surface");
250
253 }
254 else if (emission_sampling_method == EMISSION_SAMPLING_AUTO) {
255 /* Automatically disable MIS when emission is low, to avoid weakly emitting
256 * using a lot of memory in the light tree and potentially wasting samples
257 * where indirect light samples are sufficient.
258 * Possible optimization: estimate front and back emission separately. */
259
260 /* Lower importance of emission nodes from automatic value/color to shader conversion, as these
261 * are likely used for previewing and can be slow to build a light tree for on dense meshes. */
262 float scale = 1.0f;
263 const ShaderOutput *output = surf->link;
264 if (output && output->parent->type == EmissionNode::get_node_type()) {
265 const EmissionNode *emission_node = static_cast<const EmissionNode *>(output->parent);
266 if (emission_node->from_auto_conversion) {
267 scale = 0.1f;
268 }
269 }
270
274 }
275 else {
276 emission_sampling = emission_sampling_method;
277 }
278}
279
281{
282 /* do this here already so that we can detect if mesh or object attributes
283 * are needed, since the node attribute callbacks check if their sockets
284 * are connected but proxy nodes should not count */
285 if (graph_) {
286 graph_->remove_proxy_nodes();
287
288 if (displacement_method != DISPLACE_BUMP) {
289 graph_->compute_displacement_hash();
290 }
291 }
292
293 /* update geometry if displacement changed */
294 if (displacement_method != DISPLACE_BUMP) {
295 const char *old_hash = (graph) ? graph->displacement_hash.c_str() : "";
296 const char *new_hash = (graph_) ? graph_->displacement_hash.c_str() : "";
297
298 if (strcmp(old_hash, new_hash) != 0) {
300 }
301 }
302
303 /* assign graph */
304 graph = std::move(graph_);
305
306 /* Store info here before graph optimization to make sure that
307 * nodes that get optimized away still count. */
308 has_volume_connected = (graph->output()->input("Volume")->link != nullptr);
309}
310
312{
313 /* update tag */
314 tag_modified();
315
316 scene->shader_manager->tag_update(scene, ShaderManager::SHADER_MODIFIED);
317
318 /* if the shader previously was emissive, update light distribution,
319 * if the new shader is emissive, a light manager update tag will be
320 * done in the shader manager device update. */
322 scene->light_manager->tag_update(scene, LightManager::SHADER_MODIFIED);
323 }
324
325 /* Special handle of background MIS light for now: for some reason it
326 * has use_mis set to false. We are quite close to release now, so
327 * better to be safe.
328 */
329 if (this == scene->background->get_shader(scene)) {
330 scene->light_manager->need_update_background = true;
331 if (scene->light_manager->has_background_light(scene)) {
332 scene->light_manager->tag_update(scene, LightManager::SHADER_MODIFIED);
333 }
334 }
335
336 /* quick detection of which kind of shaders we have to avoid loading
337 * e.g. surface attributes when there is only a volume shader. this could
338 * be more fine grained but it's better than nothing */
339 OutputNode *output = graph->output();
340 const bool prev_has_volume = has_volume;
341 has_surface = has_surface || output->input("Surface")->link;
342 has_volume = has_volume || output->input("Volume")->link;
343 has_displacement = has_displacement || output->input("Displacement")->link;
344
345 if (!has_surface && !has_volume) {
346 /* If we need to output surface AOVs, add a Transparent BSDF so that the
347 * surface shader runs. */
348 for (ShaderNode *node : graph->nodes) {
350 for (const ShaderInput *in : node->inputs) {
351 if (in->link) {
352 TransparentBsdfNode *transparent = graph->create_node<TransparentBsdfNode>();
353 graph->connect(transparent->output("BSDF"), output->input("Surface"));
354 has_surface = true;
355 break;
356 }
357 }
358 if (has_surface) {
359 break;
360 }
361 }
362 }
363 }
364
365 /* get requested attributes. this could be optimized by pruning unused
366 * nodes here already, but that's the job of the shader manager currently,
367 * and may not be so great for interactive rendering where you temporarily
368 * disconnect a node */
369
370 const AttributeRequestSet prev_attributes = attributes;
371
372 attributes.clear();
373 for (ShaderNode *node : graph->nodes) {
374 node->attributes(this, &attributes);
375 }
376
377 if (has_displacement) {
378 if (displacement_method == DISPLACE_BOTH) {
380 }
381 if (displacement_method_is_modified()) {
384 scene->object_manager->need_flags_update = true;
385 }
386 }
387
388 /* compare if the attributes changed, mesh manager will check
389 * need_update_attribute, update the relevant meshes and clear it. */
390 if (attributes.modified(prev_attributes)) {
393 scene->procedural_manager->tag_update();
394 }
395
396 if (has_volume != prev_has_volume || volume_step_rate != prev_volume_step_rate) {
397 scene->geometry_manager->need_flags_update = true;
398 scene->object_manager->need_flags_update = true;
399 prev_volume_step_rate = volume_step_rate;
400 }
401}
402
404{
405 /* if an unused shader suddenly gets used somewhere, it needs to be
406 * recompiled because it was skipped for compilation before */
407 if (!reference_count()) {
408 tag_modified();
409 /* We do not reference here as the shader will be referenced when added to a socket. */
410 scene->shader_manager->tag_update(scene, ShaderManager::SHADER_MODIFIED);
411 }
412}
413
418
419/* Shader Manager */
420
427
429
431{
433
434 (void)shadingsystem; /* Ignored when built without OSL. */
435
436#ifdef WITH_OSL
437 if (shadingsystem == SHADINGSYSTEM_OSL) {
438 manager = make_unique<OSLShaderManager>();
439 }
440 else
441#endif
442 {
443 manager = make_unique<SVMShaderManager>();
444 }
445
446 return manager;
447}
448
450{
452
453 /* get a unique id for each name, for SVM attribute lookup */
454 const AttributeIDMap::iterator it = unique_attribute_id.find(name);
455
456 if (it != unique_attribute_id.end()) {
457 return it->second;
458 }
459
460 const uint64_t id = ATTR_STD_NUM + unique_attribute_id.size();
461 unique_attribute_id[name] = id;
462 return id;
463}
464
469
470int ShaderManager::get_shader_id(Shader *shader, bool smooth)
471{
472 /* get a shader id to pass to the kernel */
473 int id = shader->id;
474
475 /* smooth flag */
476 if (smooth) {
478 }
479
480 /* default flags */
482
483 return id;
484}
485
487 DeviceScene * /*dscene*/,
488 Scene *scene,
489 Progress & /*progress*/)
490{
491 /* This optimizes the shader graphs, but does not update anything on the device yet.
492 * After this we'll know the kernel features actually used, to load the kernels. */
493 if (!need_update()) {
494 return;
495 }
496
497 uint id = 0;
498 for (Shader *shader : scene->shaders) {
499 shader->id = id++;
500 }
501
502 /* Those shaders should always be compiled as they are used as a fallback if a shader cannot be
503 * found, e.g. bad shader index for the triangle shaders on a Mesh. */
504 assert(scene->default_surface->reference_count() != 0);
505 assert(scene->default_light->reference_count() != 0);
507 assert(scene->default_empty->reference_count() != 0);
508
509 for (Shader *shader : scene->shaders) {
510 if (shader->is_modified()) {
511 ShaderNode *output = shader->graph->output();
512
513 shader->has_bump_from_displacement = (shader->get_displacement_method() != DISPLACE_TRUE) &&
514 output->input("Surface")->link &&
515 output->input("Displacement")->link;
517
518 shader->graph->finalize(scene,
520 shader->get_displacement_method() == DISPLACE_BOTH);
521 }
522 }
523}
524
526 DeviceScene *dscene,
527 Scene *scene,
529{
530 device_update_specific(device, dscene, scene, progress);
531
532 /* This runs after kernels have been loaded, so can copy to device. */
535}
536
538 DeviceScene *dscene,
539 Scene *scene,
540 Progress & /*progress*/)
541{
542 dscene->shaders.free();
543
544 if (scene->shaders.empty()) {
545 return;
546 }
547
548 KernelShader *kshader = dscene->shaders.alloc(scene->shaders.size());
549 bool has_volumes = false;
550 bool has_transparent_shadow = false;
551
552 for (Shader *shader : scene->shaders) {
553 uint flag = 0;
554
557 }
558 else if (shader->emission_sampling == EMISSION_SAMPLING_BACK) {
559 flag |= SD_MIS_BACK;
560 }
563 }
564
565 if (!is_zero(shader->emission_estimate)) {
567 }
568 if (shader->has_surface_transparent && shader->get_use_transparent_shadow()) {
570 }
571 if (shader->has_surface_raytrace) {
573 }
574 if (shader->has_volume) {
576 has_volumes = true;
577
578 /* todo: this could check more fine grained, to skip useless volumes
579 * enclosed inside an opaque bsdf.
580 */
582 }
583 /* in this case we can assume transparent surface */
584 if (shader->has_volume_connected && !shader->has_surface) {
586 }
587 if (shader->has_volume) {
588 if (shader->get_heterogeneous_volume() && shader->has_volume_spatial_varying) {
590 }
591 }
594 }
595 if (shader->has_bssrdf_bump) {
597 }
598 if (shader->get_volume_sampling_method() == VOLUME_SAMPLING_EQUIANGULAR) {
600 }
601 if (shader->get_volume_sampling_method() == VOLUME_SAMPLING_MULTIPLE_IMPORTANCE) {
603 }
604 if (shader->get_volume_interpolation_method() == VOLUME_INTERPOLATION_CUBIC) {
606 }
607 if (shader->has_bump_from_displacement) {
609 }
610 if (shader->has_bump_from_surface) {
612 }
613 if (shader->get_displacement_method() != DISPLACE_BUMP) {
615 }
616 if (shader->get_use_bump_map_correction()) {
618 }
619
620 /* constant emission check */
621 if (shader->emission_is_constant) {
623 }
624
625 const uint32_t cryptomatte_id = util_murmur_hash3(
626 shader->name.c_str(), shader->name.length(), 0);
627
628 /* regular shader */
629 kshader->flags = flag;
630 kshader->pass_id = shader->get_pass_id();
631 kshader->constant_emission[0] = shader->emission_estimate.x;
632 kshader->constant_emission[1] = shader->emission_estimate.y;
633 kshader->constant_emission[2] = shader->emission_estimate.z;
634 kshader->cryptomatte_id = util_hash_to_float(cryptomatte_id);
635 kshader++;
636
637 has_transparent_shadow |= (flag & SD_HAS_TRANSPARENT_SHADOW) != 0;
638 }
639
640 /* lookup tables */
641 KernelTables *ktables = &dscene->data.tables;
642 ktables->ggx_E = ensure_bsdf_table(dscene, scene, table_ggx_E);
643 ktables->ggx_Eavg = ensure_bsdf_table(dscene, scene, table_ggx_Eavg);
644 ktables->ggx_glass_E = ensure_bsdf_table(dscene, scene, table_ggx_glass_E);
645 ktables->ggx_glass_Eavg = ensure_bsdf_table(dscene, scene, table_ggx_glass_Eavg);
646 ktables->ggx_glass_inv_E = ensure_bsdf_table(dscene, scene, table_ggx_glass_inv_E);
647 ktables->ggx_glass_inv_Eavg = ensure_bsdf_table(dscene, scene, table_ggx_glass_inv_Eavg);
648 ktables->sheen_ltc = ensure_bsdf_table(dscene, scene, table_sheen_ltc);
649 ktables->ggx_gen_schlick_ior_s = ensure_bsdf_table(dscene, scene, table_ggx_gen_schlick_ior_s);
650 ktables->ggx_gen_schlick_s = ensure_bsdf_table(dscene, scene, table_ggx_gen_schlick_s);
651
652 /* integrator */
653 KernelIntegrator *kintegrator = &dscene->data.integrator;
654 kintegrator->use_volumes = has_volumes;
655 /* TODO(sergey): De-duplicate with flags set in integrator.cpp. */
656 kintegrator->transparent_shadows = has_transparent_shadow;
657
658 /* film */
659 KernelFilm *kfilm = &dscene->data.film;
660 /* color space, needs to be here because e.g. displacement shaders could depend on it */
661 kfilm->xyz_to_r = make_float4(xyz_to_r);
662 kfilm->xyz_to_g = make_float4(xyz_to_g);
663 kfilm->xyz_to_b = make_float4(xyz_to_b);
664 kfilm->rgb_to_y = make_float4(rgb_to_y);
665 kfilm->white_xyz = make_float4(white_xyz);
666 kfilm->rec709_to_r = make_float4(rec709_to_r);
667 kfilm->rec709_to_g = make_float4(rec709_to_g);
668 kfilm->rec709_to_b = make_float4(rec709_to_b);
669 kfilm->is_rec709 = is_rec709;
670}
671
673{
674 for (auto &entry : bsdf_tables) {
675 scene->lookup_tables->remove_table(&entry.second);
676 }
677 bsdf_tables.clear();
678
679 dscene->shaders.free();
680}
681
683{
684 /* default surface */
685 {
686 unique_ptr<ShaderGraph> graph = make_unique<ShaderGraph>();
687
688 DiffuseBsdfNode *diffuse = graph->create_node<DiffuseBsdfNode>();
689 diffuse->set_color(make_float3(0.8f, 0.8f, 0.8f));
690
691 graph->connect(diffuse->output("BSDF"), graph->output()->input("Surface"));
692
693 Shader *shader = scene->create_node<Shader>();
694 shader->name = "default_surface";
695 shader->set_graph(std::move(graph));
696 shader->reference();
697 scene->default_surface = shader;
698 shader->tag_update(scene);
699 }
700
701 /* default volume */
702 {
703 unique_ptr<ShaderGraph> graph = make_unique<ShaderGraph>();
704
705 PrincipledVolumeNode *principled = graph->create_node<PrincipledVolumeNode>();
706
707 graph->connect(principled->output("Volume"), graph->output()->input("Volume"));
708
709 Shader *shader = scene->create_node<Shader>();
710 shader->name = "default_volume";
711 shader->set_graph(std::move(graph));
712 scene->default_volume = shader;
713 shader->tag_update(scene);
714 /* No default reference for the volume to avoid compiling volume kernels if there are no
715 * actual volumes in the scene */
716 }
717
718 /* default light */
719 {
720 unique_ptr<ShaderGraph> graph = make_unique<ShaderGraph>();
721
722 EmissionNode *emission = graph->create_node<EmissionNode>();
723 emission->set_color(make_float3(0.8f, 0.8f, 0.8f));
724 emission->set_strength(0.0f);
725
726 graph->connect(emission->output("Emission"), graph->output()->input("Surface"));
727
728 Shader *shader = scene->create_node<Shader>();
729 shader->name = "default_light";
730 shader->set_graph(std::move(graph));
731 shader->reference();
732 scene->default_light = shader;
733 shader->tag_update(scene);
734 }
735
736 /* default background */
737 {
738 unique_ptr<ShaderGraph> graph = make_unique<ShaderGraph>();
739
740 Shader *shader = scene->create_node<Shader>();
741 shader->name = "default_background";
742 shader->set_graph(std::move(graph));
743 shader->reference();
744 scene->default_background = shader;
745 shader->tag_update(scene);
746 }
747
748 /* default empty */
749 {
750 unique_ptr<ShaderGraph> graph = make_unique<ShaderGraph>();
751
752 Shader *shader = scene->create_node<Shader>();
753 shader->name = "default_empty";
754 shader->set_graph(std::move(graph));
755 shader->reference();
756 scene->default_empty = shader;
757 shader->tag_update(scene);
758 }
759}
760
762{
763 uint kernel_features = 0;
764
765 for (ShaderNode *node : graph->nodes) {
766 kernel_features |= node->get_feature();
768 BsdfBaseNode *bsdf_node = static_cast<BsdfBaseNode *>(node);
769 if (CLOSURE_IS_VOLUME(bsdf_node->get_closure_type())) {
770 kernel_features |= KERNEL_FEATURE_NODE_VOLUME;
771 }
772 }
773 if (node->has_surface_bssrdf()) {
774 kernel_features |= KERNEL_FEATURE_SUBSURFACE;
775 }
776 if (node->has_surface_transparent()) {
777 kernel_features |= KERNEL_FEATURE_TRANSPARENT;
778 }
779 }
780
781 return kernel_features;
782}
783
785{
787 for (int i = 0; i < scene->shaders.size(); i++) {
788 Shader *shader = scene->shaders[i];
789 if (!shader->reference_count()) {
790 continue;
791 }
792
793 /* Gather requested features from all the nodes from the graph nodes. */
794 kernel_features |= get_graph_kernel_features(shader->graph.get());
795 ShaderNode *output_node = shader->graph->output();
796 if (output_node->input("Displacement")->link != nullptr) {
797 kernel_features |= KERNEL_FEATURE_NODE_BUMP;
798 if (shader->get_displacement_method() == DISPLACE_BOTH) {
799 kernel_features |= KERNEL_FEATURE_NODE_BUMP_STATE;
800 }
801 }
802 /* On top of volume nodes, also check if we need volume sampling because
803 * e.g. an Emission node would slip through the KERNEL_FEATURE_NODE_VOLUME check */
804 if (shader->has_volume_connected) {
805 kernel_features |= KERNEL_FEATURE_VOLUME;
806 }
807 }
808
809 if (use_osl()) {
810 kernel_features |= KERNEL_FEATURE_OSL_SHADING;
811 }
812
813 return kernel_features;
814}
815
817{
818 return dot(c, rgb_to_y);
819}
820
825
827{
828 string manifest = "{";
829 unordered_set<ustring> materials;
830 for (Shader *shader : scene->shaders) {
831 if (materials.count(shader->name)) {
832 continue;
833 }
834 materials.insert(shader->name);
835 const uint32_t cryptomatte_id = util_murmur_hash3(
836 shader->name.c_str(), shader->name.length(), 0);
837 manifest += string_printf("\"%s\":\"%08x\",", shader->name.c_str(), cryptomatte_id);
838 }
839 manifest[manifest.size() - 1] = '}';
840 return manifest;
841}
842
843void ShaderManager::tag_update(Scene * /*scene*/, uint32_t /*flag*/)
844{
845 /* update everything for now */
847}
848
850{
851 return update_flags != UPDATE_NONE;
852}
853
854#ifdef WITH_OCIO
855static bool to_scene_linear_transform(OCIO::ConstConfigRcPtr &config,
856 const char *colorspace,
857 Transform &to_scene_linear)
858{
859 OCIO::ConstProcessorRcPtr processor;
860 try {
861 processor = config->getProcessor("scene_linear", colorspace);
862 }
863 catch (OCIO::Exception &) {
864 return false;
865 }
866
867 if (!processor) {
868 return false;
869 }
870
871 const OCIO::ConstCPUProcessorRcPtr device_processor = processor->getDefaultCPUProcessor();
872 if (!device_processor) {
873 return false;
874 }
875
876 to_scene_linear = transform_identity();
877 device_processor->applyRGB(&to_scene_linear.x.x);
878 device_processor->applyRGB(&to_scene_linear.y.x);
879 device_processor->applyRGB(&to_scene_linear.z.x);
880 to_scene_linear = transform_transposed_inverse(to_scene_linear);
881 return true;
882}
883#endif
884
886{
887 /* Default to ITU-BT.709 in case no appropriate transform found.
888 * Note XYZ here is defined as having a D65 white point. */
889 const Transform xyz_to_rec709 = make_transform(3.2404542f,
890 -1.5371385f,
891 -0.4985314f,
892 0.0f,
893 -0.9692660f,
894 1.8760108f,
895 0.0415560f,
896 0.0f,
897 0.0556434f,
898 -0.2040259f,
899 1.0572252f,
900 0.0f);
901
902 xyz_to_r = make_float3(xyz_to_rec709.x);
903 xyz_to_g = make_float3(xyz_to_rec709.y);
904 xyz_to_b = make_float3(xyz_to_rec709.z);
905 rgb_to_y = make_float3(0.2126729f, 0.7151522f, 0.0721750f);
906 white_xyz = make_float3(0.95047f, 1.0f, 1.08883f);
907
908 rec709_to_r = make_float3(1.0f, 0.0f, 0.0f);
909 rec709_to_g = make_float3(0.0f, 1.0f, 0.0f);
910 rec709_to_b = make_float3(0.0f, 0.0f, 1.0f);
911 is_rec709 = true;
912
913#ifdef WITH_OCIO
914 /* Get from OpenColorO config if it has the required roles. */
915 OCIO::ConstConfigRcPtr config = nullptr;
916 try {
917 config = OCIO::GetCurrentConfig();
918 }
919 catch (OCIO::Exception &exception) {
920 VLOG_WARNING << "OCIO config error: " << exception.what();
921 return;
922 }
923
924 if (!(config && config->hasRole("scene_linear"))) {
925 return;
926 }
927
929
930 if (config->hasRole("aces_interchange")) {
931 /* Standard OpenColorIO role, defined as ACES AP0 (ACES2065-1). */
932 Transform aces_to_rgb;
933 if (!to_scene_linear_transform(config, "aces_interchange", aces_to_rgb)) {
934 return;
935 }
936
937 /* This is the OpenColorIO builtin transform:
938 * UTILITY - ACES-AP0_to_CIE-XYZ-D65_BFD. */
939 const Transform ACES_AP0_to_xyz_D65 = make_transform(0.938280f,
940 -0.004451f,
941 0.016628f,
942 0.000000f,
943 0.337369f,
944 0.729522f,
945 -0.066890f,
946 0.000000f,
947 0.001174f,
948 -0.003711f,
949 1.091595f,
950 0.000000f);
951 const Transform xyz_to_aces = transform_inverse(ACES_AP0_to_xyz_D65);
952 xyz_to_rgb = aces_to_rgb * xyz_to_aces;
953 }
954 else if (config->hasRole("XYZ")) {
955 /* Custom role used before the standard existed. */
956 if (!to_scene_linear_transform(config, "XYZ", xyz_to_rgb)) {
957 return;
958 }
959 }
960 else {
961 /* No reference role found to determine XYZ. */
962 return;
963 }
964
968
969 const Transform rgb_to_xyz = transform_inverse(xyz_to_rgb);
970 rgb_to_y = make_float3(rgb_to_xyz.y);
971 white_xyz = transform_direction(&rgb_to_xyz, one_float3());
972
973 const Transform rec709_to_rgb = xyz_to_rgb * transform_inverse(xyz_to_rec709);
977 is_rec709 = transform_equal_threshold(xyz_to_rgb, xyz_to_rec709, 0.0001f);
978#endif
979}
980
982 Scene *scene,
983 const float *table,
984 const size_t n)
985{
986 /* Since the BSDF tables are static arrays, we can use their address to identify them. */
987 if (!(bsdf_tables.count(table))) {
988 vector<float> entries(table, table + n);
989 bsdf_tables[table] = scene->lookup_tables->add_table(dscene, entries);
990 }
991 return bsdf_tables[table];
992}
993
unsigned int uint
float progress
Definition WM_types.hh:1019
volatile int lock
unsigned long long int uint64_t
Shader * get_shader(const Scene *scene)
ClosureType get_closure_type() override
device_vector< KernelShader > shaders
Definition devicescene.h:78
device_vector< int4 > svm_nodes
Definition devicescene.h:77
KernelData data
Definition devicescene.h:89
bool from_auto_conversion
unique_ptr_vector< ShaderNode > nodes
ShaderOutput * link
const SocketType & socket_type
string get_cryptomatte_materials(Scene *scene)
float3 rec709_to_scene_linear(const float3 c)
static unique_ptr< ShaderManager > create(const int shadingsystem)
void device_update_common(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress)
size_t ensure_bsdf_table_impl(DeviceScene *dscene, Scene *scene, const float *table, const size_t n)
void device_update_pre(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress)
AttributeIDMap unique_attribute_id
float linear_rgb_to_gray(const float3 c)
virtual uint64_t get_attribute_id(ustring name)
void init_xyz_transforms()
virtual void device_update_specific(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress)=0
thread_spin_lock attribute_lock_
virtual ~ShaderManager()
int get_shader_id(Shader *shader, bool smooth=false)
unordered_map< const float *, size_t > bsdf_tables
void device_update_post(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress)
bool need_update() const
void tag_update(Scene *scene, const uint32_t flag)
void device_free_common(Device *device, DeviceScene *dscene, Scene *scene)
static thread_mutex lookup_table_mutex
uint get_kernel_features(Scene *scene)
size_t ensure_bsdf_table(DeviceScene *dscene, Scene *scene, const float(&table)[n])
static void add_default(Scene *scene)
uint32_t update_flags
virtual bool use_osl()
uint get_graph_kernel_features(ShaderGraph *graph)
ShaderInput * input(const char *name)
virtual bool has_surface_transparent()
virtual bool has_surface_emission()
ShaderNodeSpecialType special_type
virtual int get_feature()
unique_ptr_vector< ShaderInput > inputs
ShaderOutput * output(const char *name)
virtual bool has_surface_bssrdf()
virtual void attributes(Shader *shader, AttributeRequestSet *attributes)
bool has_surface_spatial_varying
bool has_bump_from_surface
bool has_surface_bssrdf
void estimate_emission()
bool need_update_attribute
bool has_volume_attribute_dependency
bool need_update_geometry() const
void set_graph(unique_ptr< ShaderGraph > &&graph)
bool has_volume
bool emission_is_constant
float3 emission_estimate
bool has_surface
bool has_bssrdf_bump
float prev_volume_step_rate
bool has_bump_from_displacement
bool need_update_displacement
EmissionSampling emission_sampling
bool has_surface_raytrace
bool need_update_uvs
bool has_displacement
AttributeRequestSet attributes
bool has_surface_transparent
void tag_update(Scene *scene)
NODE_DECLARE unique_ptr< ShaderGraph > graph
bool has_volume_connected
void tag_used(Scene *scene)
bool has_volume_spatial_varying
T * alloc(const size_t width, const size_t height=0, const size_t depth=0)
size_t size() const
reduce_max(value.rgb)") DEFINE_VALUE("REDUCE(lhs
dot(value.rgb, luminance_coefficients)") DEFINE_VALUE("REDUCE(lhs
ccl_device_inline float2 to_local(const T p, const T X, const T Y)
#define KERNEL_FEATURE_VOLUME
#define CLOSURE_IS_VOLUME(type)
#define KERNEL_FEATURE_NODE_BUMP_STATE
#define KERNEL_FEATURE_TRANSPARENT
#define KERNEL_FEATURE_OSL_SHADING
#define KERNEL_FEATURE_SUBSURFACE
#define KERNEL_FEATURE_NODE_BSDF
#define KERNEL_FEATURE_NODE_VOLUME
#define KERNEL_FEATURE_NODE_EMISSION
#define KERNEL_FEATURE_NODE_BUMP
#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 input
#define assert(assertion)
#define in
#define output
@ SD_VOLUME_MIS
@ SD_MIS_BACK
@ SD_HAS_TRANSPARENT_SHADOW
@ SD_VOLUME_EQUIANGULAR
@ SD_HAS_CONSTANT_EMISSION
@ SD_HAS_DISPLACEMENT
@ SD_HAS_EMISSION
@ SD_MIS_FRONT
@ SD_HAS_BSSRDF_BUMP
@ SD_HAS_ONLY_VOLUME
@ SD_HAS_RAYTRACE
@ SD_VOLUME_CUBIC
@ SD_HAS_VOLUME
@ SD_NEED_VOLUME_ATTRIBUTES
@ SD_USE_BUMP_MAP_CORRECTION
@ SD_HAS_BUMP_FROM_DISPLACEMENT
@ SD_HETEROGENEOUS_VOLUME
@ SD_HAS_BUMP_FROM_SURFACE
AttributeStandard
@ ATTR_STD_NUM
@ ATTR_STD_POSITION_UNDISPLACED
@ EMISSION_SAMPLING_NONE
@ EMISSION_SAMPLING_AUTO
@ EMISSION_SAMPLING_BACK
@ EMISSION_SAMPLING_FRONT_BACK
@ EMISSION_SAMPLING_FRONT
@ SHADER_AREA_LIGHT
@ SHADER_SMOOTH_NORMAL
@ SHADER_CAST_SHADOW
ccl_device float3 rec709_to_rgb(KernelGlobals kg, const float3 rec709)
#define VLOG_WARNING
Definition log.h:69
ccl_device_inline bool is_zero(const float2 a)
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
uint32_t util_murmur_hash3(const void *key, const int len, const uint32_t seed)
float util_hash_to_float(const uint32_t hash)
color xyz_to_rgb(float x, float y, float z)
Definition node_color.h:73
#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_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
static float3 output_estimate_emission(ShaderOutput *output, bool &is_constant)
@ VOLUME_INTERPOLATION_LINEAR
@ VOLUME_INTERPOLATION_CUBIC
@ DISPLACE_BUMP
@ DISPLACE_TRUE
@ DISPLACE_BOTH
@ SHADINGSYSTEM_OSL
@ VOLUME_SAMPLING_DISTANCE
@ VOLUME_SAMPLING_EQUIANGULAR
@ VOLUME_SAMPLING_MULTIPLE_IMPORTANCE
@ SHADER_SPECIAL_TYPE_OUTPUT_AOV
@ SHADER_SPECIAL_TYPE_CLOSURE
CCL_NAMESPACE_BEGIN string string_printf(const char *format,...)
Definition string.cpp:23
float constant_emission[3]
int ggx_gen_schlick_ior_s
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)
float get_float(const SocketType &input) const
const NodeType * type
Definition graph/node.h:178
float3 get_float3(const SocketType &input) const
ustring name
Definition graph/node.h:177
int reference_count() const
Definition graph/node.h:183
void reference()
Definition graph/node.h:188
void tag_modified()
bool is_modified() const
Node(const NodeType *type, ustring name=ustring())
unique_ptr< ObjectManager > object_manager
Definition scene.h:150
unique_ptr< LightManager > light_manager
Definition scene.h:146
Shader * default_volume
Definition scene.h:157
Shader * default_surface
Definition scene.h:156
Shader * default_empty
Definition scene.h:160
Shader * default_background
Definition scene.h:159
T * create_node(Args &&...)=delete
Background * background
Definition scene.h:129
unique_ptr_vector< Shader > shaders
Definition scene.h:137
unique_ptr< ShaderManager > shader_manager
Definition scene.h:148
unique_ptr< GeometryManager > geometry_manager
Definition scene.h:149
unique_ptr< ProceduralManager > procedural_manager
Definition scene.h:153
Shader * default_light
Definition scene.h:158
unique_ptr< LookupTables > lookup_tables
Definition scene.h:124
float4 y
Definition transform.h:23
float4 x
Definition transform.h:23
float4 z
Definition transform.h:23
float z
Definition sky_float3.h:27
float y
Definition sky_float3.h:27
float x
Definition sky_float3.h:27
i
Definition text_draw.cc:230
std::mutex thread_mutex
Definition thread.h:27
CCL_NAMESPACE_BEGIN Transform transform_transposed_inverse(const Transform &tfm)
Definition transform.cpp:15
ccl_device_inline Transform transform_identity()
Definition transform.h:289
ccl_device_inline bool transform_equal_threshold(const Transform &A, const Transform &B, const float threshold)
Definition transform.h:306
ccl_device_inline Transform transform_inverse(const Transform tfm)
Definition transform.h:492
ccl_device_inline Transform make_transform(const float a, const float b, const float c, const float d, const float e, const float f, const float g, const float h, const float i, const float j, const float k, const float l)
Definition transform.h:126
ccl_device_inline float3 transform_direction(const ccl_private Transform *t, const float3 a)
Definition transform.h:87
uint8_t flag
Definition wm_window.cc:139