Blender  V3.3
scene/shader.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright 2011-2022 Blender Foundation */
3 
4 #include "device/device.h"
5 
6 #include "scene/background.h"
7 #include "scene/camera.h"
8 #include "scene/colorspace.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/foreach.h"
23 #include "util/murmurhash.h"
24 #include "util/task.h"
25 #include "util/transform.h"
26 
27 #ifdef WITH_OCIO
28 # include <OpenColorIO/OpenColorIO.h>
29 namespace OCIO = OCIO_NAMESPACE;
30 #endif
31 
33 
37 
38 /* Beckmann sampling precomputed table, see bsdf_microfacet.h */
39 
40 /* 2D slope distribution (alpha = 1.0) */
41 static float beckmann_table_P22(const float slope_x, const float slope_y)
42 {
43  return expf(-(slope_x * slope_x + slope_y * slope_y));
44 }
45 
46 /* maximal slope amplitude (range that contains 99.99% of the distribution) */
48 {
49  return 6.0;
50 }
51 
52 /* MSVC 2015 needs this ugly hack to prevent a codegen bug on x86
53  * see T50176 for details
54  */
55 #if defined(_MSC_VER) && (_MSC_VER == 1900)
56 # define MSVC_VOLATILE volatile
57 #else
58 # define MSVC_VOLATILE
59 #endif
60 
61 /* Paper used: Importance Sampling Microfacet-Based BSDFs with the
62  * Distribution of Visible Normals. Supplemental Material 2/2.
63  *
64  * http://hal.inria.fr/docs/01/00/66/20/ANNEX/supplemental2.pdf
65  */
66 static void beckmann_table_rows(float *table, int row_from, int row_to)
67 {
68  /* allocate temporary data */
69  const int DATA_TMP_SIZE = 512;
70  vector<double> slope_x(DATA_TMP_SIZE);
71  vector<double> CDF_P22_omega_i(DATA_TMP_SIZE);
72 
73  /* loop over incident directions */
74  for (int index_theta = row_from; index_theta < row_to; index_theta++) {
75  /* incident vector */
76  const float cos_theta = index_theta / (BECKMANN_TABLE_SIZE - 1.0f);
77  const float sin_theta = safe_sqrtf(1.0f - cos_theta * cos_theta);
78 
79  /* for a given incident vector
80  * integrate P22_{omega_i}(x_slope, 1, 1), Eq. (10) */
81  slope_x[0] = (double)-beckmann_table_slope_max();
82  CDF_P22_omega_i[0] = 0;
83 
84  for (MSVC_VOLATILE int index_slope_x = 1; index_slope_x < DATA_TMP_SIZE; ++index_slope_x) {
85  /* slope_x */
86  slope_x[index_slope_x] = (double)(-beckmann_table_slope_max() +
87  2.0f * beckmann_table_slope_max() * index_slope_x /
88  (DATA_TMP_SIZE - 1.0f));
89 
90  /* dot product with incident vector */
91  float dot_product = fmaxf(0.0f, -(float)slope_x[index_slope_x] * sin_theta + cos_theta);
92  /* marginalize P22_{omega_i}(x_slope, 1, 1), Eq. (10) */
93  float P22_omega_i = 0.0f;
94 
95  for (int j = 0; j < 100; ++j) {
96  float slope_y = -beckmann_table_slope_max() +
97  2.0f * beckmann_table_slope_max() * j * (1.0f / 99.0f);
98  P22_omega_i += dot_product * beckmann_table_P22((float)slope_x[index_slope_x], slope_y);
99  }
100 
101  /* CDF of P22_{omega_i}(x_slope, 1, 1), Eq. (10) */
102  CDF_P22_omega_i[index_slope_x] = CDF_P22_omega_i[index_slope_x - 1] + (double)P22_omega_i;
103  }
104 
105  /* renormalize CDF_P22_omega_i */
106  for (int index_slope_x = 1; index_slope_x < DATA_TMP_SIZE; ++index_slope_x)
107  CDF_P22_omega_i[index_slope_x] /= CDF_P22_omega_i[DATA_TMP_SIZE - 1];
108 
109  /* loop over random number U1 */
110  int index_slope_x = 0;
111 
112  for (int index_U = 0; index_U < BECKMANN_TABLE_SIZE; ++index_U) {
113  const double U = 0.0000001 + 0.9999998 * index_U / (double)(BECKMANN_TABLE_SIZE - 1);
114 
115  /* inverse CDF_P22_omega_i, solve Eq.(11) */
116  while (CDF_P22_omega_i[index_slope_x] <= U)
117  ++index_slope_x;
118 
119  const double interp = (CDF_P22_omega_i[index_slope_x] - U) /
120  (CDF_P22_omega_i[index_slope_x] - CDF_P22_omega_i[index_slope_x - 1]);
121 
122  /* store value */
123  table[index_U + index_theta * BECKMANN_TABLE_SIZE] =
124  (float)(interp * slope_x[index_slope_x - 1] + (1.0 - interp) * slope_x[index_slope_x]);
125  }
126  }
127 }
128 
129 #undef MSVC_VOLATILE
130 
132 {
134 
135  /* multithreaded build */
136  TaskPool pool;
137 
138  for (int i = 0; i < BECKMANN_TABLE_SIZE; i += 8)
139  pool.push(function_bind(&beckmann_table_rows, &table[0], i, i + 8));
140 
141  pool.wait_work();
142 }
143 
144 /* Shader */
145 
147 {
148  NodeType *type = NodeType::add("shader", create);
149 
150  SOCKET_BOOLEAN(use_mis, "Use MIS", true);
151  SOCKET_BOOLEAN(use_transparent_shadow, "Use Transparent Shadow", true);
152  SOCKET_BOOLEAN(heterogeneous_volume, "Heterogeneous Volume", true);
153 
154  static NodeEnum volume_sampling_method_enum;
155  volume_sampling_method_enum.insert("distance", VOLUME_SAMPLING_DISTANCE);
156  volume_sampling_method_enum.insert("equiangular", VOLUME_SAMPLING_EQUIANGULAR);
157  volume_sampling_method_enum.insert("multiple_importance", VOLUME_SAMPLING_MULTIPLE_IMPORTANCE);
158  SOCKET_ENUM(volume_sampling_method,
159  "Volume Sampling Method",
160  volume_sampling_method_enum,
162 
163  static NodeEnum volume_interpolation_method_enum;
164  volume_interpolation_method_enum.insert("linear", VOLUME_INTERPOLATION_LINEAR);
165  volume_interpolation_method_enum.insert("cubic", VOLUME_INTERPOLATION_CUBIC);
166  SOCKET_ENUM(volume_interpolation_method,
167  "Volume Interpolation Method",
168  volume_interpolation_method_enum,
170 
171  SOCKET_FLOAT(volume_step_rate, "Volume Step Rate", 1.0f);
172 
173  static NodeEnum displacement_method_enum;
174  displacement_method_enum.insert("bump", DISPLACE_BUMP);
175  displacement_method_enum.insert("true", DISPLACE_TRUE);
176  displacement_method_enum.insert("both", DISPLACE_BOTH);
177  SOCKET_ENUM(displacement_method, "Displacement Method", displacement_method_enum, DISPLACE_BUMP);
178 
179  SOCKET_INT(pass_id, "Pass ID", 0);
180 
181  return type;
182 }
183 
184 Shader::Shader() : Node(get_node_type())
185 {
186  pass_id = 0;
187 
188  graph = NULL;
189 
190  has_surface = false;
191  has_surface_transparent = false;
192  has_surface_emission = false;
193  has_surface_raytrace = false;
194  has_surface_bssrdf = false;
195  has_volume = false;
196  has_displacement = false;
197  has_bump = false;
198  has_bssrdf_bump = false;
203  has_volume_connected = false;
204  prev_volume_step_rate = 0.0f;
205 
206  displacement_method = DISPLACE_BUMP;
207 
208  id = -1;
209 
210  need_update_uvs = true;
211  need_update_attribute = true;
213 }
214 
216 {
217  delete graph;
218 }
219 
221 {
222  /* If the shader has AOVs, they need to be evaluated, so we can't skip the shader. */
223  foreach (ShaderNode *node, graph->nodes) {
224  if (node->special_type == SHADER_SPECIAL_TYPE_OUTPUT_AOV) {
225  return false;
226  }
227  }
228 
229  ShaderInput *surf = graph->output()->input("Surface");
230 
231  if (surf->link == NULL) {
232  return false;
233  }
234 
235  if (surf->link->parent->type == EmissionNode::get_node_type()) {
237 
238  assert(node->input("Color"));
239  assert(node->input("Strength"));
240 
241  if (node->input("Color")->link || node->input("Strength")->link) {
242  return false;
243  }
244 
245  *emission = node->get_color() * node->get_strength();
246  }
247  else if (surf->link->parent->type == BackgroundNode::get_node_type()) {
249 
250  assert(node->input("Color"));
251  assert(node->input("Strength"));
252 
253  if (node->input("Color")->link || node->input("Strength")->link) {
254  return false;
255  }
256 
257  *emission = node->get_color() * node->get_strength();
258  }
259  else {
260  return false;
261  }
262 
263  return true;
264 }
265 
267 {
268  /* do this here already so that we can detect if mesh or object attributes
269  * are needed, since the node attribute callbacks check if their sockets
270  * are connected but proxy nodes should not count */
271  if (graph_) {
272  graph_->remove_proxy_nodes();
273 
274  if (displacement_method != DISPLACE_BUMP) {
275  graph_->compute_displacement_hash();
276  }
277  }
278 
279  /* update geometry if displacement changed */
280  if (displacement_method != DISPLACE_BUMP) {
281  const char *old_hash = (graph) ? graph->displacement_hash.c_str() : "";
282  const char *new_hash = (graph_) ? graph_->displacement_hash.c_str() : "";
283 
284  if (strcmp(old_hash, new_hash) != 0) {
286  }
287  }
288 
289  /* assign graph */
290  delete graph;
291  graph = graph_;
292 
293  /* Store info here before graph optimization to make sure that
294  * nodes that get optimized away still count. */
295  has_volume_connected = (graph->output()->input("Volume")->link != NULL);
296 }
297 
299 {
300  /* update tag */
301  tag_modified();
302 
304 
305  /* if the shader previously was emissive, update light distribution,
306  * if the new shader is emissive, a light manager update tag will be
307  * done in the shader manager device update. */
308  if (use_mis && has_surface_emission)
310 
311  /* Special handle of background MIS light for now: for some reason it
312  * has use_mis set to false. We are quite close to release now, so
313  * better to be safe.
314  */
315  if (this == scene->background->get_shader(scene)) {
319  }
320  }
321 
322  /* quick detection of which kind of shaders we have to avoid loading
323  * e.g. surface attributes when there is only a volume shader. this could
324  * be more fine grained but it's better than nothing */
326  bool prev_has_volume = has_volume;
327  has_surface = has_surface || output->input("Surface")->link;
328  has_volume = has_volume || output->input("Volume")->link;
329  has_displacement = has_displacement || output->input("Displacement")->link;
330 
331  /* get requested attributes. this could be optimized by pruning unused
332  * nodes here already, but that's the job of the shader manager currently,
333  * and may not be so great for interactive rendering where you temporarily
334  * disconnect a node */
335 
336  AttributeRequestSet prev_attributes = attributes;
337 
338  attributes.clear();
339  foreach (ShaderNode *node, graph->nodes)
340  node->attributes(this, &attributes);
341 
342  if (has_displacement) {
343  if (displacement_method == DISPLACE_BOTH) {
345  }
346  if (displacement_method_is_modified()) {
350  }
351  }
352 
353  /* compare if the attributes changed, mesh manager will check
354  * need_update_attribute, update the relevant meshes and clear it. */
355  if (attributes.modified(prev_attributes)) {
356  need_update_attribute = true;
359  }
360 
361  if (has_volume != prev_has_volume || volume_step_rate != prev_volume_step_rate) {
364  prev_volume_step_rate = volume_step_rate;
365  }
366 }
367 
369 {
370  /* if an unused shader suddenly gets used somewhere, it needs to be
371  * recompiled because it was skipped for compilation before */
372  if (!reference_count()) {
373  tag_modified();
374  /* We do not reference here as the shader will be referenced when added to a socket. */
376  }
377 }
378 
380 {
382 }
383 
384 /* Shader Manager */
385 
387 {
390 
392 }
393 
395 {
396 }
397 
399 {
400  ShaderManager *manager;
401 
402  (void)shadingsystem; /* Ignored when built without OSL. */
403 
404 #ifdef WITH_OSL
405  if (shadingsystem == SHADINGSYSTEM_OSL) {
406  manager = new OSLShaderManager();
407  }
408  else
409 #endif
410  {
411  manager = new SVMShaderManager();
412  }
413 
414  return manager;
415 }
416 
418 {
420 
421  /* get a unique id for each name, for SVM attribute lookup */
422  AttributeIDMap::iterator it = unique_attribute_id.find(name);
423 
424  if (it != unique_attribute_id.end())
425  return it->second;
426 
427  uint id = (uint)ATTR_STD_NUM + unique_attribute_id.size();
428  unique_attribute_id[name] = id;
429  return id;
430 }
431 
433 {
434  return (uint)std;
435 }
436 
438 {
439  /* get a shader id to pass to the kernel */
440  int id = shader->id;
441 
442  /* smooth flag */
443  if (smooth)
444  id |= SHADER_SMOOTH_NORMAL;
445 
446  /* default flags */
448 
449  return id;
450 }
451 
453  DeviceScene *dscene,
454  Scene *scene,
455  Progress &progress)
456 {
457  if (!need_update()) {
458  return;
459  }
460 
461  uint id = 0;
462  foreach (Shader *shader, scene->shaders) {
463  shader->id = id++;
464  }
465 
466  /* Those shaders should always be compiled as they are used as fallback if a shader cannot be
467  * found, e.g. bad shader index for the triangle shaders on a Mesh. */
468  assert(scene->default_surface->reference_count() != 0);
469  assert(scene->default_light->reference_count() != 0);
470  assert(scene->default_background->reference_count() != 0);
471  assert(scene->default_empty->reference_count() != 0);
472 
473  device_update_specific(device, dscene, scene, progress);
474 }
475 
477  DeviceScene *dscene,
478  Scene *scene,
479  Progress & /*progress*/)
480 {
481  dscene->shaders.free();
482 
483  if (scene->shaders.size() == 0)
484  return;
485 
486  KernelShader *kshader = dscene->shaders.alloc(scene->shaders.size());
487  bool has_volumes = false;
488  bool has_transparent_shadow = false;
489 
490  foreach (Shader *shader, scene->shaders) {
491  uint flag = 0;
492 
493  if (shader->get_use_mis())
494  flag |= SD_USE_MIS;
495  if (shader->has_surface_emission)
496  flag |= SD_HAS_EMISSION;
497  if (shader->has_surface_transparent && shader->get_use_transparent_shadow())
499  if (shader->has_surface_raytrace)
500  flag |= SD_HAS_RAYTRACE;
501  if (shader->has_volume) {
502  flag |= SD_HAS_VOLUME;
503  has_volumes = true;
504 
505  /* todo: this could check more fine grained, to skip useless volumes
506  * enclosed inside an opaque bsdf.
507  */
509  }
510  /* in this case we can assume transparent surface */
511  if (shader->has_volume_connected && !shader->has_surface)
512  flag |= SD_HAS_ONLY_VOLUME;
513  if (shader->has_volume) {
514  if (shader->get_heterogeneous_volume() && shader->has_volume_spatial_varying)
515  flag |= SD_HETEROGENEOUS_VOLUME;
516  }
519  if (shader->has_bssrdf_bump)
520  flag |= SD_HAS_BSSRDF_BUMP;
521  if (shader->get_volume_sampling_method() == VOLUME_SAMPLING_EQUIANGULAR)
522  flag |= SD_VOLUME_EQUIANGULAR;
523  if (shader->get_volume_sampling_method() == VOLUME_SAMPLING_MULTIPLE_IMPORTANCE)
524  flag |= SD_VOLUME_MIS;
525  if (shader->get_volume_interpolation_method() == VOLUME_INTERPOLATION_CUBIC)
526  flag |= SD_VOLUME_CUBIC;
527  if (shader->has_bump)
528  flag |= SD_HAS_BUMP;
529  if (shader->get_displacement_method() != DISPLACE_BUMP)
530  flag |= SD_HAS_DISPLACEMENT;
531 
532  /* constant emission check */
533  float3 constant_emission = zero_float3();
534  if (shader->is_constant_emission(&constant_emission))
535  flag |= SD_HAS_CONSTANT_EMISSION;
536 
537  uint32_t cryptomatte_id = util_murmur_hash3(shader->name.c_str(), shader->name.length(), 0);
538 
539  /* regular shader */
540  kshader->flags = flag;
541  kshader->pass_id = shader->get_pass_id();
542  kshader->constant_emission[0] = constant_emission.x;
543  kshader->constant_emission[1] = constant_emission.y;
544  kshader->constant_emission[2] = constant_emission.z;
545  kshader->cryptomatte_id = util_hash_to_float(cryptomatte_id);
546  kshader++;
547 
548  has_transparent_shadow |= (flag & SD_HAS_TRANSPARENT_SHADOW) != 0;
549  }
550 
551  dscene->shaders.copy_to_device();
552 
553  /* lookup tables */
554  KernelTables *ktables = &dscene->data.tables;
555 
556  /* beckmann lookup table */
558  if (!beckmann_table_ready) {
560  if (!beckmann_table_ready) {
562  beckmann_table_ready = true;
563  }
564  }
566  }
567  ktables->beckmann_offset = (int)beckmann_table_offset;
568 
569  /* integrator */
570  KernelIntegrator *kintegrator = &dscene->data.integrator;
571  kintegrator->use_volumes = has_volumes;
572  /* TODO(sergey): De-duplicate with flags set in integrator.cpp. */
573  kintegrator->transparent_shadows = has_transparent_shadow;
574 
575  /* film */
576  KernelFilm *kfilm = &dscene->data.film;
577  /* color space, needs to be here because e.g. displacement shaders could depend on it */
578  kfilm->xyz_to_r = float3_to_float4(xyz_to_r);
579  kfilm->xyz_to_g = float3_to_float4(xyz_to_g);
580  kfilm->xyz_to_b = float3_to_float4(xyz_to_b);
581  kfilm->rgb_to_y = float3_to_float4(rgb_to_y);
582  kfilm->rec709_to_r = float3_to_float4(rec709_to_r);
583  kfilm->rec709_to_g = float3_to_float4(rec709_to_g);
584  kfilm->rec709_to_b = float3_to_float4(rec709_to_b);
585  kfilm->is_rec709 = is_rec709;
586 }
587 
589 {
591 
592  dscene->shaders.free();
593 }
594 
596 {
597  /* default surface */
598  {
599  ShaderGraph *graph = new ShaderGraph();
600 
601  DiffuseBsdfNode *diffuse = graph->create_node<DiffuseBsdfNode>();
602  diffuse->set_color(make_float3(0.8f, 0.8f, 0.8f));
603  graph->add(diffuse);
604 
605  graph->connect(diffuse->output("BSDF"), graph->output()->input("Surface"));
606 
607  Shader *shader = scene->create_node<Shader>();
608  shader->name = "default_surface";
609  shader->set_graph(graph);
610  shader->reference();
611  scene->default_surface = shader;
612  shader->tag_update(scene);
613  }
614 
615  /* default volume */
616  {
617  ShaderGraph *graph = new ShaderGraph();
618 
619  PrincipledVolumeNode *principled = graph->create_node<PrincipledVolumeNode>();
620  graph->add(principled);
621 
622  graph->connect(principled->output("Volume"), graph->output()->input("Volume"));
623 
624  Shader *shader = scene->create_node<Shader>();
625  shader->name = "default_volume";
626  shader->set_graph(graph);
627  scene->default_volume = shader;
628  shader->tag_update(scene);
629  /* No default reference for the volume to avoid compiling volume kernels if there are no actual
630  * volumes in the scene */
631  }
632 
633  /* default light */
634  {
635  ShaderGraph *graph = new ShaderGraph();
636 
637  EmissionNode *emission = graph->create_node<EmissionNode>();
638  emission->set_color(make_float3(0.8f, 0.8f, 0.8f));
639  emission->set_strength(0.0f);
640  graph->add(emission);
641 
642  graph->connect(emission->output("Emission"), graph->output()->input("Surface"));
643 
644  Shader *shader = scene->create_node<Shader>();
645  shader->name = "default_light";
646  shader->set_graph(graph);
647  shader->reference();
648  scene->default_light = shader;
649  shader->tag_update(scene);
650  }
651 
652  /* default background */
653  {
654  ShaderGraph *graph = new ShaderGraph();
655 
656  Shader *shader = scene->create_node<Shader>();
657  shader->name = "default_background";
658  shader->set_graph(graph);
659  shader->reference();
660  scene->default_background = shader;
661  shader->tag_update(scene);
662  }
663 
664  /* default empty */
665  {
666  ShaderGraph *graph = new ShaderGraph();
667 
668  Shader *shader = scene->create_node<Shader>();
669  shader->name = "default_empty";
670  shader->set_graph(graph);
671  shader->reference();
672  scene->default_empty = shader;
673  shader->tag_update(scene);
674  }
675 }
676 
678 {
679  uint kernel_features = 0;
680 
681  foreach (ShaderNode *node, graph->nodes) {
682  kernel_features |= node->get_feature();
683  if (node->special_type == SHADER_SPECIAL_TYPE_CLOSURE) {
684  BsdfBaseNode *bsdf_node = static_cast<BsdfBaseNode *>(node);
685  if (CLOSURE_IS_VOLUME(bsdf_node->get_closure_type())) {
686  kernel_features |= KERNEL_FEATURE_NODE_VOLUME;
687  }
688  else if (CLOSURE_IS_PRINCIPLED(bsdf_node->get_closure_type())) {
689  kernel_features |= KERNEL_FEATURE_PRINCIPLED;
690  }
691  }
692  if (node->has_surface_bssrdf()) {
693  kernel_features |= KERNEL_FEATURE_SUBSURFACE;
694  }
695  if (node->has_surface_transparent()) {
696  kernel_features |= KERNEL_FEATURE_TRANSPARENT;
697  }
698  }
699 
700  return kernel_features;
701 }
702 
704 {
706  for (int i = 0; i < scene->shaders.size(); i++) {
707  Shader *shader = scene->shaders[i];
708  if (!shader->reference_count()) {
709  continue;
710  }
711 
712  /* Gather requested features from all the nodes from the graph nodes. */
713  kernel_features |= get_graph_kernel_features(shader->graph);
714  ShaderNode *output_node = shader->graph->output();
715  if (output_node->input("Displacement")->link != NULL) {
716  kernel_features |= KERNEL_FEATURE_NODE_BUMP;
717  if (shader->get_displacement_method() == DISPLACE_BOTH) {
718  kernel_features |= KERNEL_FEATURE_NODE_BUMP_STATE;
719  }
720  }
721  /* On top of volume nodes, also check if we need volume sampling because
722  * e.g. an Emission node would slip through the KERNEL_FEATURE_NODE_VOLUME check */
723  if (shader->has_volume_connected) {
724  kernel_features |= KERNEL_FEATURE_VOLUME;
725  }
726  }
727 
728  return kernel_features;
729 }
730 
732 {
733  beckmann_table.free_memory();
734 
735 #ifdef WITH_OSL
736  OSLShaderManager::free_memory();
737 #endif
738 
740 }
741 
743 {
744  return dot(c, rgb_to_y);
745 }
746 
748 {
750 }
751 
753 {
754  string manifest = "{";
755  unordered_set<ustring, ustringHash> materials;
756  foreach (Shader *shader, scene->shaders) {
757  if (materials.count(shader->name)) {
758  continue;
759  }
760  materials.insert(shader->name);
761  uint32_t cryptomatte_id = util_murmur_hash3(shader->name.c_str(), shader->name.length(), 0);
762  manifest += string_printf("\"%s\":\"%08x\",", shader->name.c_str(), cryptomatte_id);
763  }
764  manifest[manifest.size() - 1] = '}';
765  return manifest;
766 }
767 
768 void ShaderManager::tag_update(Scene * /*scene*/, uint32_t /*flag*/)
769 {
770  /* update everything for now */
772 }
773 
775 {
776  return update_flags != UPDATE_NONE;
777 }
778 
779 #ifdef WITH_OCIO
780 static bool to_scene_linear_transform(OCIO::ConstConfigRcPtr &config,
781  const char *colorspace,
782  Transform &to_scene_linear)
783 {
784  OCIO::ConstProcessorRcPtr processor;
785  try {
786  processor = config->getProcessor(OCIO::ROLE_SCENE_LINEAR, colorspace);
787  }
788  catch (OCIO::Exception &) {
789  return false;
790  }
791 
792  if (!processor) {
793  return false;
794  }
795 
796  OCIO::ConstCPUProcessorRcPtr device_processor = processor->getDefaultCPUProcessor();
797  if (!device_processor) {
798  return false;
799  }
800 
801  to_scene_linear = transform_identity();
802  device_processor->applyRGB(&to_scene_linear.x.x);
803  device_processor->applyRGB(&to_scene_linear.y.x);
804  device_processor->applyRGB(&to_scene_linear.z.x);
805  to_scene_linear = transform_transposed_inverse(to_scene_linear);
806  return true;
807 }
808 #endif
809 
811 {
812  /* Default to ITU-BT.709 in case no appropriate transform found.
813  * Note XYZ here is defined as having a D65 white point. */
814  const Transform xyz_to_rec709 = make_transform(3.2404542f,
815  -1.5371385f,
816  -0.4985314f,
817  0.0f,
818  -0.9692660f,
819  1.8760108f,
820  0.0415560f,
821  0.0f,
822  0.0556434f,
823  -0.2040259f,
824  1.0572252f,
825  0.0f);
826 
827  xyz_to_r = float4_to_float3(xyz_to_rec709.x);
828  xyz_to_g = float4_to_float3(xyz_to_rec709.y);
829  xyz_to_b = float4_to_float3(xyz_to_rec709.z);
830  rgb_to_y = make_float3(0.2126729f, 0.7151522f, 0.0721750f);
831 
832  rec709_to_r = make_float3(1.0f, 0.0f, 0.0f);
833  rec709_to_g = make_float3(0.0f, 1.0f, 0.0f);
834  rec709_to_b = make_float3(0.0f, 0.0f, 1.0f);
835  is_rec709 = true;
836 
837 #ifdef WITH_OCIO
838  /* Get from OpenColorO config if it has the required roles. */
839  OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
840  if (!(config && config->hasRole(OCIO::ROLE_SCENE_LINEAR))) {
841  return;
842  }
843 
845 
846  if (config->hasRole("aces_interchange")) {
847  /* Standard OpenColorIO role, defined as ACES AP0 (ACES2065-1). */
848  Transform aces_to_rgb;
849  if (!to_scene_linear_transform(config, "aces_interchange", aces_to_rgb)) {
850  return;
851  }
852 
853  /* This is the OpenColorIO builtin transform:
854  * UTILITY - ACES-AP0_to_CIE-XYZ-D65_BFD. */
855  const Transform ACES_AP0_to_xyz_D65 = make_transform(0.938280f,
856  -0.004451f,
857  0.016628f,
858  0.000000f,
859  0.337369f,
860  0.729522f,
861  -0.066890f,
862  0.000000f,
863  0.001174f,
864  -0.003711f,
865  1.091595f,
866  0.000000f);
867  const Transform xyz_to_aces = transform_inverse(ACES_AP0_to_xyz_D65);
868  xyz_to_rgb = aces_to_rgb * xyz_to_aces;
869  }
870  else if (config->hasRole("XYZ")) {
871  /* Custom role used before the standard existed. */
872  if (!to_scene_linear_transform(config, "XYZ", xyz_to_rgb)) {
873  return;
874  }
875  }
876  else {
877  /* No reference role found to determine XYZ. */
878  return;
879  }
880 
884 
885  const Transform rgb_to_xyz = transform_inverse(xyz_to_rgb);
886  rgb_to_y = float4_to_float3(rgb_to_xyz.y);
887 
888  const Transform rec709_to_rgb = xyz_to_rgb * transform_inverse(xyz_to_rec709);
892  is_rec709 = transform_equal_threshold(xyz_to_rgb, xyz_to_rec709, 0.0001f);
893 #endif
894 }
895 
typedef float(TangentPoint)[2]
MINLINE float safe_sqrtf(float a)
unsigned int uint
Definition: BLI_sys_types.h:67
typedef double(DMatrix)[4][4]
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
volatile int lock
#define U
unsigned int U
Definition: btGjkEpa3.h:78
void add(ustring name)
bool modified(const AttributeRequestSet &other)
Shader * get_shader(const Scene *scene)
virtual ClosureType get_closure_type()
Definition: shader_nodes.h:459
static void free_memory()
Definition: colorspace.cpp:434
device_vector< KernelShader > shaders
Definition: scene.h:119
KernelData data
Definition: scene.h:130
void tag_update(Scene *scene, uint32_t flag)
bool need_update_background
Definition: scene/light.h:103
bool has_background_light(Scene *scene)
void tag_update(Scene *scene, uint32_t flag)
size_t add_table(DeviceScene *dscene, vector< float > &data)
Definition: tables.cpp:60
void remove_table(size_t *offset)
Definition: tables.cpp:95
bool need_flags_update
Definition: scene/object.h:144
string displacement_hash
Definition: shader_graph.h:303
list< ShaderNode * > nodes
Definition: shader_graph.h:299
OutputNode * output()
void compute_displacement_hash()
void remove_proxy_nodes()
ShaderOutput * link
Definition: shader_graph.h:103
string get_cryptomatte_materials(Scene *scene)
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress)
void device_update_common(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress)
static bool beckmann_table_ready
Definition: scene/shader.h:231
static void free_memory()
uint get_attribute_id(ustring name)
AttributeIDMap unique_attribute_id
Definition: scene/shader.h:227
float linear_rgb_to_gray(float3 c)
void init_xyz_transforms()
virtual void device_update_specific(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress)=0
size_t beckmann_table_offset
Definition: scene/shader.h:233
thread_spin_lock attribute_lock_
Definition: scene/shader.h:237
virtual ~ShaderManager()
int get_shader_id(Shader *shader, bool smooth=false)
float3 rec709_to_b
Definition: scene/shader.h:245
bool need_update() const
static ShaderManager * create(int shadingsystem)
void device_free_common(Device *device, DeviceScene *dscene, Scene *scene)
static vector< float > beckmann_table
Definition: scene/shader.h:230
static thread_mutex lookup_table_mutex
Definition: scene/shader.h:229
void tag_update(Scene *scene, uint32_t flag)
uint get_kernel_features(Scene *scene)
float3 rec709_to_g
Definition: scene/shader.h:244
float3 rec709_to_scene_linear(float3 c)
float3 rec709_to_r
Definition: scene/shader.h:243
static void add_default(Scene *scene)
uint32_t update_flags
Definition: scene/shader.h:224
uint get_graph_kernel_features(ShaderGraph *graph)
ShaderInput * input(const char *name)
ShaderOutput * output(const char *name)
ShaderNode * parent
Definition: shader_graph.h:134
bool has_surface_spatial_varying
Definition: scene/shader.h:112
bool has_surface_bssrdf
Definition: scene/shader.h:109
bool need_update_attribute
Definition: scene/shader.h:90
bool has_volume_attribute_dependency
Definition: scene/shader.h:114
uint id
Definition: scene/shader.h:121
void set_graph(ShaderGraph *graph)
bool need_update_geometry() const
bool has_volume
Definition: scene/shader.h:107
bool has_surface
Definition: scene/shader.h:103
bool has_bssrdf_bump
Definition: scene/shader.h:111
NODE_DECLARE ShaderGraph * graph
Definition: scene/shader.h:71
float prev_volume_step_rate
Definition: scene/shader.h:86
bool has_integrator_dependency
Definition: scene/shader.h:115
bool need_update_displacement
Definition: scene/shader.h:91
bool has_surface_emission
Definition: scene/shader.h:104
bool has_surface_raytrace
Definition: scene/shader.h:106
bool need_update_uvs
Definition: scene/shader.h:89
bool has_displacement
Definition: scene/shader.h:108
bool has_bump
Definition: scene/shader.h:110
AttributeRequestSet attributes
Definition: scene/shader.h:118
bool has_surface_transparent
Definition: scene/shader.h:105
void tag_update(Scene *scene)
bool is_constant_emission(float3 *emission)
bool has_volume_connected
Definition: scene/shader.h:100
void tag_used(Scene *scene)
bool has_volume_spatial_varying
Definition: scene/shader.h:113
T * alloc(size_t width, size_t height=0, size_t depth=0)
#define expf(x)
Definition: cuda/compat.h:106
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
OperationNode * node
Depsgraph * graph
Scene scene
#define function_bind
SyclQueue void void size_t num_bytes void
smooth(Type::VEC4, "color_mul") .smooth(Type gpFillTexture gpSceneDepthTexture materials[GPENCIL_MATERIAL_BUFFER_LEN]
Definition: gpencil_info.hh:29
ccl_device_inline Transform transform_identity()
ccl_device_inline bool transform_equal_threshold(const Transform &A, const Transform &B, const float threshold)
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)
ccl_device_inline Transform transform_inverse(const Transform tfm)
ccl_global KernelShaderEvalInput ccl_global float * output
#define CLOSURE_IS_VOLUME(type)
#define CLOSURE_IS_PRINCIPLED(type)
@ SD_VOLUME_MIS
Definition: kernel/types.h:778
@ SD_HAS_TRANSPARENT_SHADOW
Definition: kernel/types.h:766
@ SD_VOLUME_EQUIANGULAR
Definition: kernel/types.h:776
@ SD_HAS_BUMP
Definition: kernel/types.h:782
@ SD_HAS_CONSTANT_EMISSION
Definition: kernel/types.h:786
@ SD_HAS_DISPLACEMENT
Definition: kernel/types.h:784
@ SD_HAS_EMISSION
Definition: kernel/types.h:790
@ SD_HAS_BSSRDF_BUMP
Definition: kernel/types.h:774
@ SD_HAS_ONLY_VOLUME
Definition: kernel/types.h:770
@ SD_HAS_RAYTRACE
Definition: kernel/types.h:792
@ SD_VOLUME_CUBIC
Definition: kernel/types.h:780
@ SD_HAS_VOLUME
Definition: kernel/types.h:768
@ SD_USE_MIS
Definition: kernel/types.h:764
@ SD_NEED_VOLUME_ATTRIBUTES
Definition: kernel/types.h:788
@ SD_HETEROGENEOUS_VOLUME
Definition: kernel/types.h:772
AttributeStandard
Definition: kernel/types.h:612
@ ATTR_STD_NUM
Definition: kernel/types.h:645
@ ATTR_STD_POSITION_UNDISPLACED
Definition: kernel/types.h:623
@ KERNEL_FEATURE_NODE_VOLUME
@ KERNEL_FEATURE_NODE_EMISSION
@ KERNEL_FEATURE_NODE_BSDF
@ KERNEL_FEATURE_NODE_BUMP
@ KERNEL_FEATURE_SUBSURFACE
@ KERNEL_FEATURE_PRINCIPLED
@ KERNEL_FEATURE_TRANSPARENT
@ KERNEL_FEATURE_VOLUME
@ KERNEL_FEATURE_NODE_BUMP_STATE
#define BECKMANN_TABLE_SIZE
Definition: kernel/types.h:37
@ SHADER_AREA_LIGHT
Definition: kernel/types.h:437
@ SHADER_SMOOTH_NORMAL
Definition: kernel/types.h:435
@ SHADER_CAST_SHADOW
Definition: kernel/types.h:436
ccl_device float3 rec709_to_rgb(KernelGlobals kg, float3 rec709)
ccl_device_inline float2 interp(const float2 &a, const float2 &b, float t)
Definition: math_float2.h:232
ccl_device_inline float3 zero_float3()
Definition: math_float3.h:80
#define fmaxf(x, y)
Definition: metal/compat.h:228
#define make_float3(x, y, z)
Definition: metal/compat.h:204
float util_hash_to_float(uint32_t hash)
Definition: murmurhash.cpp:98
uint32_t util_murmur_hash3(const void *key, int len, uint32_t seed)
Definition: murmurhash.cpp:49
static unsigned c
Definition: RandGen.cpp:83
std::unique_ptr< IDProperty, IDPropertyDeleter > create(StringRefNull prop_name, int32_t value)
Allocate a new IDProperty of type IDP_INT, set its name and value.
T dot(const vec_base< T, Size > &a, const vec_base< T, Size > &b)
color xyz_to_rgb(float x, float y, float z)
Definition: node_color.h:63
#define SOCKET_FLOAT(name, ui_name, default_value,...)
Definition: node_type.h:191
#define SOCKET_INT(name, ui_name, default_value,...)
Definition: node_type.h:187
#define SOCKET_BOOLEAN(name, ui_name, default_value,...)
Definition: node_type.h:185
#define SOCKET_ENUM(name, ui_name, values, default_value,...)
Definition: node_type.h:207
smooth(Type::FLOAT, "mask_weight")
static void beckmann_table_rows(float *table, int row_from, int row_to)
static void beckmann_table_build(vector< float > &table)
NODE_DEFINE(Shader)
#define MSVC_VOLATILE
static float beckmann_table_P22(const float slope_x, const float slope_y)
static float beckmann_table_slope_max()
@ VOLUME_INTERPOLATION_LINEAR
Definition: scene/shader.h:46
@ VOLUME_INTERPOLATION_CUBIC
Definition: scene/shader.h:47
@ DISPLACE_BUMP
Definition: scene/shader.h:53
@ DISPLACE_TRUE
Definition: scene/shader.h:54
@ DISPLACE_BOTH
Definition: scene/shader.h:55
@ SHADINGSYSTEM_OSL
Definition: scene/shader.h:34
@ VOLUME_SAMPLING_DISTANCE
Definition: scene/shader.h:38
@ VOLUME_SAMPLING_EQUIANGULAR
Definition: scene/shader.h:39
@ VOLUME_SAMPLING_MULTIPLE_IMPORTANCE
Definition: scene/shader.h:40
@ TABLE_OFFSET_INVALID
Definition: scene/tables.h:17
@ SHADER_SPECIAL_TYPE_OUTPUT_AOV
Definition: shader_graph.h:57
@ SHADER_SPECIAL_TYPE_CLOSURE
Definition: shader_graph.h:53
unsigned int uint32_t
Definition: stdint.h:80
CCL_NAMESPACE_BEGIN string string_printf(const char *format,...)
Definition: string.cpp:22
KernelTables tables
float constant_emission[3]
float cryptomatte_id
void insert(const char *x, int y)
Definition: node_enum.h:20
static NodeType * add(const char *name, CreateFunc create, Type type=NONE, const NodeType *base=NULL)
const NodeType * type
Definition: graph/node.h:175
ustring name
Definition: graph/node.h:174
int reference_count() const
Definition: graph/node.h:180
void reference()
Definition: graph/node.h:185
void tag_modified()
Definition: graph/node.cpp:809
T * create_node(Args &&...args)
Definition: scene.h:284
vector< Shader * > shaders
Definition: scene.h:215
Shader * default_volume
Definition: scene.h:233
LookupTables * lookup_tables
Definition: scene.h:207
Shader * default_surface
Definition: scene.h:232
Shader * default_empty
Definition: scene.h:236
Shader * default_background
Definition: scene.h:235
ObjectManager * object_manager
Definition: scene.h:226
Background * background
Definition: scene.h:209
ProceduralManager * procedural_manager
Definition: scene.h:229
ShaderManager * shader_manager
Definition: scene.h:224
LightManager * light_manager
Definition: scene.h:223
Shader * default_light
Definition: scene.h:234
GeometryManager * geometry_manager
Definition: scene.h:225
void push(TaskRunFunction &&task)
Definition: task.cpp:23
void wait_work(Summary *stats=NULL)
Definition: task.cpp:29
float z
float y
float x
std::unique_lock< std::mutex > thread_scoped_lock
Definition: thread.h:28
CCL_NAMESPACE_BEGIN typedef std::mutex thread_mutex
Definition: thread.h:27
Transform transform_transposed_inverse(const Transform &tfm)
Definition: transform.cpp:110
ccl_device_inline float4 float3_to_float4(const float3 a)
Definition: util/math.h:505
ccl_device_inline float3 float4_to_float3(const float4 a)
Definition: util/math.h:500