Blender  V3.3
node_shader_tree.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2007 Blender Foundation. All rights reserved. */
3 
8 #include <cstring>
9 
10 #include "DNA_light_types.h"
11 #include "DNA_linestyle_types.h"
12 #include "DNA_material_types.h"
13 #include "DNA_node_types.h"
14 #include "DNA_scene_types.h"
15 #include "DNA_space_types.h"
16 #include "DNA_workspace_types.h"
17 #include "DNA_world_types.h"
18 
19 #include "BLI_array.hh"
20 #include "BLI_linklist.h"
21 #include "BLI_listbase.h"
22 #include "BLI_threads.h"
23 #include "BLI_utildefines.h"
24 #include "BLI_vector.hh"
25 
26 #include "BLT_translation.h"
27 
28 #include "BKE_context.h"
29 #include "BKE_lib_id.h"
30 #include "BKE_linestyle.h"
31 #include "BKE_node.h"
32 #include "BKE_node_tree_update.h"
33 #include "BKE_scene.h"
34 
35 #include "RNA_access.h"
36 #include "RNA_prototypes.h"
37 
38 #include "GPU_material.h"
39 
40 #include "RE_texture.h"
41 
42 #include "UI_resources.h"
43 
44 #include "NOD_common.h"
45 
46 #include "node_common.h"
47 #include "node_exec.h"
48 #include "node_shader_util.hh"
49 #include "node_util.h"
50 
51 using blender::Array;
52 using blender::Vector;
53 
54 static bool shader_tree_poll(const bContext *C, bNodeTreeType *UNUSED(treetype))
55 {
57  const char *engine_id = scene->r.engine;
58 
59  /* Allow empty engine string too,
60  * this is from older versions that didn't have registerable engines yet. */
61  return (engine_id[0] == '\0' || STREQ(engine_id, RE_engine_id_CYCLES) ||
63 }
64 
65 static void shader_get_from_context(const bContext *C,
66  bNodeTreeType *UNUSED(treetype),
67  bNodeTree **r_ntree,
68  ID **r_id,
69  ID **r_from)
70 {
71  SpaceNode *snode = CTX_wm_space_node(C);
73  ViewLayer *view_layer = CTX_data_view_layer(C);
74  Object *ob = OBACT(view_layer);
75 
76  if (snode->shaderfrom == SNODE_SHADER_OBJECT) {
77  if (ob) {
78  *r_from = &ob->id;
79  if (ob->type == OB_LAMP) {
80  *r_id = static_cast<ID *>(ob->data);
81  *r_ntree = ((Light *)ob->data)->nodetree;
82  }
83  else {
85  if (ma) {
86  *r_id = &ma->id;
87  *r_ntree = ma->nodetree;
88  }
89  }
90  }
91  }
92 #ifdef WITH_FREESTYLE
93  else if (snode->shaderfrom == SNODE_SHADER_LINESTYLE) {
95  if (linestyle) {
96  *r_from = nullptr;
97  *r_id = &linestyle->id;
98  *r_ntree = linestyle->nodetree;
99  }
100  }
101 #endif
102  else { /* SNODE_SHADER_WORLD */
103  if (scene->world) {
104  *r_from = nullptr;
105  *r_id = &scene->world->id;
106  *r_ntree = scene->world->nodetree;
107  }
108  }
109 }
110 
111 static void foreach_nodeclass(Scene *UNUSED(scene), void *calldata, bNodeClassCallback func)
112 {
113  func(calldata, NODE_CLASS_INPUT, N_("Input"));
114  func(calldata, NODE_CLASS_OUTPUT, N_("Output"));
115  func(calldata, NODE_CLASS_SHADER, N_("Shader"));
116  func(calldata, NODE_CLASS_TEXTURE, N_("Texture"));
117  func(calldata, NODE_CLASS_OP_COLOR, N_("Color"));
118  func(calldata, NODE_CLASS_OP_VECTOR, N_("Vector"));
119  func(calldata, NODE_CLASS_CONVERTER, N_("Converter"));
120  func(calldata, NODE_CLASS_SCRIPT, N_("Script"));
121  func(calldata, NODE_CLASS_GROUP, N_("Group"));
122  func(calldata, NODE_CLASS_INTERFACE, N_("Interface"));
123  func(calldata, NODE_CLASS_LAYOUT, N_("Layout"));
124 }
125 
126 static void localize(bNodeTree *localtree, bNodeTree *UNUSED(ntree))
127 {
128  /* replace muted nodes and reroute nodes by internal links */
129  LISTBASE_FOREACH_MUTABLE (bNode *, node, &localtree->nodes) {
130  if (node->flag & NODE_MUTED || node->type == NODE_REROUTE) {
131  nodeInternalRelink(localtree, node);
132  ntreeFreeLocalNode(localtree, node);
133  }
134  }
135 }
136 
137 static void update(bNodeTree *ntree)
138 {
140 
142 }
143 
145 {
146  /* Can't connect shader into other socket types, other way around is fine
147  * since it will be interpreted as emission. */
148  if (from == SOCK_SHADER) {
149  return to == SOCK_SHADER;
150  }
151  return true;
152 }
153 
155  bNodeSocketType *socket_type)
156 {
157  return nodeIsStaticSocketType(socket_type) &&
159 }
160 
162 
164 {
165  bNodeTreeType *tt = ntreeType_Shader = MEM_cnew<bNodeTreeType>("shader node tree type");
166 
167  tt->type = NTREE_SHADER;
168  strcpy(tt->idname, "ShaderNodeTree");
169  strcpy(tt->ui_name, N_("Shader Editor"));
170  tt->ui_icon = ICON_NODE_MATERIAL;
171  strcpy(tt->ui_description, N_("Shader nodes"));
172 
174  tt->localize = localize;
175  tt->update = update;
176  tt->poll = shader_tree_poll;
180 
181  tt->rna_ext.srna = &RNA_ShaderNodeTree;
182 
183  ntreeTypeAdd(tt);
184 }
185 
186 /* GPU material from shader nodes */
187 
189 {
190  /* Make sure we only have single node tagged as output. */
192 
193  /* Find output node that matches type and target. If there are
194  * multiple, we prefer exact target match and active nodes. */
195  bNode *output_node = nullptr;
196 
199  continue;
200  }
201 
202  if (node->custom1 == SHD_OUTPUT_ALL) {
203  if (output_node == nullptr) {
204  output_node = node;
205  }
206  else if (output_node->custom1 == SHD_OUTPUT_ALL) {
207  if ((node->flag & NODE_DO_OUTPUT) && !(output_node->flag & NODE_DO_OUTPUT)) {
208  output_node = node;
209  }
210  }
211  }
212  else if (node->custom1 == target) {
213  if (output_node == nullptr) {
214  output_node = node;
215  }
216  else if (output_node->custom1 == SHD_OUTPUT_ALL) {
217  output_node = node;
218  }
219  else if ((node->flag & NODE_DO_OUTPUT) && !(output_node->flag & NODE_DO_OUTPUT)) {
220  output_node = node;
221  }
222  }
223  }
224 
225  return output_node;
226 }
227 
228 /* Find socket with a specified identifier. */
229 static bNodeSocket *ntree_shader_node_find_socket(ListBase *sockets, const char *identifier)
230 {
231  LISTBASE_FOREACH (bNodeSocket *, sock, sockets) {
232  if (STREQ(sock->identifier, identifier)) {
233  return sock;
234  }
235  }
236  return nullptr;
237 }
238 
239 /* Find input socket with a specified identifier. */
240 static bNodeSocket *ntree_shader_node_find_input(bNode *node, const char *identifier)
241 {
242  return ntree_shader_node_find_socket(&node->inputs, identifier);
243 }
244 
245 /* Find output socket with a specified identifier. */
246 static bNodeSocket *ntree_shader_node_find_output(bNode *node, const char *identifier)
247 {
248  return ntree_shader_node_find_socket(&node->outputs, identifier);
249 }
250 
251 /* Find input socket at a specific position. */
253 {
254  return reinterpret_cast<bNodeSocket *>(BLI_findlink(&node->inputs, n));
255 }
256 
257 /* Find output socket at a specific position. */
259 {
260  return reinterpret_cast<bNodeSocket *>(BLI_findlink(&node->outputs, n));
261 }
262 
263 /* Return true on success. */
265  bNode *node,
266  bNodeSocket *socket)
267 {
268  bNode *value_node;
269  bNodeSocket *value_socket;
270  bNodeSocketValueVector *src_vector;
271  bNodeSocketValueRGBA *src_rgba, *dst_rgba;
272  bNodeSocketValueFloat *src_float, *dst_float;
273  bNodeSocketValueInt *src_int;
274 
275  switch (socket->type) {
276  case SOCK_VECTOR:
277  value_node = nodeAddStaticNode(nullptr, localtree, SH_NODE_RGB);
278  value_socket = ntree_shader_node_find_output(value_node, "Color");
279  BLI_assert(value_socket != nullptr);
280  src_vector = static_cast<bNodeSocketValueVector *>(socket->default_value);
281  dst_rgba = static_cast<bNodeSocketValueRGBA *>(value_socket->default_value);
282  copy_v3_v3(dst_rgba->value, src_vector->value);
283  dst_rgba->value[3] = 1.0f; /* should never be read */
284  break;
285  case SOCK_RGBA:
286  value_node = nodeAddStaticNode(nullptr, localtree, SH_NODE_RGB);
287  value_socket = ntree_shader_node_find_output(value_node, "Color");
288  BLI_assert(value_socket != nullptr);
289  src_rgba = static_cast<bNodeSocketValueRGBA *>(socket->default_value);
290  dst_rgba = static_cast<bNodeSocketValueRGBA *>(value_socket->default_value);
291  copy_v4_v4(dst_rgba->value, src_rgba->value);
292  break;
293  case SOCK_INT:
294  /* HACK: Support as float. */
295  value_node = nodeAddStaticNode(nullptr, localtree, SH_NODE_VALUE);
296  value_socket = ntree_shader_node_find_output(value_node, "Value");
297  BLI_assert(value_socket != nullptr);
298  src_int = static_cast<bNodeSocketValueInt *>(socket->default_value);
299  dst_float = static_cast<bNodeSocketValueFloat *>(value_socket->default_value);
300  dst_float->value = (float)(src_int->value);
301  break;
302  case SOCK_FLOAT:
303  value_node = nodeAddStaticNode(nullptr, localtree, SH_NODE_VALUE);
304  value_socket = ntree_shader_node_find_output(value_node, "Value");
305  BLI_assert(value_socket != nullptr);
306  src_float = static_cast<bNodeSocketValueFloat *>(socket->default_value);
307  dst_float = static_cast<bNodeSocketValueFloat *>(value_socket->default_value);
308  dst_float->value = src_float->value;
309  break;
310  default:
311  return false;
312  }
313  nodeAddLink(localtree, value_node, value_socket, node, socket);
314  return true;
315 }
316 
318 {
319  bNodeTree *group_ntree = (bNodeTree *)group_node->id;
320  bool removed_link = false;
321 
322  LISTBASE_FOREACH (bNode *, node, &group_ntree->nodes) {
323  const bool is_group = ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && (node->id != nullptr);
324 
325  LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
326  if (!is_group && (sock->flag & SOCK_HIDE_VALUE) == 0) {
327  continue;
328  }
329  /* If socket is linked to a group input node and sockets id match. */
330  if (sock && sock->link && sock->link->fromnode->type == NODE_GROUP_INPUT) {
331  if (STREQ(isock->identifier, sock->link->fromsock->identifier)) {
332  if (is_group) {
333  /* Recursively unlink sockets within the nested group. */
335  }
336  else {
337  nodeRemLink(group_ntree, sock->link);
338  removed_link = true;
339  }
340  }
341  }
342  }
343  }
344 
345  if (removed_link) {
346  BKE_ntree_update_main_tree(G.main, group_ntree, nullptr);
347  }
348 }
349 
350 /* Node groups once expanded looses their input sockets values.
351  * To fix this, link value/rgba nodes into the sockets and copy the group sockets values. */
353 {
354  bool link_added = false;
355 
356  LISTBASE_FOREACH (bNode *, node, &localtree->nodes) {
357  const bool is_group = ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && (node->id != nullptr);
358  const bool is_group_output = node->type == NODE_GROUP_OUTPUT && (node->flag & NODE_DO_OUTPUT);
359 
360  if (is_group) {
361  /* Do it recursively. */
363  }
364 
365  if (is_group || is_group_output) {
366  LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) {
367  if (socket->link != nullptr && !(socket->link->flag & NODE_LINK_MUTED)) {
368  bNodeLink *link = socket->link;
369  /* Fix the case where the socket is actually converting the data. (see T71374)
370  * We only do the case of lossy conversion to float. */
371  if ((socket->type == SOCK_FLOAT) && (link->fromsock->type != link->tosock->type)) {
372  if (link->fromsock->type == SOCK_RGBA) {
373  bNode *tmp = nodeAddStaticNode(nullptr, localtree, SH_NODE_RGBTOBW);
374  nodeAddLink(localtree,
375  link->fromnode,
376  link->fromsock,
377  tmp,
378  static_cast<bNodeSocket *>(tmp->inputs.first));
379  nodeAddLink(
380  localtree, tmp, static_cast<bNodeSocket *>(tmp->outputs.first), node, socket);
381  }
382  else if (link->fromsock->type == SOCK_VECTOR) {
383  bNode *tmp = nodeAddStaticNode(nullptr, localtree, SH_NODE_VECTOR_MATH);
385  bNodeSocket *dot_input1 = static_cast<bNodeSocket *>(tmp->inputs.first);
386  bNodeSocket *dot_input2 = static_cast<bNodeSocket *>(dot_input1->next);
387  bNodeSocketValueVector *input2_socket_value = static_cast<bNodeSocketValueVector *>(
388  dot_input2->default_value);
389  copy_v3_fl(input2_socket_value->value, 1.0f / 3.0f);
390  nodeAddLink(localtree, link->fromnode, link->fromsock, tmp, dot_input1);
391  nodeAddLink(
392  localtree, tmp, static_cast<bNodeSocket *>(tmp->outputs.last), node, socket);
393  }
394  }
395  continue;
396  }
397 
398  if (is_group) {
399  /* Detect the case where an input is plugged into a hidden value socket.
400  * In this case we should just remove the link to trigger the socket default override. */
402  }
403 
404  if (ntree_shader_expand_socket_default(localtree, node, socket)) {
405  link_added = true;
406  }
407  }
408  }
409  }
410 
411  if (link_added) {
412  BKE_ntree_update_main_tree(G.main, localtree, nullptr);
413  }
414 }
415 
417 {
419  if (node->type == NODE_GROUP) {
420  if (node->id != nullptr) {
421  ntree_shader_groups_remove_muted_links(reinterpret_cast<bNodeTree *>(node->id));
422  }
423  }
424  }
426  if (link->flag & NODE_LINK_MUTED) {
427  nodeRemLink(ntree, link);
428  }
429  }
430 }
431 
432 static void flatten_group_do(bNodeTree *ntree, bNode *gnode)
433 {
434  LinkNode *group_interface_nodes = nullptr;
435  bNodeTree *ngroup = (bNodeTree *)gnode->id;
436 
437  /* Add the nodes into the ntree */
438  LISTBASE_FOREACH_MUTABLE (bNode *, node, &ngroup->nodes) {
439  /* Remove interface nodes.
440  * This also removes remaining links to and from interface nodes.
441  * We must delay removal since sockets will reference this node. see: T52092 */
443  BLI_linklist_prepend(&group_interface_nodes, node);
444  }
445  /* migrate node */
446  BLI_remlink(&ngroup->nodes, node);
448  /* ensure unique node name in the node tree */
449  /* This is very slow and it has no use for GPU nodetree. (see T70609) */
450  // nodeUniqueName(ntree, node);
451  }
452 
453  /* Save first and last link to iterate over flattened group links. */
454  bNodeLink *glinks_first = static_cast<bNodeLink *>(ntree->links.last);
455 
456  /* Add internal links to the ntree */
457  LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ngroup->links) {
458  BLI_remlink(&ngroup->links, link);
459  BLI_addtail(&ntree->links, link);
460  }
461 
462  bNodeLink *glinks_last = static_cast<bNodeLink *>(ntree->links.last);
463 
464  /* restore external links to and from the gnode */
465  if (glinks_first != nullptr) {
466  /* input links */
467  for (bNodeLink *link = glinks_first->next; link != glinks_last->next; link = link->next) {
468  if (link->fromnode->type == NODE_GROUP_INPUT) {
469  const char *identifier = link->fromsock->identifier;
470  /* find external links to this input */
471  for (bNodeLink *tlink = static_cast<bNodeLink *>(ntree->links.first);
472  tlink != glinks_first->next;
473  tlink = tlink->next) {
474  if (tlink->tonode == gnode && STREQ(tlink->tosock->identifier, identifier)) {
475  nodeAddLink(ntree, tlink->fromnode, tlink->fromsock, link->tonode, link->tosock);
476  }
477  }
478  }
479  }
480  /* Also iterate over the new links to cover passthrough links. */
481  glinks_last = static_cast<bNodeLink *>(ntree->links.last);
482  /* output links */
483  for (bNodeLink *tlink = static_cast<bNodeLink *>(ntree->links.first);
484  tlink != glinks_first->next;
485  tlink = tlink->next) {
486  if (tlink->fromnode == gnode) {
487  const char *identifier = tlink->fromsock->identifier;
488  /* find internal links to this output */
489  for (bNodeLink *link = glinks_first->next; link != glinks_last->next; link = link->next) {
490  /* only use active output node */
491  if (link->tonode->type == NODE_GROUP_OUTPUT && (link->tonode->flag & NODE_DO_OUTPUT)) {
492  if (STREQ(link->tosock->identifier, identifier)) {
493  nodeAddLink(ntree, link->fromnode, link->fromsock, tlink->tonode, tlink->tosock);
494  }
495  }
496  }
497  }
498  }
499  }
500 
501  while (group_interface_nodes) {
502  bNode *node = static_cast<bNode *>(BLI_linklist_pop(&group_interface_nodes));
504  }
505 
507 }
508 
509 /* Flatten group to only have a simple single tree */
510 static void ntree_shader_groups_flatten(bNodeTree *localtree)
511 {
512  /* This is effectively recursive as the flattened groups will add
513  * nodes at the end of the list, which will also get evaluated. */
514  for (bNode *node = static_cast<bNode *>(localtree->nodes.first), *node_next; node;
515  node = node_next) {
516  if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && node->id != nullptr) {
517  flatten_group_do(localtree, node);
518  /* Continue even on new flattened nodes. */
519  node_next = node->next;
520  /* delete the group instance and its localtree. */
521  bNodeTree *ngroup = (bNodeTree *)node->id;
522  ntreeFreeLocalNode(localtree, node);
523  ntreeFreeTree(ngroup);
524  BLI_assert(!ngroup->id.py_instance); /* Or call #BKE_libblock_free_data_py. */
525  MEM_freeN(ngroup);
526  }
527  else {
528  node_next = node->next;
529  }
530  }
531 
532  BKE_ntree_update_main_tree(G.main, localtree, nullptr);
533 }
534 
538 };
539 
540 static bool ntree_branch_count_and_tag_nodes(bNode *fromnode, bNode *tonode, void *userdata)
541 {
542  branchIterData *iter = (branchIterData *)userdata;
543  if (fromnode->tmp_flag == -1 && (iter->node_filter == nullptr || iter->node_filter(fromnode))) {
544  fromnode->tmp_flag = iter->node_count;
545  iter->node_count++;
546  }
547  if (tonode->tmp_flag == -1 && (iter->node_filter == nullptr || iter->node_filter(tonode))) {
548  tonode->tmp_flag = iter->node_count;
549  iter->node_count++;
550  }
551  return true;
552 }
553 
554 /* Create a copy of a branch starting from a given node.
555  * callback is executed once for every copied node.
556  * Returns input node copy. */
558  bNode *start_node,
559  bool (*node_filter)(const bNode *node),
560  void (*callback)(bNode *node, int user_data),
561  int user_data)
562 {
563  /* Init tmp flag. */
565  node->tmp_flag = -1;
566  }
567  /* Count and tag all nodes inside the displacement branch of the tree. */
568  start_node->tmp_flag = 0;
569  branchIterData iter_data;
570  iter_data.node_filter = node_filter;
571  iter_data.node_count = 1;
573  /* Make a full copy of the branch */
574  Array<bNode *> nodes_copy(iter_data.node_count);
576  if (node->tmp_flag >= 0) {
577  int id = node->tmp_flag;
578  nodes_copy[id] = blender::bke::node_copy(
580  nodes_copy[id]->tmp_flag = -2; /* Copy */
581  /* Make sure to clear all sockets links as they are invalid. */
582  LISTBASE_FOREACH (bNodeSocket *, sock, &nodes_copy[id]->inputs) {
583  sock->link = nullptr;
584  }
585  LISTBASE_FOREACH (bNodeSocket *, sock, &nodes_copy[id]->outputs) {
586  sock->link = nullptr;
587  }
588  }
589  }
590  /* Recreate links between copied nodes AND incoming links to the copied nodes. */
591  LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
592  if (link->tonode->tmp_flag >= 0) {
593  bool from_node_copied = link->fromnode->tmp_flag >= 0;
594  bNode *fromnode = from_node_copied ? nodes_copy[link->fromnode->tmp_flag] : link->fromnode;
595  bNode *tonode = nodes_copy[link->tonode->tmp_flag];
596  bNodeSocket *fromsock = ntree_shader_node_find_output(fromnode, link->fromsock->identifier);
597  bNodeSocket *tosock = ntree_shader_node_find_input(tonode, link->tosock->identifier);
598  nodeAddLink(ntree, fromnode, fromsock, tonode, tosock);
599  }
600  }
601  /* Per node callback. */
602  if (callback) {
603  for (int i = 0; i < iter_data.node_count; i++) {
604  callback(nodes_copy[i], user_data);
605  }
606  }
607  bNode *start_node_copy = nodes_copy[start_node->tmp_flag];
608  return start_node_copy;
609 }
610 
611 /* Generate emission node to convert regular data to closure sockets.
612  * Returns validity of the tree.
613  */
615 {
616  bool modified = false;
618  if ((link->fromsock->type != SOCK_SHADER) && (link->tosock->type == SOCK_SHADER)) {
619  bNode *emission_node = nodeAddStaticNode(NULL, ntree, SH_NODE_EMISSION);
620  bNodeSocket *in_sock = ntree_shader_node_find_input(emission_node, "Color");
621  bNodeSocket *out_sock = ntree_shader_node_find_output(emission_node, "Emission");
622  nodeAddLink(ntree, link->fromnode, link->fromsock, emission_node, in_sock);
623  nodeAddLink(ntree, emission_node, out_sock, link->tonode, link->tosock);
624  nodeRemLink(ntree, link);
625  modified = true;
626  }
627  else if ((link->fromsock->type == SOCK_SHADER) && (link->tosock->type != SOCK_SHADER)) {
628  /* Meh. Not directly visible to the user. But better than nothing. */
629  fprintf(stderr, "Shader Nodetree Error: Invalid implicit socket conversion\n");
630  BKE_ntree_update_main_tree(G.main, ntree, nullptr);
631  return false;
632  }
633  }
634  if (modified) {
635  BKE_ntree_update_main_tree(G.main, ntree, nullptr);
636  }
637  return true;
638 }
639 
640 /* Socket already has a link to it. Add weights together. */
642  bNode *UNUSED(fromnode),
643  bNodeSocket *fromsock,
644  bNode **tonode,
645  bNodeSocket **tosock)
646 {
648  addnode->custom1 = NODE_MATH_ADD;
649  addnode->tmp_flag = -2; /* Copy */
650  bNodeSocket *addsock_out = ntree_shader_node_output_get(addnode, 0);
651  bNodeSocket *addsock_in0 = ntree_shader_node_input_get(addnode, 0);
652  bNodeSocket *addsock_in1 = ntree_shader_node_input_get(addnode, 1);
653  bNodeLink *oldlink = fromsock->link;
654  nodeAddLink(ntree, oldlink->fromnode, oldlink->fromsock, addnode, addsock_in0);
655  nodeAddLink(ntree, *tonode, *tosock, addnode, addsock_in1);
656  nodeRemLink(ntree, oldlink);
657  *tonode = addnode;
658  *tosock = addsock_out;
659 }
660 
661 static bool ntree_weight_tree_tag_nodes(bNode *fromnode, bNode *tonode, void *userdata)
662 {
663  int *node_count = (int *)userdata;
664  bool to_node_from_weight_tree = ELEM(tonode->type,
670  if (tonode->tmp_flag == -1 && to_node_from_weight_tree) {
671  tonode->tmp_flag = *node_count;
672  *node_count += (tonode->type == SH_NODE_MIX_SHADER) ? 4 : 1;
673  }
674  if (fromnode->tmp_flag == -1 && ELEM(fromnode->type, SH_NODE_ADD_SHADER, SH_NODE_MIX_SHADER)) {
675  fromnode->tmp_flag = *node_count;
676  *node_count += (fromnode->type == SH_NODE_MIX_SHADER) ? 4 : 1;
677  }
678  return to_node_from_weight_tree;
679 }
680 
681 /* Invert evaluation order of the weight tree (add & mix closure nodes) to feed the closure nodes
682  * with their respective weights. */
684 {
685  bNodeLink *displace_link = NULL;
686  bNodeSocket *displace_output = ntree_shader_node_find_input(output_node, "Displacement");
687  if (displace_output && displace_output->link) {
688  /* Remove any displacement link to avoid tagging it later on. */
689  displace_link = displace_output->link;
690  displace_output->link = NULL;
691  }
692  bNodeLink *thickness_link = NULL;
693  bNodeSocket *thickness_output = ntree_shader_node_find_input(output_node, "Thickness");
694  if (thickness_output && thickness_output->link) {
695  /* Remove any thickness link to avoid tagging it later on. */
696  thickness_link = thickness_output->link;
697  thickness_output->link = NULL;
698  }
699  /* Init tmp flag. */
701  node->tmp_flag = -1;
702  }
703  /* Tag nodes from the weight tree. Only tag output node and mix/add shader nodes. */
704  output_node->tmp_flag = 0;
705  int node_count = 1;
706  nodeChainIterBackwards(ntree, output_node, ntree_weight_tree_tag_nodes, &node_count, 0);
707  /* Make a mirror copy of the weight tree. */
708  Array<bNode *> nodes_copy(node_count);
710  if (node->tmp_flag >= 0) {
711  int id = node->tmp_flag;
712 
713  switch (node->type) {
714  case SH_NODE_SHADERTORGB:
718  /* Start the tree with full weight. */
719  nodes_copy[id] = nodeAddStaticNode(NULL, ntree, SH_NODE_VALUE);
720  nodes_copy[id]->tmp_flag = -2; /* Copy */
722  ->value = 1.0f;
723  break;
724  }
725  case SH_NODE_ADD_SHADER: {
726  /* Simple passthrough node. Each original inputs will get the same weight. */
727  /* TODO(fclem): Better use some kind of reroute node? */
728  nodes_copy[id] = nodeAddStaticNode(NULL, ntree, SH_NODE_MATH);
729  nodes_copy[id]->custom1 = NODE_MATH_ADD;
730  nodes_copy[id]->tmp_flag = -2; /* Copy */
732  ->value = 0.0f;
733  break;
734  }
735  case SH_NODE_MIX_SHADER: {
736  /* We need multiple nodes to emulate the mix node in reverse. */
737  bNode *fromnode, *tonode;
738  bNodeSocket *fromsock, *tosock;
739  int id_start = id;
740  /* output = (factor * input_weight) */
741  nodes_copy[id] = nodeAddStaticNode(NULL, ntree, SH_NODE_MATH);
742  nodes_copy[id]->custom1 = NODE_MATH_MULTIPLY;
743  nodes_copy[id]->tmp_flag = -2; /* Copy */
744  id++;
745  /* output = ((1.0 - factor) * input_weight) <=> (input_weight - factor * input_weight) */
746  nodes_copy[id] = nodeAddStaticNode(NULL, ntree, SH_NODE_MATH);
747  nodes_copy[id]->custom1 = NODE_MATH_SUBTRACT;
748  nodes_copy[id]->tmp_flag = -2; /* Copy */
749  id++;
750  /* Node sanitizes the input mix factor by clamping it. */
751  nodes_copy[id] = nodeAddStaticNode(NULL, ntree, SH_NODE_MATH);
752  nodes_copy[id]->custom1 = NODE_MATH_ADD;
753  nodes_copy[id]->custom2 = SHD_MATH_CLAMP;
754  nodes_copy[id]->tmp_flag = -2; /* Copy */
756  ->value = 0.0f;
757  /* Copy default value if no link present. */
758  bNodeSocket *fac_sock = ntree_shader_node_find_input(node, "Fac");
759  if (!fac_sock->link) {
760  float default_value = ((bNodeSocketValueFloat *)fac_sock->default_value)->value;
761  bNodeSocket *dst_sock = ntree_shader_node_input_get(nodes_copy[id], 1);
762  ((bNodeSocketValueFloat *)dst_sock->default_value)->value = default_value;
763  }
764  id++;
765  /* Reroute the weight input to the 3 processing nodes. Simplify linking later-on. */
766  /* TODO(fclem): Better use some kind of reroute node? */
767  nodes_copy[id] = nodeAddStaticNode(NULL, ntree, SH_NODE_MATH);
768  nodes_copy[id]->custom1 = NODE_MATH_ADD;
769  nodes_copy[id]->tmp_flag = -2; /* Copy */
771  ->value = 0.0f;
772  id++;
773  /* Link between nodes for the subtraction. */
774  fromnode = nodes_copy[id_start];
775  tonode = nodes_copy[id_start + 1];
776  fromsock = ntree_shader_node_output_get(fromnode, 0);
777  tosock = ntree_shader_node_input_get(tonode, 1);
778  nodeAddLink(ntree, fromnode, fromsock, tonode, tosock);
779  /* Link mix input to first node. */
780  fromnode = nodes_copy[id_start + 2];
781  tonode = nodes_copy[id_start];
782  fromsock = ntree_shader_node_output_get(fromnode, 0);
783  tosock = ntree_shader_node_input_get(tonode, 1);
784  nodeAddLink(ntree, fromnode, fromsock, tonode, tosock);
785  /* Link weight input to both multiply nodes. */
786  fromnode = nodes_copy[id_start + 3];
787  fromsock = ntree_shader_node_output_get(fromnode, 0);
788  tonode = nodes_copy[id_start];
789  tosock = ntree_shader_node_input_get(tonode, 0);
790  nodeAddLink(ntree, fromnode, fromsock, tonode, tosock);
791  tonode = nodes_copy[id_start + 1];
792  tosock = ntree_shader_node_input_get(tonode, 0);
793  nodeAddLink(ntree, fromnode, fromsock, tonode, tosock);
794  break;
795  }
796  default:
797  BLI_assert(0);
798  break;
799  }
800  }
801  }
802  /* Recreate links between copied nodes. */
804  if (node->tmp_flag >= 0) {
805  /* Naming can be confusing here. We use original nodelink name for from/to prefix.
806  * The final link is in reversed order. */
807  int socket_index;
808  LISTBASE_FOREACH_INDEX (bNodeSocket *, sock, &node->inputs, socket_index) {
809  bNodeSocket *tosock;
810  bNode *tonode;
811 
812  switch (node->type) {
813  case SH_NODE_SHADERTORGB:
817  case SH_NODE_ADD_SHADER: {
818  tonode = nodes_copy[node->tmp_flag];
819  tosock = ntree_shader_node_output_get(tonode, 0);
820  break;
821  }
822  case SH_NODE_MIX_SHADER: {
823  if (socket_index == 0) {
824  /* Mix Factor. */
825  tonode = nodes_copy[node->tmp_flag + 2];
826  tosock = ntree_shader_node_input_get(tonode, 1);
827  }
828  else if (socket_index == 1) {
829  /* Shader 1. */
830  tonode = nodes_copy[node->tmp_flag + 1];
831  tosock = ntree_shader_node_output_get(tonode, 0);
832  }
833  else {
834  /* Shader 2. */
835  tonode = nodes_copy[node->tmp_flag];
836  tosock = ntree_shader_node_output_get(tonode, 0);
837  }
838  break;
839  }
840  default:
841  BLI_assert(0);
842  break;
843  }
844 
845  if (sock->link) {
846  bNodeSocket *fromsock;
847  bNode *fromnode = sock->link->fromnode;
848 
849  switch (fromnode->type) {
850  case SH_NODE_ADD_SHADER: {
851  fromnode = nodes_copy[fromnode->tmp_flag];
852  fromsock = ntree_shader_node_input_get(fromnode, 1);
853  if (fromsock->link) {
854  ntree_weight_tree_merge_weight(ntree, fromnode, fromsock, &tonode, &tosock);
855  }
856  break;
857  }
858  case SH_NODE_MIX_SHADER: {
859  fromnode = nodes_copy[fromnode->tmp_flag + 3];
860  fromsock = ntree_shader_node_input_get(fromnode, 1);
861  if (fromsock->link) {
862  ntree_weight_tree_merge_weight(ntree, fromnode, fromsock, &tonode, &tosock);
863  }
864  break;
865  }
866  case SH_NODE_BACKGROUND:
869  case SH_NODE_BSDF_GLASS:
870  case SH_NODE_BSDF_GLOSSY:
872  case SH_NODE_BSDF_HAIR:
875  case SH_NODE_BSDF_TOON:
878  case SH_NODE_BSDF_VELVET:
880  case SH_NODE_EMISSION:
881  case SH_NODE_HOLDOUT:
886  fromsock = ntree_shader_node_find_input(fromnode, "Weight");
887  if (fromsock->link) {
888  ntree_weight_tree_merge_weight(ntree, fromnode, fromsock, &tonode, &tosock);
889  }
890  break;
891  default:
892  fromsock = sock->link->fromsock;
893  break;
894  }
895 
896  /* Manually add the link to the socket to avoid calling:
897  * `BKE_ntree_update_main_tree(G.main, oop, nullptr)`. */
898  fromsock->link = nodeAddLink(ntree, fromnode, fromsock, tonode, tosock);
899  BLI_assert(fromsock->link);
900  }
901  }
902  }
903  }
904  /* Restore displacement & thickness link. */
905  if (displace_link) {
906  nodeAddLink(
907  ntree, displace_link->fromnode, displace_link->fromsock, output_node, displace_output);
908  }
909  if (thickness_link) {
910  nodeAddLink(
911  ntree, thickness_link->fromnode, thickness_link->fromsock, output_node, thickness_output);
912  }
913  BKE_ntree_update_main_tree(G.main, ntree, nullptr);
914 }
915 
916 static bool closure_node_filter(const bNode *node)
917 {
918  switch (node->type) {
919  case SH_NODE_ADD_SHADER:
920  case SH_NODE_MIX_SHADER:
921  case SH_NODE_BACKGROUND:
924  case SH_NODE_BSDF_GLASS:
925  case SH_NODE_BSDF_GLOSSY:
927  case SH_NODE_BSDF_HAIR:
930  case SH_NODE_BSDF_TOON:
933  case SH_NODE_BSDF_VELVET:
935  case SH_NODE_EMISSION:
936  case SH_NODE_HOLDOUT:
941  return true;
942  default:
943  return false;
944  }
945 }
946 
947 static bool shader_to_rgba_node_gather(bNode *UNUSED(fromnode), bNode *tonode, void *userdata)
948 {
949  Vector<bNode *> &shader_to_rgba_nodes = *(Vector<bNode *> *)userdata;
950  if (tonode->tmp_flag == -1 && tonode->type == SH_NODE_SHADERTORGB) {
951  tonode->tmp_flag = 0;
952  shader_to_rgba_nodes.append(tonode);
953  }
954  return true;
955 }
956 
957 /* Shader to rgba needs their associated closure duplicated and the weight tree generated for. */
959 {
961  node->tmp_flag = -1;
962  }
963  /* First gather the shader_to_rgba nodes linked to the output. This is separate to avoid
964  * conflicting usage of the `node->tmp_flag`. */
965  Vector<bNode *> shader_to_rgba_nodes;
966  nodeChainIterBackwards(ntree, output_node, shader_to_rgba_node_gather, &shader_to_rgba_nodes, 0);
967 
968  for (bNode *shader_to_rgba : shader_to_rgba_nodes) {
969  bNodeSocket *closure_input = ntree_shader_node_input_get(shader_to_rgba, 0);
970  if (closure_input->link == nullptr) {
971  continue;
972  }
973  bNode *start_node = closure_input->link->fromnode;
974  bNode *start_node_copy = ntree_shader_copy_branch(
975  ntree, start_node, closure_node_filter, nullptr, 0);
976  /* Replace node copy link. This assumes that every node possibly connected to the closure input
977  * has only one output. */
978  bNodeSocket *closure_output = ntree_shader_node_output_get(start_node_copy, 0);
979  nodeRemLink(ntree, closure_input->link);
980  nodeAddLink(ntree, start_node_copy, closure_output, shader_to_rgba, closure_input);
981  BKE_ntree_update_main_tree(G.main, ntree, nullptr);
982 
983  ntree_shader_weight_tree_invert(ntree, shader_to_rgba);
984  }
985 }
986 
987 static bool ntree_branch_node_tag(bNode *fromnode, bNode *tonode, void *UNUSED(userdata))
988 {
989  fromnode->tmp_flag = 1;
990  tonode->tmp_flag = 1;
991  return true;
992 }
993 
994 /* Avoid adding more node execution when multiple outputs are present. */
995 /* NOTE(@fclem): This is also a workaround for the old EEVEE SSS implementation where only the
996  * first executed SSS node gets a SSS profile. */
997 static void ntree_shader_pruned_unused(bNodeTree *ntree, bNode *output_node)
998 {
999  bool changed = false;
1000 
1002  node->tmp_flag = 0;
1003  }
1004 
1005  /* Avoid deleting the output node if it is the only node in the tree. */
1006  output_node->tmp_flag = 1;
1007 
1008  nodeChainIterBackwards(ntree, output_node, ntree_branch_node_tag, nullptr, 0);
1009 
1011  if (node->type == SH_NODE_OUTPUT_AOV) {
1012  node->tmp_flag = 1;
1014  }
1015  }
1016 
1018  if (node->tmp_flag == 0) {
1020  changed = true;
1021  }
1022  }
1023 
1024  if (changed) {
1025  BKE_ntree_update_main_tree(G.main, ntree, nullptr);
1026  }
1027 }
1028 
1030 {
1032 
1035  ntree_shader_groups_flatten(localtree);
1036 
1038 
1039  /* Tree is valid if it contains no undefined implicit socket type cast. */
1040  bool valid_tree = ntree_shader_implicit_closure_cast(localtree);
1041 
1042  if (valid_tree && output != NULL) {
1043  ntree_shader_pruned_unused(localtree, output);
1046  }
1047 
1048  exec = ntreeShaderBeginExecTree(localtree);
1049  ntreeExecGPUNodes(exec, mat, output);
1050  LISTBASE_FOREACH (bNode *, node, &localtree->nodes) {
1051  if (node->type == SH_NODE_OUTPUT_AOV) {
1052  ntreeExecGPUNodes(exec, mat, node);
1053  }
1054  }
1056 }
1057 
1059  bNodeTree *ntree,
1060  bNodeInstanceKey parent_key)
1061 {
1062  /* ensures only a single output node is enabled */
1064 
1065  /* common base initialization */
1066  bNodeTreeExec *exec = ntree_exec_begin(context, ntree, parent_key);
1067 
1068  /* allocate the thread stack listbase array */
1069  exec->threadstack = static_cast<ListBase *>(
1070  MEM_callocN(BLENDER_MAX_THREADS * sizeof(ListBase), "thread stack array"));
1071 
1072  LISTBASE_FOREACH (bNode *, node, &exec->nodetree->nodes) {
1073  node->need_exec = 1;
1074  }
1075 
1076  return exec;
1077 }
1078 
1080 {
1083 
1084  /* XXX hack: prevent exec data from being generated twice.
1085  * this should be handled by the renderer!
1086  */
1087  if (ntree->execdata) {
1088  return ntree->execdata;
1089  }
1090 
1091  context.previews = ntree->previews;
1092 
1094 
1095  /* XXX: this should not be necessary, but is still used for compositor/shader/texture nodes,
1096  * which only store the `ntree` pointer. Should be fixed at some point!
1097  */
1098  ntree->execdata = exec;
1099 
1100  return exec;
1101 }
1102 
1104 {
1105  if (exec->threadstack) {
1106  for (int a = 0; a < BLENDER_MAX_THREADS; a++) {
1107  LISTBASE_FOREACH (bNodeThreadStack *, nts, &exec->threadstack[a]) {
1108  if (nts->stack) {
1109  MEM_freeN(nts->stack);
1110  }
1111  }
1112  BLI_freelistN(&exec->threadstack[a]);
1113  }
1114 
1115  MEM_freeN(exec->threadstack);
1116  exec->threadstack = nullptr;
1117  }
1118 
1120 }
1121 
1123 {
1124  if (exec) {
1125  /* exec may get freed, so assign ntree */
1126  bNodeTree *ntree = exec->nodetree;
1128 
1129  /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
1130  ntree->execdata = nullptr;
1131  }
1132 }
typedef float(TangentPoint)[2]
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct SpaceNode * CTX_wm_space_node(const bContext *C)
Definition: context.c:878
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1100
@ LIB_ID_CREATE_NO_USER_REFCOUNT
Definition: BKE_lib_id.h:126
@ LIB_ID_CREATE_NO_MAIN
Definition: BKE_lib_id.h:122
Blender kernel freestyle line style functionality.
FreestyleLineStyle * BKE_linestyle_active_from_view_layer(struct ViewLayer *view_layer)
Definition: linestyle.c:806
struct Material * BKE_object_material_get(struct Object *ob, short act)
Definition: material.c:687
#define SH_NODE_MIX_SHADER
Definition: BKE_node.h:1105
void ntreeTypeAdd(struct bNodeTreeType *nt)
Definition: node.cc:1292
#define SH_NODE_HOLDOUT
Definition: BKE_node.h:1130
#define NODE_CLASS_OUTPUT
Definition: BKE_node.h:346
#define NODE_REROUTE
Definition: BKE_node.h:986
#define NODE_CLASS_INTERFACE
Definition: BKE_node.h:357
void nodeInternalRelink(struct bNodeTree *ntree, struct bNode *node)
Definition: node.cc:2490
const bNodeInstanceKey NODE_INSTANCE_KEY_BASE
Definition: node.cc:3896
#define NODE_CUSTOM_GROUP
Definition: BKE_node.h:989
#define SH_NODE_BSDF_PRINCIPLED
Definition: BKE_node.h:1164
#define SH_NODE_EMISSION
Definition: BKE_node.h:1115
#define NODE_CLASS_CONVERTER
Definition: BKE_node.h:351
void ntreeFreeLocalNode(struct bNodeTree *ntree, struct bNode *node)
Definition: node.cc:2998
#define SH_NODE_ADD_SHADER
Definition: BKE_node.h:1127
#define SH_NODE_SUBSURFACE_SCATTERING
Definition: BKE_node.h:1148
void(* bNodeClassCallback)(void *calldata, int nclass, const char *name)
Definition: BKE_node.h:372
#define SH_NODE_VOLUME_ABSORPTION
Definition: BKE_node.h:1132
#define SH_NODE_BSDF_VELVET
Definition: BKE_node.h:1114
#define SH_NODE_VALUE
Definition: BKE_node.h:1080
void ntreeFreeTree(struct bNodeTree *ntree)
Definition: node.cc:3106
void nodeRemLink(struct bNodeTree *ntree, struct bNodeLink *link)
Definition: node.cc:2338
#define SH_NODE_MATH
Definition: BKE_node.h:1092
#define SH_NODE_BSDF_TOON
Definition: BKE_node.h:1150
#define SH_NODE_BSDF_TRANSPARENT
Definition: BKE_node.h:1113
#define SH_NODE_BSDF_DIFFUSE
Definition: BKE_node.h:1109
#define SH_NODE_SHADERTORGB
Definition: BKE_node.h:1084
#define SH_NODE_OUTPUT_MATERIAL
Definition: BKE_node.h:1101
bool nodeIsStaticSocketType(const struct bNodeSocketType *stype)
Definition: node.cc:1701
#define SH_NODE_BSDF_TRANSLUCENT
Definition: BKE_node.h:1112
void ntreeSetOutput(struct bNodeTree *ntree)
Definition: node.cc:3141
#define SH_NODE_BSDF_HAIR_PRINCIPLED
Definition: BKE_node.h:1172
#define SH_NODE_BSDF_HAIR
Definition: BKE_node.h:1156
struct bNodeLink * nodeAddLink(struct bNodeTree *ntree, struct bNode *fromnode, struct bNodeSocket *fromsock, struct bNode *tonode, struct bNodeSocket *tosock)
Definition: node.cc:2296
#define SH_NODE_BACKGROUND
Definition: BKE_node.h:1107
#define SH_NODE_BSDF_ANISOTROPIC
Definition: BKE_node.h:1108
#define SH_NODE_BSDF_GLOSSY
Definition: BKE_node.h:1110
#define NODE_CLASS_OP_VECTOR
Definition: BKE_node.h:348
#define NODE_CLASS_LAYOUT
Definition: BKE_node.h:361
#define NODE_CLASS_OP_COLOR
Definition: BKE_node.h:347
#define SH_NODE_BSDF_GLASS
Definition: BKE_node.h:1111
#define NODE_CLASS_INPUT
Definition: BKE_node.h:345
void nodeChainIterBackwards(const bNodeTree *ntree, const bNode *node_start, bool(*callback)(bNode *, bNode *, void *), void *userdata, int recursion_lvl)
Definition: node.cc:2093
struct bNode * nodeAddStaticNode(const struct bContext *C, struct bNodeTree *ntree, int type)
Definition: node.cc:2151
#define NODE_CLASS_GROUP
Definition: BKE_node.h:350
#define SH_NODE_VOLUME_PRINCIPLED
Definition: BKE_node.h:1170
#define NODE_GROUP_INPUT
Definition: BKE_node.h:987
#define NODE_CLASS_TEXTURE
Definition: BKE_node.h:355
#define SH_NODE_BSDF_REFRACTION
Definition: BKE_node.h:1144
#define SH_NODE_OUTPUT_LIGHT
Definition: BKE_node.h:1103
#define NODE_CLASS_SHADER
Definition: BKE_node.h:358
#define SH_NODE_VOLUME_SCATTER
Definition: BKE_node.h:1133
#define SH_NODE_OUTPUT_AOV
Definition: BKE_node.h:1178
#define NODE_CLASS_SCRIPT
Definition: BKE_node.h:356
void BKE_ntree_update_tag_all(struct bNodeTree *ntree)
void BKE_ntree_update_main_tree(struct Main *bmain, struct bNodeTree *ntree, struct NodeTreeUpdateExtraParams *params)
bool BKE_scene_use_shading_nodes_custom(struct Scene *scene)
Definition: scene.cc:2838
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
Definition: BLI_listbase.h:354
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
Definition: BLI_listbase.h:344
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:466
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:100
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void copy_v3_fl(float r[3], float f)
#define BLENDER_MAX_THREADS
Definition: BLI_threads.h:19
#define UNUSED(x)
#define ELEM(...)
#define STREQ(a, b)
@ NODE_VECTOR_MATH_DOT_PRODUCT
@ NODE_MATH_ADD
@ NODE_MATH_MULTIPLY
@ NODE_MATH_SUBTRACT
@ SHD_OUTPUT_ALL
@ SHD_OUTPUT_EEVEE
#define NODE_DO_OUTPUT
#define NODE_MUTED
#define SHD_MATH_CLAMP
@ SOCK_HIDE_VALUE
eNodeSocketDatatype
@ SOCK_INT
@ SOCK_VECTOR
@ SOCK_SHADER
@ SOCK_FLOAT
@ SOCK_RGBA
#define NTREE_SHADER
#define NODE_LINK_MUTED
@ OB_LAMP
#define OBACT(_view_layer)
@ SNODE_SHADER_LINESTYLE
@ SNODE_SHADER_OBJECT
Group Output data from inside of a node group A color picker Mix two input colors SH_NODE_RGBTOBW
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a producing a negative Combine Generate a color from its and blue Hue Saturation Apply a color transformation in the HSV color model SH_NODE_EEVEE_SPECULAR
NODE_GROUP_OUTPUT
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a producing a negative Combine Generate a color from its and blue Hue Saturation Apply a color transformation in the HSV color model Specular Similar to the Principled BSDF node but uses the specular workflow instead of which functions by specifying the so the result may not be physically accurate SH_NODE_OUTPUT_WORLD
NODE_GROUP
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum SH_NODE_VECTOR_MATH
Group Output data from inside of a node group SH_NODE_RGB
#define C
Definition: RandGen.cpp:25
void append(const T &value)
Definition: BLI_vector.hh:433
OperationNode * node
StackEntry * from
Scene scene
FreestyleLineStyle linestyle
void * user_data
DEGForeachIDComponentCallback callback
bNodeTree * ntree
ccl_global KernelShaderEvalInput ccl_global float * output
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
#define G(x, y, z)
static unsigned a[3]
Definition: RandGen.cpp:78
bNode * node_copy(bNodeTree *dst_tree, const bNode &src_node, const int flag, const bool unique_name)
Definition: node.cc:2274
void ntree_update_reroute_nodes(bNodeTree *ntree)
Definition: node_common.cc:321
bNodeTreeExec * ntree_exec_begin(bNodeExecContext *context, bNodeTree *ntree, bNodeInstanceKey parent_key)
Definition: node_exec.cc:139
void ntree_exec_end(bNodeTreeExec *exec)
Definition: node_exec.cc:242
static void foreach_nodeclass(Scene *UNUSED(scene), void *calldata, bNodeClassCallback func)
static bool shader_node_tree_socket_type_valid(bNodeTreeType *UNUSED(ntreetype), bNodeSocketType *socket_type)
static bool ntree_shader_implicit_closure_cast(bNodeTree *ntree)
static bool ntree_branch_node_tag(bNode *fromnode, bNode *tonode, void *UNUSED(userdata))
bNodeTreeExec * ntreeShaderBeginExecTree(bNodeTree *ntree)
static bool ntree_branch_count_and_tag_nodes(bNode *fromnode, bNode *tonode, void *userdata)
static bool ntree_weight_tree_tag_nodes(bNode *fromnode, bNode *tonode, void *userdata)
static bool ntree_shader_expand_socket_default(bNodeTree *localtree, bNode *node, bNodeSocket *socket)
static bool shader_to_rgba_node_gather(bNode *UNUSED(fromnode), bNode *tonode, void *userdata)
static bNodeSocket * ntree_shader_node_find_output(bNode *node, const char *identifier)
static void ntree_shader_groups_expand_inputs(bNodeTree *localtree)
bNodeTreeExec * ntreeShaderBeginExecTree_internal(bNodeExecContext *context, bNodeTree *ntree, bNodeInstanceKey parent_key)
static void ntree_shader_groups_flatten(bNodeTree *localtree)
void ntreeGPUMaterialNodes(bNodeTree *localtree, GPUMaterial *mat)
static void ntree_weight_tree_merge_weight(bNodeTree *ntree, bNode *UNUSED(fromnode), bNodeSocket *fromsock, bNode **tonode, bNodeSocket **tosock)
static void localize(bNodeTree *localtree, bNodeTree *UNUSED(ntree))
static bNodeSocket * ntree_shader_node_output_get(bNode *node, int n)
static bool closure_node_filter(const bNode *node)
static void shader_get_from_context(const bContext *C, bNodeTreeType *UNUSED(treetype), bNodeTree **r_ntree, ID **r_id, ID **r_from)
static void ntree_shader_weight_tree_invert(bNodeTree *ntree, bNode *output_node)
void register_node_tree_type_sh()
static bNode * ntree_shader_copy_branch(bNodeTree *ntree, bNode *start_node, bool(*node_filter)(const bNode *node), void(*callback)(bNode *node, int user_data), int user_data)
static void update(bNodeTree *ntree)
static bNodeSocket * ntree_shader_node_find_socket(ListBase *sockets, const char *identifier)
static bNodeSocket * ntree_shader_node_input_get(bNode *node, int n)
static bool shader_validate_link(eNodeSocketDatatype from, eNodeSocketDatatype to)
static void ntree_shader_pruned_unused(bNodeTree *ntree, bNode *output_node)
static void ntree_shader_unlink_hidden_value_sockets(bNode *group_node, bNodeSocket *isock)
static void ntree_shader_shader_to_rgba_branch(bNodeTree *ntree, bNode *output_node)
bNodeTreeType * ntreeType_Shader
static void flatten_group_do(bNodeTree *ntree, bNode *gnode)
static bool shader_tree_poll(const bContext *C, bNodeTreeType *UNUSED(treetype))
static void ntree_shader_groups_remove_muted_links(bNodeTree *ntree)
void ntreeShaderEndExecTree(bNodeTreeExec *exec)
bNode * ntreeShaderOutputNode(bNodeTree *ntree, int target)
void ntreeShaderEndExecTree_internal(bNodeTreeExec *exec)
static bNodeSocket * ntree_shader_node_find_input(bNode *node, const char *identifier)
void ntreeExecGPUNodes(bNodeTreeExec *exec, GPUMaterial *mat, bNode *output_node)
static bNodeSocketTemplate outputs[]
static bNodeSocketTemplate inputs[]
static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
const char * RE_engine_id_CYCLES
Definition: scene.cc:1697
StructRNA * srna
Definition: RNA_types.h:766
struct bNodeTree * nodetree
Definition: DNA_ID.h:368
void * py_instance
Definition: DNA_ID.h:435
void * last
Definition: DNA_listBase.h:31
void * first
Definition: DNA_listBase.h:31
struct bNodeTree * nodetree
void * data
char engine[32]
struct RenderData r
struct World * world
struct bNodeTree * nodetree
Defines a socket type.
Definition: BKE_node.h:143
struct bNodeLink * link
struct bNodeSocket * next
void * default_value
char identifier[64]
bool(* validate_link)(eNodeSocketDatatype from, eNodeSocketDatatype to)
Definition: BKE_node.h:402
bool(* poll)(const struct bContext *C, struct bNodeTreeType *ntreetype)
Definition: BKE_node.h:387
char idname[64]
Definition: BKE_node.h:375
void(* update)(struct bNodeTree *ntree)
Definition: BKE_node.h:400
void(* get_from_context)(const struct bContext *C, struct bNodeTreeType *ntreetype, struct bNodeTree **r_ntree, struct ID **r_id, struct ID **r_from)
Definition: BKE_node.h:389
char ui_name[64]
Definition: BKE_node.h:377
void(* localize)(struct bNodeTree *localtree, struct bNodeTree *ntree)
Definition: BKE_node.h:396
char ui_description[256]
Definition: BKE_node.h:378
bool(* valid_socket_type)(struct bNodeTreeType *ntreetype, struct bNodeSocketType *socket_type)
Definition: BKE_node.h:407
void(* foreach_nodeclass)(struct Scene *scene, void *calldata, bNodeClassCallback func)
Definition: BKE_node.h:385
ExtensionRNA rna_ext
Definition: BKE_node.h:410
struct bNodeInstanceHash * previews
ListBase nodes
ListBase links
struct bNodeTreeExec * execdata
short custom1
ListBase inputs
struct ID * id
short tmp_flag
short type
ListBase outputs
bool(* node_filter)(const bNode *node)
#define N_(msgid)