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;
100 has_bump = false;
101 has_bssrdf_bump = false;
105 has_volume_connected = false;
107
111
112 displacement_method = DISPLACE_BUMP;
113
114 id = -1;
115
116 need_update_uvs = true;
119}
120
122{
123 /* Only supports a few nodes for now, not arbitrary shader graphs. */
124 ShaderNode *node = (output) ? output->parent : nullptr;
125
126 if (node == nullptr) {
127 return zero_float3();
128 }
129 if (node->type == EmissionNode::get_node_type() ||
130 node->type == BackgroundNode::get_node_type() ||
131 node->type == PrincipledBsdfNode::get_node_type())
132 {
133 const bool is_principled = (node->type == PrincipledBsdfNode::get_node_type());
134 /* Emission and Background node. */
135 ShaderInput *color_in = node->input(is_principled ? "Emission Color" : "Color");
136 ShaderInput *strength_in = node->input(is_principled ? "Emission Strength" : "Strength");
137
138 if (is_principled) {
139 /* Too many parameters (coat, sheen, alpha) influence Emission for the Principled BSDF. */
140 is_constant = false;
141 }
142
143 float3 estimate = one_float3();
144
145 if (color_in->link) {
146 is_constant = false;
147 }
148 else {
149 estimate *= node->get_float3(color_in->socket_type);
150 }
151
152 if (strength_in->link) {
153 is_constant = false;
154 estimate *= output_estimate_emission(strength_in->link, is_constant);
155 }
156 else {
157 estimate *= node->get_float(strength_in->socket_type);
158 }
159
160 return estimate;
161 }
162 if (node->type == LightFalloffNode::get_node_type() ||
163 node->type == IESLightNode::get_node_type())
164 {
165 /* Get strength from Light Falloff and IES texture node. */
166 ShaderInput *strength_in = node->input("Strength");
167 is_constant = false;
168
169 return (strength_in->link) ? output_estimate_emission(strength_in->link, is_constant) :
170 make_float3(node->get_float(strength_in->socket_type));
171 }
172 if (node->type == AddClosureNode::get_node_type()) {
173 /* Add Closure. */
174 ShaderInput *closure1_in = node->input("Closure1");
175 ShaderInput *closure2_in = node->input("Closure2");
176
177 const float3 estimate1 = (closure1_in->link) ?
178 output_estimate_emission(closure1_in->link, is_constant) :
179 zero_float3();
180 const float3 estimate2 = (closure2_in->link) ?
181 output_estimate_emission(closure2_in->link, is_constant) :
182 zero_float3();
183
184 return estimate1 + estimate2;
185 }
186 if (node->type == MixClosureNode::get_node_type()) {
187 /* Mix Closure. */
188 ShaderInput *fac_in = node->input("Fac");
189 ShaderInput *closure1_in = node->input("Closure1");
190 ShaderInput *closure2_in = node->input("Closure2");
191
192 const float3 estimate1 = (closure1_in->link) ?
193 output_estimate_emission(closure1_in->link, is_constant) :
194 zero_float3();
195 const float3 estimate2 = (closure2_in->link) ?
196 output_estimate_emission(closure2_in->link, is_constant) :
197 zero_float3();
198
199 if (fac_in->link) {
200 is_constant = false;
201 return estimate1 + estimate2;
202 }
203
204 const float fac = node->get_float(fac_in->socket_type);
205 return (1.0f - fac) * estimate1 + fac * estimate2;
206 }
207
208 /* Other nodes, potentially OSL nodes with arbitrary code for which all we can
209 * determine is if it has emission or not. */
210 const bool has_emission = node->has_surface_emission();
211 float3 estimate;
212
213 if (output->type() == SocketType::CLOSURE) {
214 if (has_emission) {
215 estimate = one_float3();
216 is_constant = false;
217 }
218 else {
219 estimate = zero_float3();
220 }
221
222 for (const ShaderInput *in : node->inputs) {
223 if (in->type() == SocketType::CLOSURE && in->link) {
224 estimate += output_estimate_emission(in->link, is_constant);
225 }
226 }
227 }
228 else {
229 estimate = one_float3();
230 is_constant = false;
231 }
232
233 return estimate;
234}
235
237{
238 /* If the shader has AOVs, they need to be evaluated, so we can't skip the shader. */
240
241 for (ShaderNode *node : graph->nodes) {
243 emission_is_constant = false;
244 }
245 }
246
247 ShaderInput *surf = graph->output()->input("Surface");
249
252 }
253 else if (emission_sampling_method == EMISSION_SAMPLING_AUTO) {
254 /* Automatically disable MIS when emission is low, to avoid weakly emitting
255 * using a lot of memory in the light tree and potentially wasting samples
256 * where indirect light samples are sufficient.
257 * Possible optimization: estimate front and back emission separately. */
258
259 /* Lower importance of emission nodes from automatic value/color to shader conversion, as these
260 * are likely used for previewing and can be slow to build a light tree for on dense meshes. */
261 float scale = 1.0f;
262 const ShaderOutput *output = surf->link;
263 if (output && output->parent->type == EmissionNode::get_node_type()) {
264 const EmissionNode *emission_node = static_cast<const EmissionNode *>(output->parent);
265 if (emission_node->from_auto_conversion) {
266 scale = 0.1f;
267 }
268 }
269
273 }
274 else {
275 emission_sampling = emission_sampling_method;
276 }
277}
278
280{
281 /* do this here already so that we can detect if mesh or object attributes
282 * are needed, since the node attribute callbacks check if their sockets
283 * are connected but proxy nodes should not count */
284 if (graph_) {
285 graph_->remove_proxy_nodes();
286
287 if (displacement_method != DISPLACE_BUMP) {
288 graph_->compute_displacement_hash();
289 }
290 }
291
292 /* update geometry if displacement changed */
293 if (displacement_method != DISPLACE_BUMP) {
294 const char *old_hash = (graph) ? graph->displacement_hash.c_str() : "";
295 const char *new_hash = (graph_) ? graph_->displacement_hash.c_str() : "";
296
297 if (strcmp(old_hash, new_hash) != 0) {
299 }
300 }
301
302 /* assign graph */
303 graph = std::move(graph_);
304
305 /* Store info here before graph optimization to make sure that
306 * nodes that get optimized away still count. */
307 has_volume_connected = (graph->output()->input("Volume")->link != nullptr);
308}
309
311{
312 /* update tag */
313 tag_modified();
314
315 scene->shader_manager->tag_update(scene, ShaderManager::SHADER_MODIFIED);
316
317 /* if the shader previously was emissive, update light distribution,
318 * if the new shader is emissive, a light manager update tag will be
319 * done in the shader manager device update. */
321 scene->light_manager->tag_update(scene, LightManager::SHADER_MODIFIED);
322 }
323
324 /* Special handle of background MIS light for now: for some reason it
325 * has use_mis set to false. We are quite close to release now, so
326 * better to be safe.
327 */
328 if (this == scene->background->get_shader(scene)) {
329 scene->light_manager->need_update_background = true;
330 if (scene->light_manager->has_background_light(scene)) {
331 scene->light_manager->tag_update(scene, LightManager::SHADER_MODIFIED);
332 }
333 }
334
335 /* quick detection of which kind of shaders we have to avoid loading
336 * e.g. surface attributes when there is only a volume shader. this could
337 * be more fine grained but it's better than nothing */
338 OutputNode *output = graph->output();
339 const bool prev_has_volume = has_volume;
340 has_surface = has_surface || output->input("Surface")->link;
341 has_volume = has_volume || output->input("Volume")->link;
342 has_displacement = has_displacement || output->input("Displacement")->link;
343
344 if (!has_surface && !has_volume) {
345 /* If we need to output surface AOVs, add a Transparent BSDF so that the
346 * surface shader runs. */
347 for (ShaderNode *node : graph->nodes) {
349 for (const ShaderInput *in : node->inputs) {
350 if (in->link) {
351 TransparentBsdfNode *transparent = graph->create_node<TransparentBsdfNode>();
352 graph->connect(transparent->output("BSDF"), output->input("Surface"));
353 has_surface = true;
354 break;
355 }
356 }
357 if (has_surface) {
358 break;
359 }
360 }
361 }
362 }
363
364 /* get requested attributes. this could be optimized by pruning unused
365 * nodes here already, but that's the job of the shader manager currently,
366 * and may not be so great for interactive rendering where you temporarily
367 * disconnect a node */
368
369 const AttributeRequestSet prev_attributes = attributes;
370
371 attributes.clear();
372 for (ShaderNode *node : graph->nodes) {
373 node->attributes(this, &attributes);
374 }
375
376 if (has_displacement) {
377 if (displacement_method == DISPLACE_BOTH) {
379 }
380 if (displacement_method_is_modified()) {
383 scene->object_manager->need_flags_update = true;
384 }
385 }
386
387 /* compare if the attributes changed, mesh manager will check
388 * need_update_attribute, update the relevant meshes and clear it. */
389 if (attributes.modified(prev_attributes)) {
392 scene->procedural_manager->tag_update();
393 }
394
395 if (has_volume != prev_has_volume || volume_step_rate != prev_volume_step_rate) {
396 scene->geometry_manager->need_flags_update = true;
397 scene->object_manager->need_flags_update = true;
398 prev_volume_step_rate = volume_step_rate;
399 }
400}
401
403{
404 /* if an unused shader suddenly gets used somewhere, it needs to be
405 * recompiled because it was skipped for compilation before */
406 if (!reference_count()) {
407 tag_modified();
408 /* We do not reference here as the shader will be referenced when added to a socket. */
409 scene->shader_manager->tag_update(scene, ShaderManager::SHADER_MODIFIED);
410 }
411}
412
417
418/* Shader Manager */
419
426
428
430{
432
433 (void)shadingsystem; /* Ignored when built without OSL. */
434
435#ifdef WITH_OSL
436 if (shadingsystem == SHADINGSYSTEM_OSL) {
437 manager = make_unique<OSLShaderManager>();
438 }
439 else
440#endif
441 {
442 manager = make_unique<SVMShaderManager>();
443 }
444
445 return manager;
446}
447
449{
451
452 /* get a unique id for each name, for SVM attribute lookup */
453 const AttributeIDMap::iterator it = unique_attribute_id.find(name);
454
455 if (it != unique_attribute_id.end()) {
456 return it->second;
457 }
458
459 const uint64_t id = ATTR_STD_NUM + unique_attribute_id.size();
460 unique_attribute_id[name] = id;
461 return id;
462}
463
468
469int ShaderManager::get_shader_id(Shader *shader, bool smooth)
470{
471 /* get a shader id to pass to the kernel */
472 int id = shader->id;
473
474 /* smooth flag */
475 if (smooth) {
477 }
478
479 /* default flags */
481
482 return id;
483}
484
486 DeviceScene * /*dscene*/,
487 Scene *scene,
488 Progress & /*progress*/)
489{
490 /* This optimizes the shader graphs, but does not update anything on the device yet.
491 * After this we'll know the kernel features actually used, to load the kernels. */
492 if (!need_update()) {
493 return;
494 }
495
496 uint id = 0;
497 for (Shader *shader : scene->shaders) {
498 shader->id = id++;
499 }
500
501 /* Those shaders should always be compiled as they are used as a fallback if a shader cannot be
502 * found, e.g. bad shader index for the triangle shaders on a Mesh. */
503 assert(scene->default_surface->reference_count() != 0);
504 assert(scene->default_light->reference_count() != 0);
506 assert(scene->default_empty->reference_count() != 0);
507
508 for (Shader *shader : scene->shaders) {
509 if (shader->is_modified()) {
510 ShaderNode *output = shader->graph->output();
511
512 shader->has_bump = (shader->get_displacement_method() != DISPLACE_TRUE) &&
513 output->input("Surface")->link && output->input("Displacement")->link;
514 shader->has_bssrdf_bump = shader->has_bump;
515
516 shader->graph->finalize(
517 scene, shader->has_bump, shader->get_displacement_method() == DISPLACE_BOTH);
518 }
519 }
520}
521
523 DeviceScene *dscene,
524 Scene *scene,
526{
527 device_update_specific(device, dscene, scene, progress);
528
529 /* This runs after kernels have been loaded, so can copy to device. */
532}
533
535 DeviceScene *dscene,
536 Scene *scene,
537 Progress & /*progress*/)
538{
539 dscene->shaders.free();
540
541 if (scene->shaders.empty()) {
542 return;
543 }
544
545 KernelShader *kshader = dscene->shaders.alloc(scene->shaders.size());
546 bool has_volumes = false;
547 bool has_transparent_shadow = false;
548
549 for (Shader *shader : scene->shaders) {
550 uint flag = 0;
551
554 }
555 else if (shader->emission_sampling == EMISSION_SAMPLING_BACK) {
556 flag |= SD_MIS_BACK;
557 }
560 }
561
562 if (!is_zero(shader->emission_estimate)) {
564 }
565 if (shader->has_surface_transparent && shader->get_use_transparent_shadow()) {
567 }
568 if (shader->has_surface_raytrace) {
570 }
571 if (shader->has_volume) {
573 has_volumes = true;
574
575 /* todo: this could check more fine grained, to skip useless volumes
576 * enclosed inside an opaque bsdf.
577 */
579 }
580 /* in this case we can assume transparent surface */
581 if (shader->has_volume_connected && !shader->has_surface) {
583 }
584 if (shader->has_volume) {
585 if (shader->get_heterogeneous_volume() && shader->has_volume_spatial_varying) {
587 }
588 }
591 }
592 if (shader->has_bssrdf_bump) {
594 }
595 if (shader->get_volume_sampling_method() == VOLUME_SAMPLING_EQUIANGULAR) {
597 }
598 if (shader->get_volume_sampling_method() == VOLUME_SAMPLING_MULTIPLE_IMPORTANCE) {
600 }
601 if (shader->get_volume_interpolation_method() == VOLUME_INTERPOLATION_CUBIC) {
603 }
604 if (shader->has_bump) {
605 flag |= SD_HAS_BUMP;
606 }
607 if (shader->get_displacement_method() != DISPLACE_BUMP) {
609 }
610 if (shader->get_use_bump_map_correction()) {
612 }
613
614 /* constant emission check */
615 if (shader->emission_is_constant) {
617 }
618
619 const uint32_t cryptomatte_id = util_murmur_hash3(
620 shader->name.c_str(), shader->name.length(), 0);
621
622 /* regular shader */
623 kshader->flags = flag;
624 kshader->pass_id = shader->get_pass_id();
625 kshader->constant_emission[0] = shader->emission_estimate.x;
626 kshader->constant_emission[1] = shader->emission_estimate.y;
627 kshader->constant_emission[2] = shader->emission_estimate.z;
628 kshader->cryptomatte_id = util_hash_to_float(cryptomatte_id);
629 kshader++;
630
631 has_transparent_shadow |= (flag & SD_HAS_TRANSPARENT_SHADOW) != 0;
632 }
633
634 /* lookup tables */
635 KernelTables *ktables = &dscene->data.tables;
636 ktables->ggx_E = ensure_bsdf_table(dscene, scene, table_ggx_E);
637 ktables->ggx_Eavg = ensure_bsdf_table(dscene, scene, table_ggx_Eavg);
638 ktables->ggx_glass_E = ensure_bsdf_table(dscene, scene, table_ggx_glass_E);
639 ktables->ggx_glass_Eavg = ensure_bsdf_table(dscene, scene, table_ggx_glass_Eavg);
640 ktables->ggx_glass_inv_E = ensure_bsdf_table(dscene, scene, table_ggx_glass_inv_E);
641 ktables->ggx_glass_inv_Eavg = ensure_bsdf_table(dscene, scene, table_ggx_glass_inv_Eavg);
642 ktables->sheen_ltc = ensure_bsdf_table(dscene, scene, table_sheen_ltc);
643 ktables->ggx_gen_schlick_ior_s = ensure_bsdf_table(dscene, scene, table_ggx_gen_schlick_ior_s);
644 ktables->ggx_gen_schlick_s = ensure_bsdf_table(dscene, scene, table_ggx_gen_schlick_s);
645
646 /* integrator */
647 KernelIntegrator *kintegrator = &dscene->data.integrator;
648 kintegrator->use_volumes = has_volumes;
649 /* TODO(sergey): De-duplicate with flags set in integrator.cpp. */
650 kintegrator->transparent_shadows = has_transparent_shadow;
651
652 /* film */
653 KernelFilm *kfilm = &dscene->data.film;
654 /* color space, needs to be here because e.g. displacement shaders could depend on it */
655 kfilm->xyz_to_r = make_float4(xyz_to_r);
656 kfilm->xyz_to_g = make_float4(xyz_to_g);
657 kfilm->xyz_to_b = make_float4(xyz_to_b);
658 kfilm->rgb_to_y = make_float4(rgb_to_y);
659 kfilm->white_xyz = make_float4(white_xyz);
660 kfilm->rec709_to_r = make_float4(rec709_to_r);
661 kfilm->rec709_to_g = make_float4(rec709_to_g);
662 kfilm->rec709_to_b = make_float4(rec709_to_b);
663 kfilm->is_rec709 = is_rec709;
664}
665
667{
668 for (auto &entry : bsdf_tables) {
669 scene->lookup_tables->remove_table(&entry.second);
670 }
671 bsdf_tables.clear();
672
673 dscene->shaders.free();
674}
675
677{
678 /* default surface */
679 {
680 unique_ptr<ShaderGraph> graph = make_unique<ShaderGraph>();
681
682 DiffuseBsdfNode *diffuse = graph->create_node<DiffuseBsdfNode>();
683 diffuse->set_color(make_float3(0.8f, 0.8f, 0.8f));
684
685 graph->connect(diffuse->output("BSDF"), graph->output()->input("Surface"));
686
687 Shader *shader = scene->create_node<Shader>();
688 shader->name = "default_surface";
689 shader->set_graph(std::move(graph));
690 shader->reference();
691 scene->default_surface = shader;
692 shader->tag_update(scene);
693 }
694
695 /* default volume */
696 {
697 unique_ptr<ShaderGraph> graph = make_unique<ShaderGraph>();
698
699 PrincipledVolumeNode *principled = graph->create_node<PrincipledVolumeNode>();
700
701 graph->connect(principled->output("Volume"), graph->output()->input("Volume"));
702
703 Shader *shader = scene->create_node<Shader>();
704 shader->name = "default_volume";
705 shader->set_graph(std::move(graph));
706 scene->default_volume = shader;
707 shader->tag_update(scene);
708 /* No default reference for the volume to avoid compiling volume kernels if there are no
709 * actual volumes in the scene */
710 }
711
712 /* default light */
713 {
714 unique_ptr<ShaderGraph> graph = make_unique<ShaderGraph>();
715
716 EmissionNode *emission = graph->create_node<EmissionNode>();
717 emission->set_color(make_float3(0.8f, 0.8f, 0.8f));
718 emission->set_strength(0.0f);
719
720 graph->connect(emission->output("Emission"), graph->output()->input("Surface"));
721
722 Shader *shader = scene->create_node<Shader>();
723 shader->name = "default_light";
724 shader->set_graph(std::move(graph));
725 shader->reference();
726 scene->default_light = shader;
727 shader->tag_update(scene);
728 }
729
730 /* default background */
731 {
732 unique_ptr<ShaderGraph> graph = make_unique<ShaderGraph>();
733
734 Shader *shader = scene->create_node<Shader>();
735 shader->name = "default_background";
736 shader->set_graph(std::move(graph));
737 shader->reference();
738 scene->default_background = shader;
739 shader->tag_update(scene);
740 }
741
742 /* default empty */
743 {
744 unique_ptr<ShaderGraph> graph = make_unique<ShaderGraph>();
745
746 Shader *shader = scene->create_node<Shader>();
747 shader->name = "default_empty";
748 shader->set_graph(std::move(graph));
749 shader->reference();
750 scene->default_empty = shader;
751 shader->tag_update(scene);
752 }
753}
754
756{
757 uint kernel_features = 0;
758
759 for (ShaderNode *node : graph->nodes) {
760 kernel_features |= node->get_feature();
762 BsdfBaseNode *bsdf_node = static_cast<BsdfBaseNode *>(node);
763 if (CLOSURE_IS_VOLUME(bsdf_node->get_closure_type())) {
764 kernel_features |= KERNEL_FEATURE_NODE_VOLUME;
765 }
766 }
767 if (node->has_surface_bssrdf()) {
768 kernel_features |= KERNEL_FEATURE_SUBSURFACE;
769 }
770 if (node->has_surface_transparent()) {
771 kernel_features |= KERNEL_FEATURE_TRANSPARENT;
772 }
773 }
774
775 return kernel_features;
776}
777
779{
781 for (int i = 0; i < scene->shaders.size(); i++) {
782 Shader *shader = scene->shaders[i];
783 if (!shader->reference_count()) {
784 continue;
785 }
786
787 /* Gather requested features from all the nodes from the graph nodes. */
788 kernel_features |= get_graph_kernel_features(shader->graph.get());
789 ShaderNode *output_node = shader->graph->output();
790 if (output_node->input("Displacement")->link != nullptr) {
791 kernel_features |= KERNEL_FEATURE_NODE_BUMP;
792 if (shader->get_displacement_method() == DISPLACE_BOTH) {
793 kernel_features |= KERNEL_FEATURE_NODE_BUMP_STATE;
794 }
795 }
796 /* On top of volume nodes, also check if we need volume sampling because
797 * e.g. an Emission node would slip through the KERNEL_FEATURE_NODE_VOLUME check */
798 if (shader->has_volume_connected) {
799 kernel_features |= KERNEL_FEATURE_VOLUME;
800 }
801 }
802
803 if (use_osl()) {
804 kernel_features |= KERNEL_FEATURE_OSL_SHADING;
805 }
806
807 return kernel_features;
808}
809
811{
812 return dot(c, rgb_to_y);
813}
814
819
821{
822 string manifest = "{";
823 unordered_set<ustring> materials;
824 for (Shader *shader : scene->shaders) {
825 if (materials.count(shader->name)) {
826 continue;
827 }
828 materials.insert(shader->name);
829 const uint32_t cryptomatte_id = util_murmur_hash3(
830 shader->name.c_str(), shader->name.length(), 0);
831 manifest += string_printf("\"%s\":\"%08x\",", shader->name.c_str(), cryptomatte_id);
832 }
833 manifest[manifest.size() - 1] = '}';
834 return manifest;
835}
836
837void ShaderManager::tag_update(Scene * /*scene*/, uint32_t /*flag*/)
838{
839 /* update everything for now */
841}
842
844{
845 return update_flags != UPDATE_NONE;
846}
847
848#ifdef WITH_OCIO
849static bool to_scene_linear_transform(OCIO::ConstConfigRcPtr &config,
850 const char *colorspace,
851 Transform &to_scene_linear)
852{
853 OCIO::ConstProcessorRcPtr processor;
854 try {
855 processor = config->getProcessor("scene_linear", colorspace);
856 }
857 catch (OCIO::Exception &) {
858 return false;
859 }
860
861 if (!processor) {
862 return false;
863 }
864
865 const OCIO::ConstCPUProcessorRcPtr device_processor = processor->getDefaultCPUProcessor();
866 if (!device_processor) {
867 return false;
868 }
869
870 to_scene_linear = transform_identity();
871 device_processor->applyRGB(&to_scene_linear.x.x);
872 device_processor->applyRGB(&to_scene_linear.y.x);
873 device_processor->applyRGB(&to_scene_linear.z.x);
874 to_scene_linear = transform_transposed_inverse(to_scene_linear);
875 return true;
876}
877#endif
878
880{
881 /* Default to ITU-BT.709 in case no appropriate transform found.
882 * Note XYZ here is defined as having a D65 white point. */
883 const Transform xyz_to_rec709 = make_transform(3.2404542f,
884 -1.5371385f,
885 -0.4985314f,
886 0.0f,
887 -0.9692660f,
888 1.8760108f,
889 0.0415560f,
890 0.0f,
891 0.0556434f,
892 -0.2040259f,
893 1.0572252f,
894 0.0f);
895
896 xyz_to_r = make_float3(xyz_to_rec709.x);
897 xyz_to_g = make_float3(xyz_to_rec709.y);
898 xyz_to_b = make_float3(xyz_to_rec709.z);
899 rgb_to_y = make_float3(0.2126729f, 0.7151522f, 0.0721750f);
900 white_xyz = make_float3(0.95047f, 1.0f, 1.08883f);
901
902 rec709_to_r = make_float3(1.0f, 0.0f, 0.0f);
903 rec709_to_g = make_float3(0.0f, 1.0f, 0.0f);
904 rec709_to_b = make_float3(0.0f, 0.0f, 1.0f);
905 is_rec709 = true;
906
907#ifdef WITH_OCIO
908 /* Get from OpenColorO config if it has the required roles. */
909 OCIO::ConstConfigRcPtr config = nullptr;
910 try {
911 config = OCIO::GetCurrentConfig();
912 }
913 catch (OCIO::Exception &exception) {
914 VLOG_WARNING << "OCIO config error: " << exception.what();
915 return;
916 }
917
918 if (!(config && config->hasRole("scene_linear"))) {
919 return;
920 }
921
923
924 if (config->hasRole("aces_interchange")) {
925 /* Standard OpenColorIO role, defined as ACES AP0 (ACES2065-1). */
926 Transform aces_to_rgb;
927 if (!to_scene_linear_transform(config, "aces_interchange", aces_to_rgb)) {
928 return;
929 }
930
931 /* This is the OpenColorIO builtin transform:
932 * UTILITY - ACES-AP0_to_CIE-XYZ-D65_BFD. */
933 const Transform ACES_AP0_to_xyz_D65 = make_transform(0.938280f,
934 -0.004451f,
935 0.016628f,
936 0.000000f,
937 0.337369f,
938 0.729522f,
939 -0.066890f,
940 0.000000f,
941 0.001174f,
942 -0.003711f,
943 1.091595f,
944 0.000000f);
945 const Transform xyz_to_aces = transform_inverse(ACES_AP0_to_xyz_D65);
946 xyz_to_rgb = aces_to_rgb * xyz_to_aces;
947 }
948 else if (config->hasRole("XYZ")) {
949 /* Custom role used before the standard existed. */
950 if (!to_scene_linear_transform(config, "XYZ", xyz_to_rgb)) {
951 return;
952 }
953 }
954 else {
955 /* No reference role found to determine XYZ. */
956 return;
957 }
958
962
963 const Transform rgb_to_xyz = transform_inverse(xyz_to_rgb);
964 rgb_to_y = make_float3(rgb_to_xyz.y);
965 white_xyz = transform_direction(&rgb_to_xyz, one_float3());
966
967 const Transform rec709_to_rgb = xyz_to_rgb * transform_inverse(xyz_to_rec709);
971 is_rec709 = transform_equal_threshold(xyz_to_rgb, xyz_to_rec709, 0.0001f);
972#endif
973}
974
976 Scene *scene,
977 const float *table,
978 const size_t n)
979{
980 /* Since the BSDF tables are static arrays, we can use their address to identify them. */
981 if (!(bsdf_tables.count(table))) {
982 vector<float> entries(table, table + n);
983 bsdf_tables[table] = scene->lookup_tables->add_table(dscene, entries);
984 }
985 return bsdf_tables[table];
986}
987
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_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 need_update_displacement
EmissionSampling emission_sampling
bool has_surface_raytrace
bool need_update_uvs
bool has_displacement
bool has_bump
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_BUMP
@ 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_HETEROGENEOUS_VOLUME
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