Blender V4.5
node_shader_tree.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2007 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cstring>
10
11#include "DNA_light_types.h"
12#include "DNA_linestyle_types.h"
13#include "DNA_material_types.h"
14#include "DNA_node_types.h"
15#include "DNA_scene_types.h"
16#include "DNA_space_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_math_vector.h"
23#include "BLI_set.hh"
24#include "BLI_threads.h"
25#include "BLI_utildefines.h"
26#include "BLI_vector.hh"
27
28#include "BKE_context.hh"
29#include "BKE_global.hh"
30#include "BKE_layer.hh"
31#include "BKE_lib_id.hh"
32#include "BKE_linestyle.h"
33#include "BKE_material.hh"
34#include "BKE_node.hh"
36#include "BKE_node_runtime.hh"
38#include "BKE_scene.hh"
39
40#include "RNA_prototypes.hh"
41
42#include "UI_resources.hh"
43
44#include "NOD_shader.h"
45
46#include "node_common.h"
47#include "node_exec.hh"
48#include "node_shader_util.hh"
49#include "node_util.hh"
50
51using blender::Array;
52using blender::Vector;
53
54static bool shader_tree_poll(const bContext *C, blender::bke::bNodeTreeType * /*treetype*/)
55{
56 Scene *scene = CTX_data_scene(C);
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
66 blender::bke::bNodeTreeType * /*treetype*/,
67 bNodeTree **r_ntree,
68 ID **r_id,
69 ID **r_from)
70{
72 Scene *scene = CTX_data_scene(C);
73 ViewLayer *view_layer = CTX_data_view_layer(C);
74 BKE_view_layer_synced_ensure(scene, view_layer);
76
77 if (snode->shaderfrom == SNODE_SHADER_OBJECT) {
78 if (ob) {
79 *r_from = &ob->id;
80 if (ob->type == OB_LAMP) {
81 *r_id = static_cast<ID *>(ob->data);
82 *r_ntree = ((Light *)ob->data)->nodetree;
83 }
84 else {
86 if (ma) {
87 *r_id = &ma->id;
88 *r_ntree = ma->nodetree;
89 }
90 }
91 }
92 }
93#ifdef WITH_FREESTYLE
94 else if (snode->shaderfrom == SNODE_SHADER_LINESTYLE) {
96 if (linestyle) {
97 *r_from = nullptr;
98 *r_id = &linestyle->id;
99 *r_ntree = linestyle->nodetree;
100 }
101 }
102#endif
103 else { /* SNODE_SHADER_WORLD */
104 if (scene->world) {
105 *r_from = nullptr;
106 *r_id = &scene->world->id;
107 *r_ntree = scene->world->nodetree;
108 }
109 }
110}
111
113{
114 func(calldata, NODE_CLASS_INPUT, N_("Input"));
115 func(calldata, NODE_CLASS_OUTPUT, N_("Output"));
116 func(calldata, NODE_CLASS_SHADER, N_("Shader"));
117 func(calldata, NODE_CLASS_TEXTURE, N_("Texture"));
118 func(calldata, NODE_CLASS_OP_COLOR, N_("Color"));
119 func(calldata, NODE_CLASS_OP_VECTOR, N_("Vector"));
120 func(calldata, NODE_CLASS_CONVERTER, N_("Converter"));
121 func(calldata, NODE_CLASS_SCRIPT, N_("Script"));
122 func(calldata, NODE_CLASS_GROUP, N_("Group"));
123 func(calldata, NODE_CLASS_INTERFACE, N_("Interface"));
124 func(calldata, NODE_CLASS_LAYOUT, N_("Layout"));
125}
126
127static void localize(bNodeTree *localtree, bNodeTree * /*ntree*/)
128{
129 /* replace muted nodes and reroute nodes by internal links */
130 LISTBASE_FOREACH_MUTABLE (bNode *, node, &localtree->nodes) {
131 if (node->is_muted() || node->is_reroute()) {
132 if (node->is_group() && node->id) {
133 /* Free the group like in #ntree_shader_groups_flatten. */
134 bNodeTree *group = reinterpret_cast<bNodeTree *>(node->id);
136 MEM_freeN(group);
137 node->id = nullptr;
138 }
139
140 blender::bke::node_internal_relink(*localtree, *node);
142 }
143 }
144}
145
146static void update(bNodeTree *ntree)
147{
149
151}
152
154{
155 /* Can't connect shader into other socket types, other way around is fine
156 * since it will be interpreted as emission. */
157 if (from == SOCK_SHADER) {
158 return to == SOCK_SHADER;
159 }
160 return true;
161}
162
165{
166 return blender::bke::node_is_static_socket_type(*socket_type) && ELEM(socket_type->type,
168 SOCK_INT,
171 SOCK_RGBA,
173}
174
176
178{
179 blender::bke::bNodeTreeType *tt = ntreeType_Shader = MEM_new<blender::bke::bNodeTreeType>(
180 __func__);
181
182 tt->type = NTREE_SHADER;
183 tt->idname = "ShaderNodeTree";
184 tt->group_idname = "ShaderNodeGroup";
185 tt->ui_name = N_("Shader Editor");
186 tt->ui_icon = ICON_NODE_MATERIAL;
187 tt->ui_description = N_("Shader nodes");
188
190 tt->localize = localize;
191 tt->update = update;
196
197 tt->rna_ext.srna = &RNA_ShaderNodeTree;
198
200}
201
202/* GPU material from shader nodes */
203
205{
206 /* Make sure we only have single node tagged as output. */
208
209 /* Find output node that matches type and target. If there are
210 * multiple, we prefer exact target match and active nodes. */
211 bNode *output_node = nullptr;
212
213 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
214 if (!ELEM(node->type_legacy,
218 {
219 continue;
220 }
221
222 if (node->custom1 == SHD_OUTPUT_ALL) {
223 if (output_node == nullptr) {
224 output_node = node;
225 }
226 else if (output_node->custom1 == SHD_OUTPUT_ALL) {
227 if ((node->flag & NODE_DO_OUTPUT) && !(output_node->flag & NODE_DO_OUTPUT)) {
228 output_node = node;
229 }
230 }
231 }
232 else if (node->custom1 == target) {
233 if (output_node == nullptr) {
234 output_node = node;
235 }
236 else if (output_node->custom1 == SHD_OUTPUT_ALL) {
237 output_node = node;
238 }
239 else if ((node->flag & NODE_DO_OUTPUT) && !(output_node->flag & NODE_DO_OUTPUT)) {
240 output_node = node;
241 }
242 }
243 }
244
245 return output_node;
246}
247
248/* Find socket with a specified identifier. */
249static bNodeSocket *ntree_shader_node_find_socket(ListBase *sockets, const char *identifier)
250{
251 LISTBASE_FOREACH (bNodeSocket *, sock, sockets) {
252 if (STREQ(sock->identifier, identifier)) {
253 return sock;
254 }
255 }
256 return nullptr;
257}
258
259/* Find input socket with a specified identifier. */
260static bNodeSocket *ntree_shader_node_find_input(bNode *node, const char *identifier)
261{
262 return ntree_shader_node_find_socket(&node->inputs, identifier);
263}
264
265/* Find output socket with a specified identifier. */
266static bNodeSocket *ntree_shader_node_find_output(bNode *node, const char *identifier)
267{
268 return ntree_shader_node_find_socket(&node->outputs, identifier);
269}
270
271/* Find input socket at a specific position. */
273{
274 return reinterpret_cast<bNodeSocket *>(BLI_findlink(&node->inputs, n));
275}
276
277/* Find output socket at a specific position. */
279{
280 return reinterpret_cast<bNodeSocket *>(BLI_findlink(&node->outputs, n));
281}
282
283/* Return true on success. */
285 bNode *node,
286 bNodeSocket *socket)
287{
288 bNode *value_node;
289 bNodeSocket *value_socket;
290 bNodeSocketValueVector *src_vector;
291 bNodeSocketValueRGBA *src_rgba, *dst_rgba;
292 bNodeSocketValueFloat *src_float, *dst_float;
293 bNodeSocketValueInt *src_int;
294 bNodeSocketValueBoolean *src_bool;
295
296 switch (socket->type) {
297 case SOCK_VECTOR:
298 value_node = blender::bke::node_add_static_node(nullptr, *localtree, SH_NODE_RGB);
299 value_socket = ntree_shader_node_find_output(value_node, "Color");
300 BLI_assert(value_socket != nullptr);
301 src_vector = static_cast<bNodeSocketValueVector *>(socket->default_value);
302 dst_rgba = static_cast<bNodeSocketValueRGBA *>(value_socket->default_value);
303 copy_v3_v3(dst_rgba->value, src_vector->value);
304 dst_rgba->value[3] = 1.0f; /* should never be read */
305 break;
306 case SOCK_RGBA:
307 value_node = blender::bke::node_add_static_node(nullptr, *localtree, SH_NODE_RGB);
308 value_socket = ntree_shader_node_find_output(value_node, "Color");
309 BLI_assert(value_socket != nullptr);
310 src_rgba = static_cast<bNodeSocketValueRGBA *>(socket->default_value);
311 dst_rgba = static_cast<bNodeSocketValueRGBA *>(value_socket->default_value);
312 copy_v4_v4(dst_rgba->value, src_rgba->value);
313 break;
314 case SOCK_BOOLEAN:
315 /* HACK: Support as float. */
316 value_node = blender::bke::node_add_static_node(nullptr, *localtree, SH_NODE_VALUE);
317 value_socket = ntree_shader_node_find_output(value_node, "Value");
318 BLI_assert(value_socket != nullptr);
319 src_bool = static_cast<bNodeSocketValueBoolean *>(socket->default_value);
320 dst_float = static_cast<bNodeSocketValueFloat *>(value_socket->default_value);
321 dst_float->value = float(src_bool->value);
322 break;
323 case SOCK_INT:
324 /* HACK: Support as float. */
325 value_node = blender::bke::node_add_static_node(nullptr, *localtree, SH_NODE_VALUE);
326 value_socket = ntree_shader_node_find_output(value_node, "Value");
327 BLI_assert(value_socket != nullptr);
328 src_int = static_cast<bNodeSocketValueInt *>(socket->default_value);
329 dst_float = static_cast<bNodeSocketValueFloat *>(value_socket->default_value);
330 dst_float->value = float(src_int->value);
331 break;
332 case SOCK_FLOAT:
333 value_node = blender::bke::node_add_static_node(nullptr, *localtree, SH_NODE_VALUE);
334 value_socket = ntree_shader_node_find_output(value_node, "Value");
335 BLI_assert(value_socket != nullptr);
336 src_float = static_cast<bNodeSocketValueFloat *>(socket->default_value);
337 dst_float = static_cast<bNodeSocketValueFloat *>(value_socket->default_value);
338 dst_float->value = src_float->value;
339 break;
340 default:
341 return false;
342 }
343 blender::bke::node_add_link(*localtree, *value_node, *value_socket, *node, *socket);
344 return true;
345}
346
348{
349 bNodeTree *group_ntree = (bNodeTree *)group_node->id;
350 bool removed_link = false;
351
352 LISTBASE_FOREACH (bNode *, node, &group_ntree->nodes) {
353 const bool is_group = node->is_group() && (node->id != nullptr);
354
355 LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
356 if (!is_group && (sock->flag & SOCK_HIDE_VALUE) == 0) {
357 continue;
358 }
359 /* If socket is linked to a group input node and sockets id match. */
360 if (sock && sock->link && sock->link->fromnode->is_group_input()) {
361 if (STREQ(isock->identifier, sock->link->fromsock->identifier)) {
362 if (is_group) {
363 /* Recursively unlink sockets within the nested group. */
365 }
366 else {
367 blender::bke::node_remove_link(group_ntree, *sock->link);
368 removed_link = true;
369 }
370 }
371 }
372 }
373 }
374
375 if (removed_link) {
376 BKE_ntree_update_after_single_tree_change(*G.main, *group_ntree);
377 }
378}
379
380/* Node groups once expanded looses their input sockets values.
381 * To fix this, link value/rgba nodes into the sockets and copy the group sockets values. */
383{
384 bool link_added = false;
385
386 LISTBASE_FOREACH (bNode *, node, &localtree->nodes) {
387 const bool is_group = node->is_group() && (node->id != nullptr);
388 const bool is_group_output = node->is_group_output() && (node->flag & NODE_DO_OUTPUT);
389
390 if (is_group) {
391 /* Do it recursively. */
393 }
394
395 if (is_group || is_group_output) {
396 LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) {
397 if (socket->link != nullptr && !(socket->link->flag & NODE_LINK_MUTED)) {
398 bNodeLink *link = socket->link;
399 /* Fix the case where the socket is actually converting the data. (see #71374)
400 * We only do the case of lossy conversion to float. */
401 if ((socket->type == SOCK_FLOAT) && (link->fromsock->type != link->tosock->type)) {
402 if (link->fromsock->type == SOCK_RGBA) {
404 nullptr, *localtree, SH_NODE_RGBTOBW);
406 *link->fromnode,
407 *link->fromsock,
408 *tmp,
409 *static_cast<bNodeSocket *>(tmp->inputs.first));
411 *tmp,
412 *static_cast<bNodeSocket *>(tmp->outputs.first),
413 *node,
414 *socket);
415 }
416 else if (link->fromsock->type == SOCK_VECTOR) {
418 nullptr, *localtree, SH_NODE_VECTOR_MATH);
420 bNodeSocket *dot_input1 = static_cast<bNodeSocket *>(tmp->inputs.first);
421 bNodeSocket *dot_input2 = static_cast<bNodeSocket *>(dot_input1->next);
422 bNodeSocketValueVector *input2_socket_value = static_cast<bNodeSocketValueVector *>(
423 dot_input2->default_value);
424 copy_v3_fl(input2_socket_value->value, 1.0f / 3.0f);
426 *localtree, *link->fromnode, *link->fromsock, *tmp, *dot_input1);
428 *tmp,
429 *static_cast<bNodeSocket *>(tmp->outputs.last),
430 *node,
431 *socket);
432 }
433 }
434 continue;
435 }
436
437 if (is_group) {
438 /* Detect the case where an input is plugged into a hidden value socket.
439 * In this case we should just remove the link to trigger the socket default override. */
441 }
442
443 if (ntree_shader_expand_socket_default(localtree, node, socket)) {
444 link_added = true;
445 }
446 }
447 }
448 }
449
450 if (link_added) {
452 }
453}
454
456{
457 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
458 if (node->is_group()) {
459 if (node->id != nullptr) {
460 ntree_shader_groups_remove_muted_links(reinterpret_cast<bNodeTree *>(node->id));
461 }
462 }
463 }
464 LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
465 if (link->flag & NODE_LINK_MUTED) {
466 blender::bke::node_remove_link(ntree, *link);
467 }
468 }
469}
470
471static void flatten_group_do(bNodeTree *ntree, bNode *gnode)
472{
473 LinkNode *group_interface_nodes = nullptr;
474 bNodeTree *ngroup = (bNodeTree *)gnode->id;
475
476 /* Add the nodes into the ntree */
477 LISTBASE_FOREACH_MUTABLE (bNode *, node, &ngroup->nodes) {
478 /* Remove interface nodes.
479 * This also removes remaining links to and from interface nodes.
480 * We must delay removal since sockets will reference this node. see: #52092 */
481 if (node->is_group_input() || node->is_group_output()) {
482 BLI_linklist_prepend(&group_interface_nodes, node);
483 }
484 /* migrate node */
485 BLI_remlink(&ngroup->nodes, node);
486 BLI_addtail(&ntree->nodes, node);
487 blender::bke::node_unique_id(*ntree, *node);
488 /* ensure unique node name in the node tree */
489 /* This is very slow and it has no use for GPU nodetree. (see #70609) */
490 // blender::bke::node_unique_name(ntree, node);
491 }
492 ngroup->runtime->nodes_by_id.clear();
493
494 /* Save first and last link to iterate over flattened group links. */
495 bNodeLink *glinks_first = static_cast<bNodeLink *>(ntree->links.last);
496
497 /* Add internal links to the ntree */
498 LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ngroup->links) {
499 BLI_remlink(&ngroup->links, link);
500 BLI_addtail(&ntree->links, link);
501 }
502
503 bNodeLink *glinks_last = static_cast<bNodeLink *>(ntree->links.last);
504
505 /* restore external links to and from the gnode */
506 if (glinks_first != nullptr) {
507 /* input links */
508 for (bNodeLink *link = glinks_first->next; link != glinks_last->next; link = link->next) {
509 if (link->fromnode->is_group_input()) {
510 const char *identifier = link->fromsock->identifier;
511 /* find external links to this input */
512 for (bNodeLink *tlink = static_cast<bNodeLink *>(ntree->links.first);
513 tlink != glinks_first->next;
514 tlink = tlink->next)
515 {
516 if (tlink->tonode == gnode && STREQ(tlink->tosock->identifier, identifier)) {
518 *ntree, *tlink->fromnode, *tlink->fromsock, *link->tonode, *link->tosock);
519 }
520 }
521 }
522 }
523 /* Also iterate over the new links to cover passthrough links. */
524 glinks_last = static_cast<bNodeLink *>(ntree->links.last);
525 /* output links */
526 for (bNodeLink *tlink = static_cast<bNodeLink *>(ntree->links.first);
527 tlink != glinks_first->next;
528 tlink = tlink->next)
529 {
530 if (tlink->fromnode == gnode) {
531 const char *identifier = tlink->fromsock->identifier;
532 /* find internal links to this output */
533 for (bNodeLink *link = glinks_first->next; link != glinks_last->next; link = link->next) {
534 /* only use active output node */
535 if (link->tonode->is_group_output() && (link->tonode->flag & NODE_DO_OUTPUT)) {
536 if (STREQ(link->tosock->identifier, identifier)) {
538 *ntree, *link->fromnode, *link->fromsock, *tlink->tonode, *tlink->tosock);
539 }
540 }
541 }
542 }
543 }
544 }
545
546 while (group_interface_nodes) {
547 bNode *node = static_cast<bNode *>(BLI_linklist_pop(&group_interface_nodes));
549 }
550
552}
553
554/* Flatten group to only have a simple single tree */
556{
557 /* This is effectively recursive as the flattened groups will add
558 * nodes at the end of the list, which will also get evaluated. */
559 for (bNode *node = static_cast<bNode *>(localtree->nodes.first), *node_next; node;
560 node = node_next)
561 {
562 if (node->is_group() && node->id != nullptr) {
563 flatten_group_do(localtree, node);
564 /* Continue even on new flattened nodes. */
565 node_next = node->next;
566 /* delete the group instance and its localtree. */
567 bNodeTree *ngroup = (bNodeTree *)node->id;
570 BLI_assert(!ngroup->id.py_instance); /* Or call #BKE_libblock_free_data_py. */
571 MEM_freeN(ngroup);
572 }
573 else {
574 node_next = node->next;
575 }
576 }
577
579}
580
582 bool (*node_filter)(const bNode *node);
584};
585
586static bool ntree_branch_count_and_tag_nodes(bNode *fromnode, bNode *tonode, void *userdata)
587{
588 branchIterData *iter = (branchIterData *)userdata;
589 if (fromnode->runtime->tmp_flag == -1 &&
590 (iter->node_filter == nullptr || iter->node_filter(fromnode)))
591 {
592 fromnode->runtime->tmp_flag = iter->node_count;
593 iter->node_count++;
594 }
595 if (tonode->runtime->tmp_flag == -1 &&
596 (iter->node_filter == nullptr || iter->node_filter(tonode)))
597 {
598 tonode->runtime->tmp_flag = iter->node_count;
599 iter->node_count++;
600 }
601 return true;
602}
603
604/* Create a copy of a branch starting from a given node. */
606 bNode *start_node,
607 bool (*node_filter)(const bNode *node))
608{
609 auto gather_branch_nodes = [](bNode *fromnode, bNode * /*tonode*/, void *userdata) {
610 blender::Set<bNode *> *set = static_cast<blender::Set<bNode *> *>(userdata);
611 set->add(fromnode);
612 return true;
613 };
614 blender::Set<bNode *> branch_nodes = {start_node};
616 ntree, start_node, gather_branch_nodes, &branch_nodes, 0);
617
618 /* Initialize `runtime->tmp_flag`. */
619 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
620 node->runtime->tmp_flag = -1;
621 }
622 /* Count and tag all nodes inside the displacement branch of the tree. */
623 branchIterData iter_data;
624 iter_data.node_filter = node_filter;
625 iter_data.node_count = 0;
627 ntree, start_node, ntree_branch_count_and_tag_nodes, &iter_data, 1);
628 /* Copies of the non-filtered nodes on the branch. */
629 Array<bNode *> nodes_copy(iter_data.node_count);
630
631 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
632 if (node->runtime->tmp_flag >= 0) {
633 int id = node->runtime->tmp_flag;
634 /* Avoid creating unique names in the new tree, since it is very slow.
635 * The names on the new nodes will be invalid. */
636 nodes_copy[id] = blender::bke::node_copy(
638 /* But identifiers must be created for the `bNodeTree::all_nodes()` vector,
639 * so they won't match the original. */
640 blender::bke::node_unique_id(*ntree, *nodes_copy[id]);
641
642 bNode *copy = nodes_copy[id];
643 copy->runtime->tmp_flag = -2; /* Copy */
644 copy->runtime->original = node->runtime->original;
645 /* Make sure to clear all sockets links as they are invalid. */
646 LISTBASE_FOREACH (bNodeSocket *, sock, &copy->inputs) {
647 sock->link = nullptr;
648 }
649 LISTBASE_FOREACH (bNodeSocket *, sock, &copy->outputs) {
650 sock->link = nullptr;
651 }
652 }
653 }
654
655 /* Unlink the original nodes from this branch and link the copies. */
656 LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
657 bool from_copy = link->fromnode->runtime->tmp_flag >= 0;
658 bool to_copy = link->tonode->runtime->tmp_flag >= 0;
659 if (from_copy && to_copy) {
660 bNode *from_node = nodes_copy[link->fromnode->runtime->tmp_flag];
661 bNode *to_node = nodes_copy[link->tonode->runtime->tmp_flag];
663 *ntree,
664 *from_node,
665 *ntree_shader_node_find_output(from_node, link->fromsock->identifier),
666 *to_node,
667 *ntree_shader_node_find_input(to_node, link->tosock->identifier));
668 }
669 else if (to_copy) {
670 bNode *to_node = nodes_copy[link->tonode->runtime->tmp_flag];
672 *ntree,
673 *link->fromnode,
674 *link->fromsock,
675 *to_node,
676 *ntree_shader_node_find_input(to_node, link->tosock->identifier));
677 }
678 else if (from_copy && branch_nodes.contains(link->tonode)) {
679 bNode *from_node = nodes_copy[link->fromnode->runtime->tmp_flag];
681 *ntree,
682 *from_node,
683 *ntree_shader_node_find_output(from_node, link->fromsock->identifier),
684 *link->tonode,
685 *link->tosock);
686 blender::bke::node_remove_link(ntree, *link);
687 }
688 }
689}
690
691/* Generate emission node to convert regular data to closure sockets.
692 * Returns validity of the tree.
693 */
695{
696 bool modified = false;
697 LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
698 if ((link->fromsock->type != SOCK_SHADER) && (link->tosock->type == SOCK_SHADER)) {
699 bNode *emission_node = blender::bke::node_add_static_node(nullptr, *ntree, SH_NODE_EMISSION);
700 bNodeSocket *in_sock = ntree_shader_node_find_input(emission_node, "Color");
701 bNodeSocket *out_sock = ntree_shader_node_find_output(emission_node, "Emission");
703 *ntree, *link->fromnode, *link->fromsock, *emission_node, *in_sock);
704 blender::bke::node_add_link(*ntree, *emission_node, *out_sock, *link->tonode, *link->tosock);
705 blender::bke::node_remove_link(ntree, *link);
706 modified = true;
707 }
708 else if ((link->fromsock->type == SOCK_SHADER) && (link->tosock->type != SOCK_SHADER)) {
709 blender::bke::node_remove_link(ntree, *link);
711 modified = true;
712 }
713 }
714 if (modified) {
716 }
717 return true;
718}
719
720/* Socket already has a link to it. Add weights together. */
722 bNode * /*fromnode*/,
723 bNodeSocket *fromsock,
724 bNode **tonode,
725 bNodeSocket **tosock)
726{
727 bNode *addnode = blender::bke::node_add_static_node(nullptr, *ntree, SH_NODE_MATH);
728 addnode->custom1 = NODE_MATH_ADD;
729 addnode->runtime->tmp_flag = -2; /* Copy */
730 bNodeSocket *addsock_out = ntree_shader_node_output_get(addnode, 0);
731 bNodeSocket *addsock_in0 = ntree_shader_node_input_get(addnode, 0);
732 bNodeSocket *addsock_in1 = ntree_shader_node_input_get(addnode, 1);
733 bNodeLink *oldlink = fromsock->link;
735 *ntree, *oldlink->fromnode, *oldlink->fromsock, *addnode, *addsock_in0);
736 blender::bke::node_add_link(*ntree, **tonode, **tosock, *addnode, *addsock_in1);
737 blender::bke::node_remove_link(ntree, *oldlink);
738 *tonode = addnode;
739 *tosock = addsock_out;
740}
741
742static bool ntree_weight_tree_tag_nodes(bNode *fromnode, bNode *tonode, void *userdata)
743{
744 int *node_count = (int *)userdata;
745 bool to_node_from_weight_tree = ELEM(tonode->type_legacy,
751 if (tonode->runtime->tmp_flag == -1 && to_node_from_weight_tree) {
752 tonode->runtime->tmp_flag = *node_count;
753 *node_count += (tonode->type_legacy == SH_NODE_MIX_SHADER) ? 4 : 1;
754 }
755 if (fromnode->runtime->tmp_flag == -1 &&
757 {
758 fromnode->runtime->tmp_flag = *node_count;
759 *node_count += (fromnode->type_legacy == SH_NODE_MIX_SHADER) ? 4 : 1;
760 }
761 return to_node_from_weight_tree;
762}
763
764/* Invert evaluation order of the weight tree (add & mix closure nodes) to feed the closure nodes
765 * with their respective weights. */
766static void ntree_shader_weight_tree_invert(bNodeTree *ntree, bNode *output_node)
767{
768 bNodeLink *displace_link = nullptr;
769 bNodeSocket *displace_output = ntree_shader_node_find_input(output_node, "Displacement");
770 if (displace_output && displace_output->link) {
771 /* Remove any displacement link to avoid tagging it later on. */
772 displace_link = displace_output->link;
773 displace_output->link = nullptr;
774 }
775 bNodeLink *thickness_link = nullptr;
776 bNodeSocket *thickness_output = ntree_shader_node_find_input(output_node, "Thickness");
777 if (thickness_output && thickness_output->link) {
778 /* Remove any thickness link to avoid tagging it later on. */
779 thickness_link = thickness_output->link;
780 thickness_output->link = nullptr;
781 }
782 /* Init tmp flag. */
783 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
784 node->runtime->tmp_flag = -1;
785 }
786 /* Tag nodes from the weight tree. Only tag output node and mix/add shader nodes. */
787 output_node->runtime->tmp_flag = 0;
788 int node_count = 1;
790 ntree, output_node, ntree_weight_tree_tag_nodes, &node_count, 0);
791 /* Make a mirror copy of the weight tree. */
792 Array<bNode *> nodes_copy(node_count);
793 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
794 if (node->runtime->tmp_flag >= 0) {
795 int id = node->runtime->tmp_flag;
796
797 switch (node->type_legacy) {
802 /* Start the tree with full weight. */
803 nodes_copy[id] = blender::bke::node_add_static_node(nullptr, *ntree, SH_NODE_VALUE);
804 nodes_copy[id]->runtime->tmp_flag = -2; /* Copy */
805 ((bNodeSocketValueFloat *)ntree_shader_node_output_get(nodes_copy[id], 0)->default_value)
806 ->value = 1.0f;
807 break;
808 }
809 case SH_NODE_ADD_SHADER: {
810 /* Simple passthrough node. Each original inputs will get the same weight. */
811 /* TODO(fclem): Better use some kind of reroute node? */
812 nodes_copy[id] = blender::bke::node_add_static_node(nullptr, *ntree, SH_NODE_MATH);
813 nodes_copy[id]->custom1 = NODE_MATH_ADD;
814 nodes_copy[id]->runtime->tmp_flag = -2; /* Copy */
815 ((bNodeSocketValueFloat *)ntree_shader_node_input_get(nodes_copy[id], 0)->default_value)
816 ->value = 0.0f;
817 break;
818 }
819 case SH_NODE_MIX_SHADER: {
820 /* We need multiple nodes to emulate the mix node in reverse. */
821 bNode *fromnode, *tonode;
822 bNodeSocket *fromsock, *tosock;
823 int id_start = id;
824 /* output = (factor * input_weight) */
825 nodes_copy[id] = blender::bke::node_add_static_node(nullptr, *ntree, SH_NODE_MATH);
826 nodes_copy[id]->custom1 = NODE_MATH_MULTIPLY;
827 nodes_copy[id]->runtime->tmp_flag = -2; /* Copy */
828 id++;
829 /* output = ((1.0 - factor) * input_weight) <=> (input_weight - factor * input_weight) */
830 nodes_copy[id] = blender::bke::node_add_static_node(nullptr, *ntree, SH_NODE_MATH);
831 nodes_copy[id]->custom1 = NODE_MATH_SUBTRACT;
832 nodes_copy[id]->runtime->tmp_flag = -2; /* Copy */
833 id++;
834 /* Node sanitizes the input mix factor by clamping it. */
835 nodes_copy[id] = blender::bke::node_add_static_node(nullptr, *ntree, SH_NODE_MATH);
836 nodes_copy[id]->custom1 = NODE_MATH_ADD;
837 nodes_copy[id]->custom2 = SHD_MATH_CLAMP;
838 nodes_copy[id]->runtime->tmp_flag = -2; /* Copy */
839 ((bNodeSocketValueFloat *)ntree_shader_node_input_get(nodes_copy[id], 0)->default_value)
840 ->value = 0.0f;
841 /* Copy default value if no link present. */
842 bNodeSocket *fac_sock = ntree_shader_node_find_input(node, "Fac");
843 if (!fac_sock->link) {
844 float default_value = ((bNodeSocketValueFloat *)fac_sock->default_value)->value;
845 bNodeSocket *dst_sock = ntree_shader_node_input_get(nodes_copy[id], 1);
846 ((bNodeSocketValueFloat *)dst_sock->default_value)->value = default_value;
847 }
848 id++;
849 /* Reroute the weight input to the 3 processing nodes. Simplify linking later-on. */
850 /* TODO(fclem): Better use some kind of reroute node? */
851 nodes_copy[id] = blender::bke::node_add_static_node(nullptr, *ntree, SH_NODE_MATH);
852 nodes_copy[id]->custom1 = NODE_MATH_ADD;
853 nodes_copy[id]->runtime->tmp_flag = -2; /* Copy */
854 ((bNodeSocketValueFloat *)ntree_shader_node_input_get(nodes_copy[id], 0)->default_value)
855 ->value = 0.0f;
856 id++;
857 /* Link between nodes for the subtraction. */
858 fromnode = nodes_copy[id_start];
859 tonode = nodes_copy[id_start + 1];
860 fromsock = ntree_shader_node_output_get(fromnode, 0);
861 tosock = ntree_shader_node_input_get(tonode, 1);
862 blender::bke::node_add_link(*ntree, *fromnode, *fromsock, *tonode, *tosock);
863 /* Link mix input to first node. */
864 fromnode = nodes_copy[id_start + 2];
865 tonode = nodes_copy[id_start];
866 fromsock = ntree_shader_node_output_get(fromnode, 0);
867 tosock = ntree_shader_node_input_get(tonode, 1);
868 blender::bke::node_add_link(*ntree, *fromnode, *fromsock, *tonode, *tosock);
869 /* Link weight input to both multiply nodes. */
870 fromnode = nodes_copy[id_start + 3];
871 fromsock = ntree_shader_node_output_get(fromnode, 0);
872 tonode = nodes_copy[id_start];
873 tosock = ntree_shader_node_input_get(tonode, 0);
874 blender::bke::node_add_link(*ntree, *fromnode, *fromsock, *tonode, *tosock);
875 tonode = nodes_copy[id_start + 1];
876 tosock = ntree_shader_node_input_get(tonode, 0);
877 blender::bke::node_add_link(*ntree, *fromnode, *fromsock, *tonode, *tosock);
878 break;
879 }
880 default:
881 BLI_assert(0);
882 break;
883 }
884 }
885 }
886 /* Recreate links between copied nodes. */
887 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
888 if (node->runtime->tmp_flag >= 0) {
889 /* Naming can be confusing here. We use original node-link name for from/to prefix.
890 * The final link is in reversed order. */
891 int socket_index;
892 LISTBASE_FOREACH_INDEX (bNodeSocket *, sock, &node->inputs, socket_index) {
893 bNodeSocket *tosock;
894 bNode *tonode;
895
896 switch (node->type_legacy) {
901 case SH_NODE_ADD_SHADER: {
902 tonode = nodes_copy[node->runtime->tmp_flag];
903 tosock = ntree_shader_node_output_get(tonode, 0);
904 break;
905 }
906 case SH_NODE_MIX_SHADER: {
907 if (socket_index == 0) {
908 /* Mix Factor. */
909 tonode = nodes_copy[node->runtime->tmp_flag + 2];
910 tosock = ntree_shader_node_input_get(tonode, 1);
911 }
912 else if (socket_index == 1) {
913 /* Shader 1. */
914 tonode = nodes_copy[node->runtime->tmp_flag + 1];
915 tosock = ntree_shader_node_output_get(tonode, 0);
916 }
917 else {
918 /* Shader 2. */
919 tonode = nodes_copy[node->runtime->tmp_flag];
920 tosock = ntree_shader_node_output_get(tonode, 0);
921 }
922 break;
923 }
924 default:
925 BLI_assert(0);
926 break;
927 }
928
929 if (sock->link) {
930 bNodeSocket *fromsock;
931 bNode *fromnode = sock->link->fromnode;
932
933 switch (fromnode->type_legacy) {
934 case SH_NODE_ADD_SHADER: {
935 fromnode = nodes_copy[fromnode->runtime->tmp_flag];
936 fromsock = ntree_shader_node_input_get(fromnode, 1);
937 if (fromsock->link) {
938 ntree_weight_tree_merge_weight(ntree, fromnode, fromsock, &tonode, &tosock);
939 }
940 break;
941 }
942 case SH_NODE_MIX_SHADER: {
943 fromnode = nodes_copy[fromnode->runtime->tmp_flag + 3];
944 fromsock = ntree_shader_node_input_get(fromnode, 1);
945 if (fromsock->link) {
946 ntree_weight_tree_merge_weight(ntree, fromnode, fromsock, &tonode, &tosock);
947 }
948 break;
949 }
965 case SH_NODE_EMISSION:
966 case SH_NODE_HOLDOUT:
972 fromsock = ntree_shader_node_find_input(fromnode, "Weight");
973 /* Make "weight" sockets available so that links to it are available as well and are
974 * not ignored in other places. */
975 fromsock->flag &= ~SOCK_UNAVAIL;
976 if (fromsock->link) {
977 ntree_weight_tree_merge_weight(ntree, fromnode, fromsock, &tonode, &tosock);
978 }
979 break;
980 default:
981 fromsock = sock->link->fromsock;
982 break;
983 }
984
985 /* Manually add the link to the socket to avoid calling:
986 * `BKE_ntree_update(G.main, oop)`. */
988 *ntree, *fromnode, *fromsock, *tonode, *tosock);
989 BLI_assert(fromsock->link);
990 }
991 }
992 }
993 }
994 /* Restore displacement & thickness link. */
995 if (displace_link) {
997 *displace_link->fromnode,
998 *displace_link->fromsock,
999 *output_node,
1000 *displace_output);
1001 }
1002 if (thickness_link) {
1004 *thickness_link->fromnode,
1005 *thickness_link->fromsock,
1006 *output_node,
1007 *thickness_output);
1008 }
1010}
1011
1012static bool closure_node_filter(const bNode *node)
1013{
1014 switch (node->type_legacy) {
1015 case SH_NODE_ADD_SHADER:
1016 case SH_NODE_MIX_SHADER:
1017 case SH_NODE_BACKGROUND:
1020 case SH_NODE_BSDF_GLASS:
1023 case SH_NODE_BSDF_HAIR:
1027 case SH_NODE_BSDF_TOON:
1030 case SH_NODE_BSDF_SHEEN:
1032 case SH_NODE_EMISSION:
1033 case SH_NODE_HOLDOUT:
1039 return true;
1040 default:
1041 return false;
1042 }
1043}
1044
1045/* Shader to rgba needs their associated closure duplicated and the weight tree generated for. */
1047{
1048 Vector<bNode *> shader_to_rgba_nodes;
1049 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
1050 if (node->type_legacy == SH_NODE_SHADERTORGB) {
1051 shader_to_rgba_nodes.append(node);
1052 }
1053 }
1054
1055 for (bNode *shader_to_rgba : shader_to_rgba_nodes) {
1056 bNodeSocket *closure_input = ntree_shader_node_input_get(shader_to_rgba, 0);
1057 if (closure_input->link == nullptr) {
1058 continue;
1059 }
1060 ntree_shader_copy_branch(ntree, shader_to_rgba, closure_node_filter);
1062
1063 ntree_shader_weight_tree_invert(ntree, shader_to_rgba);
1064 }
1065}
1066
1068 int16_t &max_depth,
1069 int16_t depth_level = 0)
1070{
1071 if (node->type_legacy == SH_NODE_SHADERTORGB) {
1072 depth_level++;
1073 max_depth = std::max(max_depth, depth_level);
1074 }
1075
1076 if (node->runtime->tmp_flag >= depth_level) {
1077 /* We already iterated this branch at this or a greater depth. */
1078 return;
1079 }
1080 node->runtime->tmp_flag = std::max(node->runtime->tmp_flag, depth_level);
1081
1082 LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
1083 bNodeLink *link = sock->link;
1084 if (link == nullptr) {
1085 continue;
1086 }
1087 if ((link->flag & NODE_LINK_VALID) == 0) {
1088 /* Skip links marked as cyclic. */
1089 continue;
1090 }
1091 iter_shader_to_rgba_depth_count(link->fromnode, max_depth, depth_level);
1092 }
1093}
1094
1095static void shader_node_disconnect_input(bNodeTree *ntree, bNode *node, int index)
1096{
1097 bNodeLink *link = ntree_shader_node_input_get(node, index)->link;
1098 if (link) {
1099 blender::bke::node_remove_link(ntree, *link);
1100 }
1101}
1102
1104 bNode *node,
1105 int factor_socket_index,
1106 int a_socket_index,
1107 int b_socket_index,
1108 bool clamp_factor)
1109{
1110 bNodeSocket *factor_socket = ntree_shader_node_input_get(node, factor_socket_index);
1111 if (factor_socket->link == nullptr) {
1112 float factor = 0.5;
1113
1114 if (factor_socket->type == SOCK_FLOAT) {
1115 factor = factor_socket->default_value_typed<bNodeSocketValueFloat>()->value;
1116 if (clamp_factor) {
1117 factor = clamp_f(factor, 0.0f, 1.0f);
1118 }
1119 }
1120 else if (factor_socket->type == SOCK_VECTOR) {
1121 const float *vfactor = factor_socket->default_value_typed<bNodeSocketValueVector>()->value;
1122 float vfactor_copy[3];
1123 for (int i = 0; i < 3; i++) {
1124 if (clamp_factor) {
1125 vfactor_copy[i] = clamp_f(vfactor[i], 0.0f, 1.0f);
1126 }
1127 else {
1128 vfactor_copy[i] = vfactor[i];
1129 }
1130 }
1131 if (vfactor_copy[0] == vfactor_copy[1] && vfactor_copy[0] == vfactor_copy[2]) {
1132 factor = vfactor_copy[0];
1133 }
1134 }
1135
1136 if (factor == 1.0f && a_socket_index >= 0) {
1137 shader_node_disconnect_input(ntree, node, a_socket_index);
1138 }
1139 else if (factor == 0.0f && b_socket_index >= 0) {
1140 shader_node_disconnect_input(ntree, node, b_socket_index);
1141 }
1142 }
1143}
1144
1146{
1147 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
1148 if (node->typeinfo->type_legacy == SH_NODE_MIX_SHADER) {
1149 shader_node_disconnect_inactive_mix_branch(ntree, node, 0, 1, 2, true);
1150 }
1151 else if (node->typeinfo->type_legacy == SH_NODE_MIX) {
1152 const NodeShaderMix *storage = static_cast<NodeShaderMix *>(node->storage);
1153 if (storage->data_type == SOCK_FLOAT) {
1154 shader_node_disconnect_inactive_mix_branch(ntree, node, 0, 2, 3, storage->clamp_factor);
1155 /* Disconnect links from data_type-specific sockets that are not currently in use */
1156 for (int i : {1, 4, 5, 6, 7}) {
1157 shader_node_disconnect_input(ntree, node, i);
1158 }
1159 }
1160 else if (storage->data_type == SOCK_VECTOR) {
1161 int factor_socket = storage->factor_mode == NODE_MIX_MODE_UNIFORM ? 0 : 1;
1163 ntree, node, factor_socket, 4, 5, storage->clamp_factor);
1164 /* Disconnect links from data_type-specific sockets that are not currently in use */
1165 int unused_factor_socket = factor_socket == 0 ? 1 : 0;
1166 for (int i : {unused_factor_socket, 2, 3, 6, 7}) {
1167 shader_node_disconnect_input(ntree, node, i);
1168 }
1169 }
1170 else if (storage->data_type == SOCK_RGBA) {
1171 /* Branch A can't be optimized-out, since its alpha is always used regardless of factor */
1172 shader_node_disconnect_inactive_mix_branch(ntree, node, 0, -1, 7, storage->clamp_factor);
1173 /* Disconnect links from data_type-specific sockets that are not currently in use */
1174 for (int i : {1, 2, 3, 4, 5}) {
1175 shader_node_disconnect_input(ntree, node, i);
1176 }
1177 }
1178 }
1179 }
1180}
1181
1182static bool ntree_branch_node_tag(bNode *fromnode, bNode *tonode, void * /*userdata*/)
1183{
1184 fromnode->runtime->tmp_flag = 1;
1185 tonode->runtime->tmp_flag = 1;
1186 return true;
1187}
1188
1189/* Avoid adding more node execution when multiple outputs are present. */
1190/* NOTE(@fclem): This is also a workaround for the old EEVEE SSS implementation where only the
1191 * first executed SSS node gets a SSS profile. */
1192static void ntree_shader_pruned_unused(bNodeTree *ntree, bNode *output_node)
1193{
1195
1196 bool changed = false;
1197
1198 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
1199 node->runtime->tmp_flag = 0;
1200 }
1201
1202 /* Avoid deleting the output node if it is the only node in the tree. */
1203 if (output_node) {
1204 output_node->runtime->tmp_flag = 1;
1206 ntree, output_node, ntree_branch_node_tag, nullptr, 0);
1207 }
1208
1209 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
1210 if (node->type_legacy == SH_NODE_OUTPUT_AOV) {
1211 node->runtime->tmp_flag = 1;
1213 }
1214 }
1215
1216 LISTBASE_FOREACH_MUTABLE (bNode *, node, &ntree->nodes) {
1217 if (node->runtime->tmp_flag == 0) {
1219 changed = true;
1220 }
1221 }
1222
1223 if (changed) {
1225 }
1226}
1227
1229{
1231
1234 ntree_shader_groups_flatten(localtree);
1235
1237
1238 /* Tree is valid if it contains no undefined implicit socket type cast. */
1239 bool valid_tree = ntree_shader_implicit_closure_cast(localtree);
1240
1241 if (valid_tree) {
1243 if (output != nullptr) {
1246 }
1247 }
1248
1249 exec = ntreeShaderBeginExecTree(localtree);
1250 /* Execute nodes ordered by the number of ShaderToRGB nodes found in their path,
1251 * so all closures can be properly evaluated. */
1252 int16_t max_depth = 0;
1253 LISTBASE_FOREACH (bNode *, node, &localtree->nodes) {
1254 node->runtime->tmp_flag = -1;
1255 }
1256 if (output != nullptr) {
1258 }
1259 LISTBASE_FOREACH (bNode *, node, &localtree->nodes) {
1260 if (node->type_legacy == SH_NODE_OUTPUT_AOV) {
1261 iter_shader_to_rgba_depth_count(node, max_depth);
1262 }
1263 }
1264 for (int depth = max_depth; depth >= 0; depth--) {
1265 ntreeExecGPUNodes(exec, mat, output, &depth);
1266 LISTBASE_FOREACH (bNode *, node, &localtree->nodes) {
1267 if (node->type_legacy == SH_NODE_OUTPUT_AOV) {
1268 ntreeExecGPUNodes(exec, mat, node, &depth);
1269 }
1270 }
1271 }
1273}
1274
1276 bNodeTree *ntree,
1277 bNodeInstanceKey parent_key)
1278{
1279 /* ensures only a single output node is enabled */
1281
1282 /* common base initialization */
1283 bNodeTreeExec *exec = ntree_exec_begin(context, ntree, parent_key);
1284
1285 /* allocate the thread stack listbase array */
1286 exec->threadstack = MEM_calloc_arrayN<ListBase>(BLENDER_MAX_THREADS, "thread stack array");
1287
1288 LISTBASE_FOREACH (bNode *, node, &exec->nodetree->nodes) {
1289 node->runtime->need_exec = 1;
1290 }
1291
1292 return exec;
1293}
1294
1296{
1297 bNodeExecContext context;
1299
1300 /* XXX hack: prevent exec data from being generated twice.
1301 * this should be handled by the renderer!
1302 */
1303 if (ntree->runtime->execdata) {
1304 return ntree->runtime->execdata;
1305 }
1306
1308
1309 /* XXX: this should not be necessary, but is still used for compositor/shader/texture nodes,
1310 * which only store the `ntree` pointer. Should be fixed at some point!
1311 */
1312 ntree->runtime->execdata = exec;
1313
1314 return exec;
1315}
1316
1318{
1319 if (exec->threadstack) {
1320 for (int a = 0; a < BLENDER_MAX_THREADS; a++) {
1321 LISTBASE_FOREACH (bNodeThreadStack *, nts, &exec->threadstack[a]) {
1322 if (nts->stack) {
1323 MEM_freeN(nts->stack);
1324 }
1325 }
1326 BLI_freelistN(&exec->threadstack[a]);
1327 }
1328
1329 MEM_freeN(exec->threadstack);
1330 exec->threadstack = nullptr;
1331 }
1332
1334}
1335
1337{
1338 if (exec) {
1339 /* exec may get freed, so assign ntree */
1340 bNodeTree *ntree = exec->nodetree;
1342
1343 /* XXX: clear node-tree back-pointer to exec data,
1344 * same problem as noted in #ntreeBeginExecTree. */
1345 ntree->runtime->execdata = nullptr;
1346 }
1347}
SpaceNode * CTX_wm_space_node(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
Object * BKE_view_layer_active_object_get(const ViewLayer *view_layer)
@ LIB_ID_CREATE_NO_USER_REFCOUNT
@ LIB_ID_CREATE_NO_MAIN
Blender kernel freestyle line style functionality.
FreestyleLineStyle * BKE_linestyle_active_from_view_layer(struct ViewLayer *view_layer)
Definition linestyle.cc:704
General operations, lookup, etc. for materials.
Material * BKE_object_material_get(Object *ob, short act)
#define NODE_CLASS_OUTPUT
Definition BKE_node.hh:434
#define NODE_CLASS_INTERFACE
Definition BKE_node.hh:445
#define NODE_CLASS_CONVERTER
Definition BKE_node.hh:439
#define NODE_CLASS_OP_VECTOR
Definition BKE_node.hh:436
#define NODE_CLASS_LAYOUT
Definition BKE_node.hh:449
#define NODE_CLASS_OP_COLOR
Definition BKE_node.hh:435
#define NODE_CLASS_INPUT
Definition BKE_node.hh:433
#define NODE_CLASS_GROUP
Definition BKE_node.hh:438
#define NODE_CLASS_TEXTURE
Definition BKE_node.hh:443
#define NODE_CLASS_SHADER
Definition BKE_node.hh:446
#define NODE_CLASS_SCRIPT
Definition BKE_node.hh:444
#define SH_NODE_MIX_SHADER
#define SH_NODE_BSDF_METALLIC
#define SH_NODE_HOLDOUT
#define SH_NODE_VOLUME_COEFFICIENTS
#define SH_NODE_OUTPUT_WORLD
#define SH_NODE_BSDF_PRINCIPLED
#define SH_NODE_EMISSION
#define SH_NODE_BSDF_SHEEN
#define SH_NODE_ADD_SHADER
#define SH_NODE_SUBSURFACE_SCATTERING
#define SH_NODE_VOLUME_ABSORPTION
#define SH_NODE_VECTOR_MATH
#define SH_NODE_VALUE
#define SH_NODE_MATH
#define SH_NODE_BSDF_TOON
#define SH_NODE_BSDF_TRANSPARENT
#define SH_NODE_BSDF_DIFFUSE
#define SH_NODE_SHADERTORGB
#define SH_NODE_OUTPUT_MATERIAL
#define SH_NODE_BSDF_TRANSLUCENT
#define SH_NODE_BSDF_HAIR_PRINCIPLED
#define SH_NODE_BSDF_HAIR
#define SH_NODE_BACKGROUND
#define SH_NODE_BSDF_RAY_PORTAL
#define SH_NODE_BSDF_GLOSSY
#define SH_NODE_MIX
#define SH_NODE_RGB
#define SH_NODE_EEVEE_SPECULAR
#define SH_NODE_BSDF_GLASS
#define SH_NODE_VOLUME_PRINCIPLED
#define SH_NODE_BSDF_REFRACTION
#define SH_NODE_OUTPUT_LIGHT
#define SH_NODE_VOLUME_SCATTER
#define SH_NODE_RGBTOBW
#define SH_NODE_OUTPUT_AOV
void BKE_ntree_update_after_single_tree_change(Main &bmain, bNodeTree &modified_tree, const NodeTreeUpdateExtraParams &params={})
void BKE_ntree_update_tag_all(bNodeTree *ntree)
bool BKE_scene_use_shading_nodes_custom(Scene *scene)
Definition scene.cc:2809
#define BLI_assert(a)
Definition BLI_assert.h:46
void * BLI_findlink(const ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:534
#define LISTBASE_FOREACH(type, var, list)
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:497
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:131
MINLINE float clamp_f(float value, float min, float max)
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:16
#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
@ NTREE_SHADER
@ SHD_MATH_CLAMP
@ NODE_DO_OUTPUT
@ NODE_MIX_MODE_UNIFORM
@ SOCK_HIDE_VALUE
@ SOCK_UNAVAIL
@ NODE_LINK_MUTED
@ NODE_LINK_VALID
eNodeSocketDatatype
@ SOCK_INT
@ SOCK_VECTOR
@ SOCK_BOOLEAN
@ SOCK_SHADER
@ SOCK_FLOAT
@ SOCK_RGBA
@ OB_LAMP
@ SNODE_SHADER_LINESTYLE
@ SNODE_SHADER_OBJECT
struct blender::bke::bNodeTreeType * ntreeType_Shader
#define C
Definition RandGen.cpp:29
bool contains(const Key &key) const
Definition BLI_set.hh:310
bool add(const Key &key)
Definition BLI_set.hh:248
void append(const T &value)
#define output
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
#define G(x, y, z)
void node_tree_free_local_node(bNodeTree &ntree, bNode &node)
Definition node.cc:4635
void node_tree_set_output(bNodeTree &ntree)
Definition node.cc:4742
void node_tree_free_tree(bNodeTree &ntree)
Definition node.cc:4718
void node_unique_id(bNodeTree &ntree, bNode &node)
Definition node.cc:3770
bNode * node_copy(bNodeTree *dst_tree, const bNode &src_node, int flag, bool use_unique)
Definition node.cc:4070
void node_remove_link(bNodeTree *ntree, bNodeLink &link)
Definition node.cc:4124
void node_chain_iterator_backwards(const bNodeTree *ntree, const bNode *node_start, bool(*callback)(bNode *, bNode *, void *), void *userdata, int recursion_lvl)
Definition node.cc:3732
void node_tree_type_add(bNodeTreeType &nt)
Definition node.cc:2672
void node_internal_relink(bNodeTree &ntree, bNode &node)
Definition node.cc:4185
const bNodeInstanceKey NODE_INSTANCE_KEY_BASE
Definition node.cc:5118
void(*)(void *calldata, int nclass, StringRefNull name) bNodeClassCallback
Definition BKE_node.hh:478
bNode * node_add_static_node(const bContext *C, bNodeTree &ntree, int type)
Definition node.cc:3804
bNodeLink & node_add_link(bNodeTree &ntree, bNode &fromnode, bNodeSocket &fromsock, bNode &tonode, bNodeSocket &tosock)
Definition node.cc:4087
bool node_is_static_socket_type(const bNodeSocketType &stype)
Definition node.cc:3158
void ntree_update_reroute_nodes(bNodeTree *ntree)
static void localize(bNodeTree *localtree, bNodeTree *ntree)
static void update(bNodeTree *ntree)
static void foreach_nodeclass(void *calldata, blender::bke::bNodeClassCallback func)
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:233
static bNodeSocket * ntree_shader_node_input_get(bNode *node, int n)
static bool ntree_shader_implicit_closure_cast(bNodeTree *ntree)
static bool ntree_branch_count_and_tag_nodes(bNode *fromnode, bNode *tonode, void *userdata)
bNodeTreeExec * ntreeShaderBeginExecTree_internal(bNodeExecContext *context, bNodeTree *ntree, bNodeInstanceKey parent_key)
static bool ntree_weight_tree_tag_nodes(bNode *fromnode, bNode *tonode, void *userdata)
static bNodeSocket * ntree_shader_node_find_output(bNode *node, const char *identifier)
static void ntree_weight_tree_merge_weight(bNodeTree *ntree, bNode *, bNodeSocket *fromsock, bNode **tonode, bNodeSocket **tosock)
static bool ntree_shader_expand_socket_default(bNodeTree *localtree, bNode *node, bNodeSocket *socket)
static void iter_shader_to_rgba_depth_count(bNode *node, int16_t &max_depth, int16_t depth_level=0)
static void ntree_shader_disconnect_inactive_mix_branches(bNodeTree *ntree)
static void ntree_shader_groups_expand_inputs(bNodeTree *localtree)
static void ntree_shader_shader_to_rgba_branches(bNodeTree *ntree)
static bNodeSocket * ntree_shader_node_find_input(bNode *node, const char *identifier)
static void ntree_shader_groups_flatten(bNodeTree *localtree)
static void shader_node_disconnect_inactive_mix_branch(bNodeTree *ntree, bNode *node, int factor_socket_index, int a_socket_index, int b_socket_index, bool clamp_factor)
static bool closure_node_filter(const bNode *node)
static void ntree_shader_weight_tree_invert(bNodeTree *ntree, bNode *output_node)
static bool shader_node_tree_socket_type_valid(blender::bke::bNodeTreeType *, blender::bke::bNodeSocketType *socket_type)
void register_node_tree_type_sh()
static void update(bNodeTree *ntree)
bNode * ntreeShaderOutputNode(bNodeTree *ntree, int target)
static bNodeSocket * ntree_shader_node_find_socket(ListBase *sockets, const char *identifier)
static void shader_get_from_context(const bContext *C, blender::bke::bNodeTreeType *, bNodeTree **r_ntree, ID **r_id, ID **r_from)
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 bool ntree_branch_node_tag(bNode *fromnode, bNode *tonode, void *)
static void ntree_shader_copy_branch(bNodeTree *ntree, bNode *start_node, bool(*node_filter)(const bNode *node))
bNodeTreeExec * ntreeShaderBeginExecTree(bNodeTree *ntree)
static void flatten_group_do(bNodeTree *ntree, bNode *gnode)
static bool shader_tree_poll(const bContext *C, blender::bke::bNodeTreeType *)
static void ntree_shader_groups_remove_muted_links(bNodeTree *ntree)
void ntreeShaderEndExecTree(bNodeTreeExec *exec)
static void shader_node_disconnect_input(bNodeTree *ntree, bNode *node, int index)
static bNodeSocket * ntree_shader_node_output_get(bNode *node, int n)
static void localize(bNodeTree *localtree, bNodeTree *)
void ntreeShaderEndExecTree_internal(bNodeTreeExec *exec)
static void foreach_nodeclass(void *calldata, blender::bke::bNodeClassCallback func)
void ntreeExecGPUNodes(bNodeTreeExec *exec, GPUMaterial *mat, bNode *output_node, const int *depth_level)
static void exec(void *data, int, bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
static void copy(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node)
const char * RE_engine_id_CYCLES
Definition scene.cc:1628
StructRNA * srna
Definition RNA_types.hh:909
struct bNodeTree * nodetree
Definition DNA_ID.h:404
void * py_instance
Definition DNA_ID.h:483
void * last
void * first
struct bNodeTree * nodetree
char engine[32]
struct RenderData r
struct World * world
struct bNodeTree * nodetree
struct bNodeLink * link
struct bNodeSocket * next
void * default_value
char identifier[64]
bNodeTreeRuntimeHandle * runtime
ListBase nodes
ListBase links
int16_t custom1
ListBase inputs
struct ID * id
int16_t type_legacy
bNodeRuntimeHandle * runtime
ListBase outputs
int32_t identifier
Defines a socket type.
Definition BKE_node.hh:152
eNodeSocketDatatype type
Definition BKE_node.hh:187
void(* update)(bNodeTree *ntree)
Definition BKE_node.hh:508
void(* foreach_nodeclass)(void *calldata, bNodeClassCallback func)
Definition BKE_node.hh:493
bool(* poll)(const bContext *C, bNodeTreeType *ntreetype)
Definition BKE_node.hh:495
void(* get_from_context)(const bContext *C, bNodeTreeType *ntreetype, bNodeTree **r_ntree, ID **r_id, ID **r_from)
Definition BKE_node.hh:497
void(* localize)(bNodeTree *localtree, bNodeTree *ntree)
Definition BKE_node.hh:504
bool(* validate_link)(eNodeSocketDatatype from, eNodeSocketDatatype to)
Definition BKE_node.hh:510
bool(* valid_socket_type)(bNodeTreeType *ntreetype, bNodeSocketType *socket_type)
Definition BKE_node.hh:515
bool(* node_filter)(const bNode *node)
void * ntreeGPUMaterialNodes
Definition stubs.c:42
i
Definition text_draw.cc:230
#define N_(msgid)