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