Blender  V2.93
graph.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2011-2016 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "render/graph.h"
18 #include "render/attribute.h"
19 #include "render/constant_fold.h"
20 #include "render/nodes.h"
21 #include "render/scene.h"
22 #include "render/shader.h"
23 
24 #include "util/util_algorithm.h"
25 #include "util/util_foreach.h"
26 #include "util/util_logging.h"
27 #include "util/util_md5.h"
28 #include "util/util_queue.h"
29 
31 
32 namespace {
33 
35 {
36  foreach (const ShaderInput *in, node->inputs) {
37  if (in->link) {
38  return true;
39  }
40  }
41  return false;
42 }
43 
45 {
46  foreach (const ShaderInput *in, node->inputs) {
47  if (in->link) {
48  if (done.find(in->link->parent) == done.end()) {
49  return false;
50  }
51  }
52  }
53  return true;
54 }
55 
56 } /* namespace */
57 
58 /* Sockets */
59 
61 {
62  if (link) {
63  link->links.erase(remove(link->links.begin(), link->links.end(), this), link->links.end());
64  }
65  link = NULL;
66 }
67 
69 {
70  foreach (ShaderInput *sock, links) {
71  sock->link = NULL;
72  }
73 
74  links.clear();
75 }
76 
77 /* Node */
78 
80 {
81  name = type->name;
82  id = -1;
85 
87 }
88 
90 {
91  foreach (ShaderInput *socket, inputs)
92  delete socket;
93 
94  foreach (ShaderOutput *socket, outputs)
95  delete socket;
96 }
97 
99 {
100  foreach (const SocketType &socket, type->inputs) {
101  if (socket.flags & SocketType::LINKABLE) {
102  inputs.push_back(new ShaderInput(socket, this));
103  }
104  }
105 
106  foreach (const SocketType &socket, type->outputs) {
107  outputs.push_back(new ShaderOutput(socket, this));
108  }
109 }
110 
111 ShaderInput *ShaderNode::input(const char *name)
112 {
113  foreach (ShaderInput *socket, inputs) {
114  if (socket->name() == name)
115  return socket;
116  }
117 
118  return NULL;
119 }
120 
122 {
123  foreach (ShaderOutput *socket, outputs)
124  if (socket->name() == name)
125  return socket;
126 
127  return NULL;
128 }
129 
131 {
132  foreach (ShaderInput *socket, inputs) {
133  if (socket->name() == name)
134  return socket;
135  }
136 
137  return NULL;
138 }
139 
141 {
142  foreach (ShaderOutput *socket, outputs)
143  if (socket->name() == name)
144  return socket;
145 
146  return NULL;
147 }
148 
150 {
151  assert(input->link == NULL);
152  delete input;
153  inputs.erase(remove(inputs.begin(), inputs.end(), input), inputs.end());
154 }
155 
157 {
158  foreach (ShaderInput *input, inputs) {
159  if (!input->link) {
161  if (shader->has_surface)
163  if (shader->has_volume)
165  }
166  else if (input->flags() & SocketType::LINK_TEXTURE_UV) {
167  if (shader->has_surface)
168  attributes->add(ATTR_STD_UV);
169  }
170  }
171  }
172 }
173 
174 bool ShaderNode::equals(const ShaderNode &other)
175 {
176  if (type != other.type || bump != other.bump) {
177  return false;
178  }
179 
180  assert(inputs.size() == other.inputs.size());
181 
182  /* Compare unlinkable sockets */
183  foreach (const SocketType &socket, type->inputs) {
184  if (!(socket.flags & SocketType::LINKABLE)) {
185  if (!Node::equals_value(other, socket)) {
186  return false;
187  }
188  }
189  }
190 
191  /* Compare linkable input sockets */
192  for (int i = 0; i < inputs.size(); ++i) {
193  ShaderInput *input_a = inputs[i], *input_b = other.inputs[i];
194  if (input_a->link == NULL && input_b->link == NULL) {
195  /* Unconnected inputs are expected to have the same value. */
196  if (!Node::equals_value(other, input_a->socket_type)) {
197  return false;
198  }
199  }
200  else if (input_a->link != NULL && input_b->link != NULL) {
201  /* Expect links are to come from the same exact socket. */
202  if (input_a->link != input_b->link) {
203  return false;
204  }
205  }
206  else {
207  /* One socket has a link and another has not, inputs can't be
208  * considered equal.
209  */
210  return false;
211  }
212  }
213 
214  return true;
215 }
216 
217 /* Graph */
218 
220 {
221  finalized = false;
222  simplified = false;
223  num_node_ids = 0;
224  add(create_node<OutputNode>());
225 }
226 
228 {
229  clear_nodes();
230 }
231 
233 {
234  assert(!finalized);
235  simplified = false;
236 
237  node->id = num_node_ids++;
238  nodes.push_back(node);
239  return node;
240 }
241 
243 {
244  return (OutputNode *)nodes.front();
245 }
246 
248 {
249  assert(!finalized);
250  assert(from && to);
251 
252  if (to->link) {
253  fprintf(stderr, "Cycles shader graph connect: input already connected.\n");
254  return;
255  }
256 
257  if (from->type() != to->type()) {
258  /* can't do automatic conversion from closure */
259  if (from->type() == SocketType::CLOSURE) {
260  fprintf(stderr,
261  "Cycles shader graph connect: can only connect closure to closure "
262  "(%s.%s to %s.%s).\n",
263  from->parent->name.c_str(),
264  from->name().c_str(),
265  to->parent->name.c_str(),
266  to->name().c_str());
267  return;
268  }
269 
270  /* add automatic conversion node in case of type mismatch */
272  ShaderInput *convert_in;
273 
274  if (to->type() == SocketType::CLOSURE) {
275  EmissionNode *emission = create_node<EmissionNode>();
276  emission->set_color(one_float3());
277  emission->set_strength(1.0f);
278  convert = add(emission);
279  /* Connect float inputs to Strength to save an additional Value->Color conversion. */
280  if (from->type() == SocketType::FLOAT) {
281  convert_in = convert->input("Strength");
282  }
283  else {
284  convert_in = convert->input("Color");
285  }
286  }
287  else {
288  convert = add(create_node<ConvertNode>(from->type(), to->type(), true));
289  convert_in = convert->inputs[0];
290  }
291 
292  connect(from, convert_in);
293  connect(convert->outputs[0], to);
294  }
295  else {
296  /* types match, just connect */
297  to->link = from;
298  from->links.push_back(to);
299  }
300 }
301 
303 {
304  assert(!finalized);
305  simplified = false;
306 
307  from->disconnect();
308 }
309 
311 {
312  assert(!finalized);
313  assert(to->link);
314  simplified = false;
315 
316  to->disconnect();
317 }
318 
320 {
321  ShaderOutput *out = from->link;
322  if (out) {
323  disconnect(from);
324  connect(out, to);
325  }
326  to->parent->copy_value(to->socket_type, *(from->parent), from->socket_type);
327 }
328 
330 {
331  /* Copy because disconnect modifies this list. */
333 
334  foreach (ShaderInput *sock, outputs) {
335  disconnect(sock);
336  if (to)
337  connect(to, sock);
338  }
339 }
340 
342 {
343  simplified = false;
344 
345  /* Copy because disconnect modifies this list */
347 
348  /* Bypass node by moving all links from "from" to "to" */
349  foreach (ShaderInput *sock, node->inputs) {
350  if (sock->link)
351  disconnect(sock);
352  }
353 
354  foreach (ShaderInput *sock, outputs) {
355  disconnect(sock);
356  if (to)
357  connect(to, sock);
358  }
359 }
360 
362 {
363  if (!simplified) {
364  expand();
366  clean(scene);
368 
369  simplified = true;
370  }
371 }
372 
373 void ShaderGraph::finalize(Scene *scene, bool do_bump, bool do_simplify, bool bump_in_object_space)
374 {
375  /* before compiling, the shader graph may undergo a number of modifications.
376  * currently we set default geometry shader inputs, and create automatic bump
377  * from displacement. a graph can be finalized only once, and should not be
378  * modified afterwards. */
379 
380  if (!finalized) {
381  simplify(scene);
382 
383  if (do_bump)
384  bump_from_displacement(bump_in_object_space);
385 
386  ShaderInput *surface_in = output()->input("Surface");
387  ShaderInput *volume_in = output()->input("Volume");
388 
389  /* todo: make this work when surface and volume closures are tangled up */
390 
391  if (surface_in->link)
392  transform_multi_closure(surface_in->link->parent, NULL, false);
393  if (volume_in->link)
394  transform_multi_closure(volume_in->link->parent, NULL, true);
395 
396  finalized = true;
397  }
398  else if (do_simplify) {
400  }
401 }
402 
404 {
405  /* find all nodes that this input depends on directly and indirectly */
406  ShaderNode *node = (input->link) ? input->link->parent : NULL;
407 
408  if (node != NULL && dependencies.find(node) == dependencies.end()) {
409  foreach (ShaderInput *in, node->inputs)
410  find_dependencies(dependencies, in);
411 
412  dependencies.insert(node);
413  }
414 }
415 
417 {
418  foreach (ShaderNode *node, nodes) {
419  delete_node(node);
420  }
421  nodes.clear();
422 }
423 
425 {
426  /* copy a set of nodes, and the links between them. the assumption is
427  * made that all nodes that inputs are linked to are in the set too. */
428 
429  /* copy nodes */
430  foreach (ShaderNode *node, nodes) {
431  ShaderNode *nnode = node->clone(this);
432  nnodemap[node] = nnode;
433 
434  /* create new inputs and outputs to recreate links and ensure
435  * that we still point to valid SocketType if the NodeType
436  * changed in cloning, as it does for OSL nodes */
437  nnode->inputs.clear();
438  nnode->outputs.clear();
439  nnode->create_inputs_outputs(nnode->type);
440  }
441 
442  /* recreate links */
443  foreach (ShaderNode *node, nodes) {
444  foreach (ShaderInput *input, node->inputs) {
445  if (input->link) {
446  /* find new input and output */
447  ShaderNode *nfrom = nnodemap[input->link->parent];
448  ShaderNode *nto = nnodemap[input->parent];
449  ShaderOutput *noutput = nfrom->output(input->link->name());
450  ShaderInput *ninput = nto->input(input->name());
451 
452  /* connect */
453  connect(noutput, ninput);
454  }
455  }
456  }
457 }
458 
459 /* Graph simplification */
460 /* ******************** */
461 
462 /* Remove proxy nodes.
463  *
464  * These only exists temporarily when exporting groups, and we must remove them
465  * early so that node->attributes() and default links do not see them.
466  */
468 {
469  vector<bool> removed(num_node_ids, false);
470  bool any_node_removed = false;
471 
472  foreach (ShaderNode *node, nodes) {
473  if (node->special_type == SHADER_SPECIAL_TYPE_PROXY) {
474  ConvertNode *proxy = static_cast<ConvertNode *>(node);
475  ShaderInput *input = proxy->inputs[0];
476  ShaderOutput *output = proxy->outputs[0];
477 
478  /* bypass the proxy node */
479  if (input->link) {
480  relink(proxy, output, input->link);
481  }
482  else {
483  /* Copy because disconnect modifies this list */
484  vector<ShaderInput *> links(output->links);
485 
486  foreach (ShaderInput *to, links) {
487  /* Remove any auto-convert nodes too if they lead to
488  * sockets with an automatically set default value. */
489  ShaderNode *tonode = to->parent;
490 
492  bool all_links_removed = true;
493  vector<ShaderInput *> links = tonode->outputs[0]->links;
494 
495  foreach (ShaderInput *autoin, links) {
496  if (autoin->flags() & SocketType::DEFAULT_LINK_MASK)
497  disconnect(autoin);
498  else
499  all_links_removed = false;
500  }
501 
502  if (all_links_removed)
503  removed[tonode->id] = true;
504  }
505 
506  disconnect(to);
507 
508  /* transfer the default input value to the target socket */
509  tonode->copy_value(to->socket_type, *proxy, input->socket_type);
510  }
511  }
512 
513  removed[proxy->id] = true;
514  any_node_removed = true;
515  }
516  }
517 
518  /* remove nodes */
519  if (any_node_removed) {
520  list<ShaderNode *> newnodes;
521 
522  foreach (ShaderNode *node, nodes) {
523  if (!removed[node->id])
524  newnodes.push_back(node);
525  else
526  delete_node(node);
527  }
528 
529  nodes = newnodes;
530  }
531 }
532 
533 /* Constant folding.
534  *
535  * Try to constant fold some nodes, and pipe result directly to
536  * the input socket of connected nodes.
537  */
539 {
540  ShaderNodeSet done, scheduled;
541  queue<ShaderNode *> traverse_queue;
542 
543  bool has_displacement = (output()->input("Displacement")->link != NULL);
544 
545  /* Schedule nodes which doesn't have any dependencies. */
546  foreach (ShaderNode *node, nodes) {
548  traverse_queue.push(node);
549  scheduled.insert(node);
550  }
551  }
552 
553  while (!traverse_queue.empty()) {
554  ShaderNode *node = traverse_queue.front();
555  traverse_queue.pop();
556  done.insert(node);
557  foreach (ShaderOutput *output, node->outputs) {
558  if (output->links.size() == 0) {
559  continue;
560  }
561  /* Schedule node which was depending on the value,
562  * when possible. Do it before disconnect.
563  */
564  foreach (ShaderInput *input, output->links) {
565  if (scheduled.find(input->parent) != scheduled.end()) {
566  /* Node might not be optimized yet but scheduled already
567  * by other dependencies. No need to re-schedule it.
568  */
569  continue;
570  }
571  /* Schedule node if its inputs are fully done. */
572  if (check_node_inputs_traversed(input->parent, done)) {
573  traverse_queue.push(input->parent);
574  scheduled.insert(input->parent);
575  }
576  }
577  /* Optimize current node. */
578  ConstantFolder folder(this, node, output, scene);
579  node->constant_fold(folder);
580  }
581  }
582 
583  /* Folding might have removed all nodes connected to the displacement output
584  * even tho there is displacement to be applied, so add in a value node if
585  * that happens to ensure there is still a valid graph for displacement.
586  */
587  if (has_displacement && !output()->input("Displacement")->link) {
588  ColorNode *value = (ColorNode *)add(create_node<ColorNode>());
589  value->set_value(output()->get_displacement());
590 
591  connect(value->output("Color"), output()->input("Displacement"));
592  }
593 }
594 
595 /* Simplification. */
597 {
598  foreach (ShaderNode *node, nodes) {
599  node->simplify_settings(scene);
600  }
601 }
602 
603 /* Deduplicate nodes with same settings. */
605 {
606  /* NOTES:
607  * - Deduplication happens for nodes which has same exact settings and same
608  * exact input links configuration (either connected to same output or has
609  * the same exact default value).
610  * - Deduplication happens in the bottom-top manner, so we know for fact that
611  * all traversed nodes are either can not be deduplicated at all or were
612  * already deduplicated.
613  */
614 
615  ShaderNodeSet scheduled, done;
616  map<ustring, ShaderNodeSet> candidates;
617  queue<ShaderNode *> traverse_queue;
618  int num_deduplicated = 0;
619 
620  /* Schedule nodes which doesn't have any dependencies. */
621  foreach (ShaderNode *node, nodes) {
623  traverse_queue.push(node);
624  scheduled.insert(node);
625  }
626  }
627 
628  while (!traverse_queue.empty()) {
629  ShaderNode *node = traverse_queue.front();
630  traverse_queue.pop();
631  done.insert(node);
632  /* Schedule the nodes which were depending on the current node. */
633  bool has_output_links = false;
634  foreach (ShaderOutput *output, node->outputs) {
635  foreach (ShaderInput *input, output->links) {
636  has_output_links = true;
637  if (scheduled.find(input->parent) != scheduled.end()) {
638  /* Node might not be optimized yet but scheduled already
639  * by other dependencies. No need to re-schedule it.
640  */
641  continue;
642  }
643  /* Schedule node if its inputs are fully done. */
644  if (check_node_inputs_traversed(input->parent, done)) {
645  traverse_queue.push(input->parent);
646  scheduled.insert(input->parent);
647  }
648  }
649  }
650  /* Only need to care about nodes that are actually used */
651  if (!has_output_links) {
652  continue;
653  }
654  /* Try to merge this node with another one. */
655  ShaderNode *merge_with = NULL;
656  foreach (ShaderNode *other_node, candidates[node->type->name]) {
657  if (node != other_node && node->equals(*other_node)) {
658  merge_with = other_node;
659  break;
660  }
661  }
662  /* If found an equivalent, merge; otherwise keep node for later merges */
663  if (merge_with != NULL) {
664  for (int i = 0; i < node->outputs.size(); ++i) {
665  relink(node, node->outputs[i], merge_with->outputs[i]);
666  }
667  num_deduplicated++;
668  }
669  else {
670  candidates[node->type->name].insert(node);
671  }
672  }
673 
674  if (num_deduplicated > 0) {
675  VLOG(1) << "Deduplicated " << num_deduplicated << " nodes.";
676  }
677 }
678 
679 /* Check whether volume output has meaningful nodes, otherwise
680  * disconnect the output.
681  */
683 {
684  /* Check whether we can optimize the whole volume graph out. */
685  ShaderInput *volume_in = output()->input("Volume");
686  if (volume_in->link == NULL) {
687  return;
688  }
689  bool has_valid_volume = false;
690  ShaderNodeSet scheduled;
691  queue<ShaderNode *> traverse_queue;
692  /* Schedule volume output. */
693  traverse_queue.push(volume_in->link->parent);
694  scheduled.insert(volume_in->link->parent);
695  /* Traverse down the tree. */
696  while (!traverse_queue.empty()) {
697  ShaderNode *node = traverse_queue.front();
698  traverse_queue.pop();
699  /* Node is fully valid for volume, can't optimize anything out. */
700  if (node->has_volume_support()) {
701  has_valid_volume = true;
702  break;
703  }
704  foreach (ShaderInput *input, node->inputs) {
705  if (input->link == NULL) {
706  continue;
707  }
708  if (scheduled.find(input->link->parent) != scheduled.end()) {
709  continue;
710  }
711  traverse_queue.push(input->link->parent);
712  scheduled.insert(input->link->parent);
713  }
714  }
715  if (!has_valid_volume) {
716  VLOG(1) << "Disconnect meaningless volume output.";
717  disconnect(volume_in->link);
718  }
719 }
720 
722 {
723  visited[node->id] = true;
724  on_stack[node->id] = true;
725 
726  foreach (ShaderInput *input, node->inputs) {
727  if (input->link) {
728  ShaderNode *depnode = input->link->parent;
729 
730  if (on_stack[depnode->id]) {
731  /* break cycle */
732  disconnect(input);
733  fprintf(stderr, "Cycles shader graph: detected cycle in graph, connection removed.\n");
734  }
735  else if (!visited[depnode->id]) {
736  /* visit dependencies */
737  break_cycles(depnode, visited, on_stack);
738  }
739  }
740  }
741 
742  on_stack[node->id] = false;
743 }
744 
746 {
747  /* Compute hash of all nodes linked to displacement, to detect if we need
748  * to recompute displacement when shader nodes change. */
749  ShaderInput *displacement_in = output()->input("Displacement");
750 
751  if (!displacement_in->link) {
752  displacement_hash = "";
753  return;
754  }
755 
756  ShaderNodeSet nodes_displace;
757  find_dependencies(nodes_displace, displacement_in);
758 
759  MD5Hash md5;
760  foreach (ShaderNode *node, nodes_displace) {
761  node->hash(md5);
762  foreach (ShaderInput *input, node->inputs) {
763  int link_id = (input->link) ? input->link->parent->id : 0;
764  md5.append((uint8_t *)&link_id, sizeof(link_id));
765  md5.append((input->link) ? input->link->name().c_str() : "");
766  }
767 
768  if (node->special_type == SHADER_SPECIAL_TYPE_OSL) {
769  /* Hash takes into account socket values, to detect changes
770  * in the code of the node we need an exception. */
771  OSLNode *oslnode = static_cast<OSLNode *>(node);
772  md5.append(oslnode->bytecode_hash);
773  }
774  }
775 
776  displacement_hash = md5.get_hex();
777 }
778 
780 {
781  /* Graph simplification */
782 
783  /* NOTE: Remove proxy nodes was already done. */
788 
789  /* we do two things here: find cycles and break them, and remove unused
790  * nodes that don't feed into the output. how cycles are broken is
791  * undefined, they are invalid input, the important thing is to not crash */
792 
794  vector<bool> on_stack(num_node_ids, false);
795 
796  /* break cycles */
797  break_cycles(output(), visited, on_stack);
798  foreach (ShaderNode *node, nodes) {
799  if (node->special_type == SHADER_SPECIAL_TYPE_OUTPUT_AOV) {
800  break_cycles(node, visited, on_stack);
801  }
802  }
803 
804  /* disconnect unused nodes */
805  foreach (ShaderNode *node, nodes) {
806  if (!visited[node->id]) {
807  foreach (ShaderInput *to, node->inputs) {
808  ShaderOutput *from = to->link;
809 
810  if (from) {
811  to->link = NULL;
812  from->links.erase(remove(from->links.begin(), from->links.end(), to), from->links.end());
813  }
814  }
815  }
816  }
817 
818  /* remove unused nodes */
819  list<ShaderNode *> newnodes;
820 
821  foreach (ShaderNode *node, nodes) {
822  if (visited[node->id])
823  newnodes.push_back(node);
824  else
825  delete_node(node);
826  }
827 
828  nodes = newnodes;
829 }
830 
832 {
833  /* Call expand on all nodes, to generate additional nodes. */
834  foreach (ShaderNode *node, nodes) {
835  node->expand(this);
836  }
837 }
838 
840 {
841  /* nodes can specify default texture coordinates, for now we give
842  * everything the position by default, except for the sky texture */
843 
844  ShaderNode *geom = NULL;
845  ShaderNode *texco = NULL;
846 
847  foreach (ShaderNode *node, nodes) {
848  foreach (ShaderInput *input, node->inputs) {
849  if (!input->link && (!(input->flags() & SocketType::OSL_INTERNAL) || do_osl)) {
850  if (input->flags() & SocketType::LINK_TEXTURE_GENERATED) {
851  if (!texco)
852  texco = create_node<TextureCoordinateNode>();
853 
854  connect(texco->output("Generated"), input);
855  }
856  if (input->flags() & SocketType::LINK_TEXTURE_NORMAL) {
857  if (!texco)
858  texco = create_node<TextureCoordinateNode>();
859 
860  connect(texco->output("Normal"), input);
861  }
862  else if (input->flags() & SocketType::LINK_TEXTURE_UV) {
863  if (!texco)
864  texco = create_node<TextureCoordinateNode>();
865 
866  connect(texco->output("UV"), input);
867  }
868  else if (input->flags() & SocketType::LINK_INCOMING) {
869  if (!geom)
870  geom = create_node<GeometryNode>();
871 
872  connect(geom->output("Incoming"), input);
873  }
874  else if (input->flags() & SocketType::LINK_NORMAL) {
875  if (!geom)
876  geom = create_node<GeometryNode>();
877 
878  connect(geom->output("Normal"), input);
879  }
880  else if (input->flags() & SocketType::LINK_POSITION) {
881  if (!geom)
882  geom = create_node<GeometryNode>();
883 
884  connect(geom->output("Position"), input);
885  }
886  else if (input->flags() & SocketType::LINK_TANGENT) {
887  if (!geom)
888  geom = create_node<GeometryNode>();
889 
890  connect(geom->output("Tangent"), input);
891  }
892  }
893  }
894  }
895 
896  if (geom)
897  add(geom);
898  if (texco)
899  add(texco);
900 }
901 
903 {
904  /* we transverse the node graph looking for bump nodes, when we find them,
905  * like in bump_from_displacement(), we copy the sub-graph defined from "bump"
906  * input to the inputs "center","dx" and "dy" What is in "bump" input is moved
907  * to "center" input. */
908 
909  foreach (ShaderNode *node, nodes) {
910  if (node->special_type == SHADER_SPECIAL_TYPE_BUMP && node->input("Height")->link) {
911  ShaderInput *bump_input = node->input("Height");
912  ShaderNodeSet nodes_bump;
913 
914  /* make 2 extra copies of the subgraph defined in Bump input */
915  ShaderNodeMap nodes_dx;
916  ShaderNodeMap nodes_dy;
917 
918  /* find dependencies for the given input */
919  find_dependencies(nodes_bump, bump_input);
920 
921  copy_nodes(nodes_bump, nodes_dx);
922  copy_nodes(nodes_bump, nodes_dy);
923 
924  /* mark nodes to indicate they are use for bump computation, so
925  that any texture coordinates are shifted by dx/dy when sampling */
926  foreach (ShaderNode *node, nodes_bump)
927  node->bump = SHADER_BUMP_CENTER;
928  foreach (NodePair &pair, nodes_dx)
929  pair.second->bump = SHADER_BUMP_DX;
930  foreach (NodePair &pair, nodes_dy)
931  pair.second->bump = SHADER_BUMP_DY;
932 
933  ShaderOutput *out = bump_input->link;
934  ShaderOutput *out_dx = nodes_dx[out->parent]->output(out->name());
935  ShaderOutput *out_dy = nodes_dy[out->parent]->output(out->name());
936 
937  connect(out_dx, node->input("SampleX"));
938  connect(out_dy, node->input("SampleY"));
939 
940  /* add generated nodes */
941  foreach (NodePair &pair, nodes_dx)
942  add(pair.second);
943  foreach (NodePair &pair, nodes_dy)
944  add(pair.second);
945 
946  /* Connect what is connected is bump to sample-center input. */
947  connect(out, node->input("SampleCenter"));
948 
949  /* Bump input is just for connectivity purpose for the graph input,
950  * we re-connected this input to sample-center, so lets disconnect it
951  * from bump input. */
952  disconnect(bump_input);
953  }
954  }
955 }
956 
957 void ShaderGraph::bump_from_displacement(bool use_object_space)
958 {
959  /* generate bump mapping automatically from displacement. bump mapping is
960  * done using a 3-tap filter, computing the displacement at the center,
961  * and two other positions shifted by ray differentials.
962  *
963  * since the input to displacement is a node graph, we need to ensure that
964  * all texture coordinates use are shift by the ray differentials. for this
965  * reason we make 3 copies of the node subgraph defining the displacement,
966  * with each different geometry and texture coordinate nodes that generate
967  * different shifted coordinates.
968  *
969  * these 3 displacement values are then fed into the bump node, which will
970  * output the perturbed normal. */
971 
972  ShaderInput *displacement_in = output()->input("Displacement");
973 
974  if (!displacement_in->link)
975  return;
976 
977  /* find dependencies for the given input */
978  ShaderNodeSet nodes_displace;
979  find_dependencies(nodes_displace, displacement_in);
980 
981  /* copy nodes for 3 bump samples */
982  ShaderNodeMap nodes_center;
983  ShaderNodeMap nodes_dx;
984  ShaderNodeMap nodes_dy;
985 
986  copy_nodes(nodes_displace, nodes_center);
987  copy_nodes(nodes_displace, nodes_dx);
988  copy_nodes(nodes_displace, nodes_dy);
989 
990  /* mark nodes to indicate they are use for bump computation, so
991  * that any texture coordinates are shifted by dx/dy when sampling */
992  foreach (NodePair &pair, nodes_center)
993  pair.second->bump = SHADER_BUMP_CENTER;
994  foreach (NodePair &pair, nodes_dx)
995  pair.second->bump = SHADER_BUMP_DX;
996  foreach (NodePair &pair, nodes_dy)
997  pair.second->bump = SHADER_BUMP_DY;
998 
999  /* add set normal node and connect the bump normal output to the set normal
1000  * output, so it can finally set the shader normal, note we are only doing
1001  * this for bump from displacement, this will be the only bump allowed to
1002  * overwrite the shader normal */
1003  ShaderNode *set_normal = add(create_node<SetNormalNode>());
1004 
1005  /* add bump node and connect copied graphs to it */
1006  BumpNode *bump = (BumpNode *)add(create_node<BumpNode>());
1007  bump->set_use_object_space(use_object_space);
1008  bump->set_distance(1.0f);
1009 
1010  ShaderOutput *out = displacement_in->link;
1011  ShaderOutput *out_center = nodes_center[out->parent]->output(out->name());
1012  ShaderOutput *out_dx = nodes_dx[out->parent]->output(out->name());
1013  ShaderOutput *out_dy = nodes_dy[out->parent]->output(out->name());
1014 
1015  /* convert displacement vector to height */
1016  VectorMathNode *dot_center = (VectorMathNode *)add(create_node<VectorMathNode>());
1017  VectorMathNode *dot_dx = (VectorMathNode *)add(create_node<VectorMathNode>());
1018  VectorMathNode *dot_dy = (VectorMathNode *)add(create_node<VectorMathNode>());
1019 
1020  dot_center->set_math_type(NODE_VECTOR_MATH_DOT_PRODUCT);
1021  dot_dx->set_math_type(NODE_VECTOR_MATH_DOT_PRODUCT);
1022  dot_dy->set_math_type(NODE_VECTOR_MATH_DOT_PRODUCT);
1023 
1024  GeometryNode *geom = (GeometryNode *)add(create_node<GeometryNode>());
1025  connect(geom->output("Normal"), dot_center->input("Vector2"));
1026  connect(geom->output("Normal"), dot_dx->input("Vector2"));
1027  connect(geom->output("Normal"), dot_dy->input("Vector2"));
1028 
1029  connect(out_center, dot_center->input("Vector1"));
1030  connect(out_dx, dot_dx->input("Vector1"));
1031  connect(out_dy, dot_dy->input("Vector1"));
1032 
1033  connect(dot_center->output("Value"), bump->input("SampleCenter"));
1034  connect(dot_dx->output("Value"), bump->input("SampleX"));
1035  connect(dot_dy->output("Value"), bump->input("SampleY"));
1036 
1037  /* connect the bump out to the set normal in: */
1038  connect(bump->output("Normal"), set_normal->input("Direction"));
1039 
1040  /* connect to output node */
1041  connect(set_normal->output("Normal"), output()->input("Normal"));
1042 
1043  /* finally, add the copied nodes to the graph. we can't do this earlier
1044  * because we would create dependency cycles in the above loop */
1045  foreach (NodePair &pair, nodes_center)
1046  add(pair.second);
1047  foreach (NodePair &pair, nodes_dx)
1048  add(pair.second);
1049  foreach (NodePair &pair, nodes_dy)
1050  add(pair.second);
1051 }
1052 
1054 {
1055  /* for SVM in multi closure mode, this transforms the shader mix/add part of
1056  * the graph into nodes that feed weights into closure nodes. this is too
1057  * avoid building a closure tree and then flattening it, and instead write it
1058  * directly to an array */
1059 
1060  if (node->special_type == SHADER_SPECIAL_TYPE_COMBINE_CLOSURE) {
1061  ShaderInput *fin = node->input("Fac");
1062  ShaderInput *cl1in = node->input("Closure1");
1063  ShaderInput *cl2in = node->input("Closure2");
1064  ShaderOutput *weight1_out, *weight2_out;
1065 
1066  if (fin) {
1067  /* mix closure: add node to mix closure weights */
1068  MixClosureWeightNode *mix_node = create_node<MixClosureWeightNode>();
1069  add(mix_node);
1070  ShaderInput *fac_in = mix_node->input("Fac");
1071  ShaderInput *weight_in = mix_node->input("Weight");
1072 
1073  if (fin->link)
1074  connect(fin->link, fac_in);
1075  else
1076  mix_node->set_fac(node->get_float(fin->socket_type));
1077 
1078  if (weight_out)
1079  connect(weight_out, weight_in);
1080 
1081  weight1_out = mix_node->output("Weight1");
1082  weight2_out = mix_node->output("Weight2");
1083  }
1084  else {
1085  /* add closure: just pass on any weights */
1086  weight1_out = weight_out;
1087  weight2_out = weight_out;
1088  }
1089 
1090  if (cl1in->link)
1091  transform_multi_closure(cl1in->link->parent, weight1_out, volume);
1092  if (cl2in->link)
1093  transform_multi_closure(cl2in->link->parent, weight2_out, volume);
1094  }
1095  else {
1096  ShaderInput *weight_in = node->input((volume) ? "VolumeMixWeight" : "SurfaceMixWeight");
1097 
1098  /* not a closure node? */
1099  if (!weight_in)
1100  return;
1101 
1102  /* already has a weight connected to it? add weights */
1103  float weight_value = node->get_float(weight_in->socket_type);
1104  if (weight_in->link || weight_value != 0.0f) {
1105  MathNode *math_node = create_node<MathNode>();
1106  add(math_node);
1107 
1108  if (weight_in->link)
1109  connect(weight_in->link, math_node->input("Value1"));
1110  else
1111  math_node->set_value1(weight_value);
1112 
1113  if (weight_out)
1114  connect(weight_out, math_node->input("Value2"));
1115  else
1116  math_node->set_value2(1.0f);
1117 
1118  weight_out = math_node->output("Value");
1119  if (weight_in->link)
1120  disconnect(weight_in);
1121  }
1122 
1123  /* connected to closure mix weight */
1124  if (weight_out)
1125  connect(weight_out, weight_in);
1126  else
1127  node->set(weight_in->socket_type, weight_value + 1.0f);
1128  }
1129 }
1130 
1132 {
1133  int num_closures = 0;
1134  foreach (ShaderNode *node, nodes) {
1135  ClosureType closure_type = node->get_closure_type();
1136  if (closure_type == CLOSURE_NONE_ID) {
1137  continue;
1138  }
1139  else if (CLOSURE_IS_BSSRDF(closure_type)) {
1140  num_closures += 3;
1141  }
1142  else if (CLOSURE_IS_GLASS(closure_type)) {
1143  num_closures += 2;
1144  }
1145  else if (CLOSURE_IS_BSDF_MULTISCATTER(closure_type)) {
1146  num_closures += 2;
1147  }
1148  else if (CLOSURE_IS_PRINCIPLED(closure_type)) {
1149  num_closures += 8;
1150  }
1151  else if (CLOSURE_IS_VOLUME(closure_type)) {
1152  num_closures += VOLUME_STACK_SIZE;
1153  }
1154  else if (closure_type == CLOSURE_BSDF_HAIR_PRINCIPLED_ID) {
1155  num_closures += 4;
1156  }
1157  else {
1158  ++num_closures;
1159  }
1160  }
1161  return num_closures;
1162 }
1163 
1164 void ShaderGraph::dump_graph(const char *filename)
1165 {
1166  FILE *fd = fopen(filename, "w");
1167 
1168  if (fd == NULL) {
1169  printf("Error opening file for dumping the graph: %s\n", filename);
1170  return;
1171  }
1172 
1173  fprintf(fd, "digraph shader_graph {\n");
1174  fprintf(fd, "ranksep=1.5\n");
1175  fprintf(fd, "rankdir=LR\n");
1176  fprintf(fd, "splines=false\n");
1177 
1178  foreach (ShaderNode *node, nodes) {
1179  fprintf(fd, "// NODE: %p\n", node);
1180  fprintf(fd, "\"%p\" [shape=record,label=\"{", node);
1181  if (node->inputs.size()) {
1182  fprintf(fd, "{");
1183  foreach (ShaderInput *socket, node->inputs) {
1184  if (socket != node->inputs[0]) {
1185  fprintf(fd, "|");
1186  }
1187  fprintf(fd, "<IN_%p>%s", socket, socket->name().c_str());
1188  }
1189  fprintf(fd, "}|");
1190  }
1191  fprintf(fd, "%s", node->name.c_str());
1192  if (node->bump == SHADER_BUMP_CENTER) {
1193  fprintf(fd, " (bump:center)");
1194  }
1195  else if (node->bump == SHADER_BUMP_DX) {
1196  fprintf(fd, " (bump:dx)");
1197  }
1198  else if (node->bump == SHADER_BUMP_DY) {
1199  fprintf(fd, " (bump:dy)");
1200  }
1201  if (node->outputs.size()) {
1202  fprintf(fd, "|{");
1203  foreach (ShaderOutput *socket, node->outputs) {
1204  if (socket != node->outputs[0]) {
1205  fprintf(fd, "|");
1206  }
1207  fprintf(fd, "<OUT_%p>%s", socket, socket->name().c_str());
1208  }
1209  fprintf(fd, "}");
1210  }
1211  fprintf(fd, "}\"]");
1212  }
1213 
1214  foreach (ShaderNode *node, nodes) {
1215  foreach (ShaderOutput *output, node->outputs) {
1216  foreach (ShaderInput *input, output->links) {
1217  fprintf(fd,
1218  "// CONNECTION: OUT_%p->IN_%p (%s:%s)\n",
1219  output,
1220  input,
1221  output->name().c_str(),
1222  input->name().c_str());
1223  fprintf(fd,
1224  "\"%p\":\"OUT_%p\":e -> \"%p\":\"IN_%p\":w [label=\"\"]\n",
1225  output->parent,
1226  output,
1227  input->parent,
1228  input);
1229  }
1230  }
1231  }
1232 
1233  fprintf(fd, "}\n");
1234  fclose(fd);
1235 }
1236 
@ NODE_VECTOR_MATH_DOT_PRODUCT
_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
string get_hex()
Definition: util_md5.cpp:366
void append(const uint8_t *data, int size)
Definition: util_md5.cpp:274
string bytecode_hash
Definition: nodes.h:1644
void find_dependencies(ShaderNodeSet &dependencies, ShaderInput *input)
Definition: graph.cpp:403
bool finalized
Definition: graph.h:319
string displacement_hash
Definition: graph.h:321
list< ShaderNode * > nodes
Definition: graph.h:317
OutputNode * output()
Definition: graph.cpp:242
void verify_volume_output()
Definition: graph.cpp:682
void simplify(Scene *scene)
Definition: graph.cpp:361
void disconnect(ShaderOutput *from)
Definition: graph.cpp:302
void delete_node(T *node)
Definition: graph.h:360
size_t num_node_ids
Definition: graph.h:318
~ShaderGraph()
Definition: graph.cpp:227
void break_cycles(ShaderNode *node, vector< bool > &visited, vector< bool > &on_stack)
Definition: graph.cpp:721
void copy_nodes(ShaderNodeSet &nodes, ShaderNodeMap &nnodemap)
Definition: graph.cpp:424
void clean(Scene *scene)
Definition: graph.cpp:779
ShaderGraph()
Definition: graph.cpp:219
pair< ShaderNode *const, ShaderNode * > NodePair
Definition: graph.h:367
void compute_displacement_hash()
Definition: graph.cpp:745
void default_inputs(bool do_osl)
Definition: graph.cpp:839
void expand()
Definition: graph.cpp:831
void connect(ShaderOutput *from, ShaderInput *to)
Definition: graph.cpp:247
void relink(ShaderInput *from, ShaderInput *to)
Definition: graph.cpp:319
void clear_nodes()
Definition: graph.cpp:416
void constant_fold(Scene *scene)
Definition: graph.cpp:538
bool simplified
Definition: graph.h:320
void transform_multi_closure(ShaderNode *node, ShaderOutput *weight_out, bool volume)
Definition: graph.cpp:1053
void deduplicate_nodes()
Definition: graph.cpp:604
void remove_proxy_nodes()
Definition: graph.cpp:467
void simplify_settings(Scene *scene)
Definition: graph.cpp:596
void bump_from_displacement(bool use_object_space)
Definition: graph.cpp:957
int get_num_closures()
Definition: graph.cpp:1131
void finalize(Scene *scene, bool do_bump=false, bool do_simplify=false, bool bump_in_object_space=false)
Definition: graph.cpp:373
ShaderNode * add(ShaderNode *node)
Definition: graph.cpp:232
void refine_bump_nodes()
Definition: graph.cpp:902
void dump_graph(const char *filename)
Definition: graph.cpp:1164
ShaderOutput * link
Definition: graph.h:112
void disconnect()
Definition: graph.cpp:60
ShaderNode * parent
Definition: graph.h:111
SocketType::Type type()
Definition: graph.h:94
int flags()
Definition: graph.h:90
ustring name()
Definition: graph.h:86
const SocketType & socket_type
Definition: graph.h:110
virtual bool use_osl()
Definition: shader.h:184
ShaderInput * input(const char *name)
Definition: graph.cpp:111
vector< ShaderOutput * > outputs
Definition: graph.h:224
void remove_input(ShaderInput *input)
Definition: graph.cpp:149
int id
Definition: graph.h:226
ShaderNodeSpecialType special_type
Definition: graph.h:229
vector< ShaderInput * > inputs
Definition: graph.h:223
virtual ~ShaderNode()
Definition: graph.cpp:89
virtual bool equals(const ShaderNode &other)
Definition: graph.cpp:174
ShaderNode(const NodeType *type)
Definition: graph.cpp:79
void create_inputs_outputs(const NodeType *type)
Definition: graph.cpp:98
ShaderBump bump
Definition: graph.h:227
ShaderOutput * output(const char *name)
Definition: graph.cpp:121
virtual void attributes(Shader *shader, AttributeRequestSet *attributes)
Definition: graph.cpp:156
ustring name()
Definition: graph.h:127
vector< ShaderInput * > links
Definition: graph.h:140
void disconnect()
Definition: graph.cpp:68
ShaderNode * parent
Definition: graph.h:139
Definition: shader.h:80
OperationNode * node
StackEntry * from
Scene scene
Set< ComponentNode * > visited
@ SHADER_SPECIAL_TYPE_PROXY
Definition: graph.h:61
@ SHADER_SPECIAL_TYPE_OUTPUT_AOV
Definition: graph.h:70
@ SHADER_SPECIAL_TYPE_COMBINE_CLOSURE
Definition: graph.h:67
@ SHADER_SPECIAL_TYPE_BUMP
Definition: graph.h:69
@ SHADER_SPECIAL_TYPE_AUTOCONVERT
Definition: graph.h:62
@ SHADER_SPECIAL_TYPE_NONE
Definition: graph.h:60
@ SHADER_SPECIAL_TYPE_OSL
Definition: graph.h:64
set< ShaderNode *, ShaderNodeIDComparator > ShaderNodeSet
Definition: graph.h:307
@ SHADER_BUMP_CENTER
Definition: graph.h:52
@ SHADER_BUMP_DX
Definition: graph.h:52
@ SHADER_BUMP_DY
Definition: graph.h:52
@ SHADER_BUMP_NONE
Definition: graph.h:52
map< ShaderNode *, ShaderNode *, ShaderNodeIDComparator > ShaderNodeMap
Definition: graph.h:308
#define CCL_NAMESPACE_END
void KERNEL_FUNCTION_FULL_NAME() shader(KernelGlobals *kg, uint4 *input, float4 *output, int type, int filter, int i, int offset, int sample)
@ ATTR_STD_GENERATED_TRANSFORM
Definition: kernel_types.h:753
@ ATTR_STD_UV
Definition: kernel_types.h:748
@ ATTR_STD_GENERATED
Definition: kernel_types.h:752
#define VOLUME_STACK_SIZE
Definition: kernel_types.h:64
bool check_node_inputs_traversed(const ShaderNode *node, const ShaderNodeSet &done)
Definition: graph.cpp:44
bool check_node_inputs_has_links(const ShaderNode *node)
Definition: graph.cpp:34
uint convert(uint c, uint inbits, uint outbits)
Definition: PixelFormat.h:59
struct blender::gpu::ShaderInput ShaderInput
static bNodeSocketTemplate outputs[]
unsigned char uint8_t
Definition: stdint.h:81
vector< SocketType, std::allocator< SocketType > > inputs
Definition: node_type.h:131
ustring name
Definition: node_type.h:128
vector< SocketType, std::allocator< SocketType > > outputs
Definition: node_type.h:132
Definition: node.h:98
const NodeType * type
Definition: node.h:175
void set_value(const SocketType &input, const Node &other, const SocketType &other_input)
Definition: node.cpp:385
void copy_value(const SocketType &input, const Node &other, const SocketType &other_input)
Definition: node.cpp:334
ustring name
Definition: node.h:174
bool equals_value(const Node &other, const SocketType &input) const
Definition: node.cpp:482
ShaderManager * shader_manager
Definition: scene.h:245
@ LINK_TEXTURE_UV
Definition: node_type.h:77
@ LINK_NORMAL
Definition: node_type.h:79
@ LINK_TEXTURE_GENERATED
Definition: node_type.h:75
@ OSL_INTERNAL
Definition: node_type.h:72
@ LINK_TANGENT
Definition: node_type.h:81
@ LINK_INCOMING
Definition: node_type.h:78
@ LINK_TEXTURE_NORMAL
Definition: node_type.h:76
@ DEFAULT_LINK_MASK
Definition: node_type.h:82
@ LINK_POSITION
Definition: node_type.h:80
int flags
Definition: node_type.h:91
#define CLOSURE_IS_GLASS(type)
Definition: svm_types.h:633
#define CLOSURE_IS_VOLUME(type)
Definition: svm_types.h:627
#define CLOSURE_IS_PRINCIPLED(type)
Definition: svm_types.h:635
ClosureType
Definition: svm_types.h:527
@ CLOSURE_BSDF_HAIR_PRINCIPLED_ID
Definition: svm_types.h:565
@ CLOSURE_NONE_ID
Definition: svm_types.h:529
#define CLOSURE_IS_BSSRDF(type)
Definition: svm_types.h:623
#define CLOSURE_IS_BSDF_MULTISCATTER(type)
Definition: svm_types.h:609
#define VLOG(severity)
Definition: util_logging.h:50
ccl_device_inline float3 one_float3()