Blender V4.3
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
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_string.h"
25#include "BLI_threads.h"
26#include "BLI_utildefines.h"
27#include "BLI_vector.hh"
28
29#include "BKE_context.hh"
30#include "BKE_global.hh"
31#include "BKE_layer.hh"
32#include "BKE_lib_id.hh"
33#include "BKE_linestyle.h"
34#include "BKE_material.h"
35#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
65static void shader_get_from_context(const bContext *C,
66 blender::bke::bNodeTreeType * /*treetype*/,
67 bNodeTree **r_ntree,
68 ID **r_id,
69 ID **r_from)
70{
71 SpaceNode *snode = CTX_wm_space_node(C);
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->flag & NODE_MUTED || node->type == NODE_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_cnew<blender::bke::bNodeTreeType>(
180 "shader node tree type");
181
182 tt->type = NTREE_SHADER;
183 STRNCPY(tt->idname, "ShaderNodeTree");
184 STRNCPY(tt->group_idname, "ShaderNodeGroup");
185 STRNCPY(tt->ui_name, N_("Shader Editor"));
186 tt->ui_icon = ICON_NODE_MATERIAL;
187 STRNCPY(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) {
215 continue;
216 }
217
218 if (node->custom1 == SHD_OUTPUT_ALL) {
219 if (output_node == nullptr) {
220 output_node = node;
221 }
222 else if (output_node->custom1 == SHD_OUTPUT_ALL) {
223 if ((node->flag & NODE_DO_OUTPUT) && !(output_node->flag & NODE_DO_OUTPUT)) {
224 output_node = node;
225 }
226 }
227 }
228 else if (node->custom1 == target) {
229 if (output_node == nullptr) {
230 output_node = node;
231 }
232 else if (output_node->custom1 == SHD_OUTPUT_ALL) {
233 output_node = node;
234 }
235 else if ((node->flag & NODE_DO_OUTPUT) && !(output_node->flag & NODE_DO_OUTPUT)) {
236 output_node = node;
237 }
238 }
239 }
240
241 return output_node;
242}
243
244/* Find socket with a specified identifier. */
245static bNodeSocket *ntree_shader_node_find_socket(ListBase *sockets, const char *identifier)
246{
247 LISTBASE_FOREACH (bNodeSocket *, sock, sockets) {
248 if (STREQ(sock->identifier, identifier)) {
249 return sock;
250 }
251 }
252 return nullptr;
253}
254
255/* Find input socket with a specified identifier. */
256static bNodeSocket *ntree_shader_node_find_input(bNode *node, const char *identifier)
257{
258 return ntree_shader_node_find_socket(&node->inputs, identifier);
259}
260
261/* Find output socket with a specified identifier. */
262static bNodeSocket *ntree_shader_node_find_output(bNode *node, const char *identifier)
263{
264 return ntree_shader_node_find_socket(&node->outputs, identifier);
265}
266
267/* Find input socket at a specific position. */
269{
270 return reinterpret_cast<bNodeSocket *>(BLI_findlink(&node->inputs, n));
271}
272
273/* Find output socket at a specific position. */
275{
276 return reinterpret_cast<bNodeSocket *>(BLI_findlink(&node->outputs, n));
277}
278
279/* Return true on success. */
281 bNode *node,
282 bNodeSocket *socket)
283{
284 bNode *value_node;
285 bNodeSocket *value_socket;
286 bNodeSocketValueVector *src_vector;
287 bNodeSocketValueRGBA *src_rgba, *dst_rgba;
288 bNodeSocketValueFloat *src_float, *dst_float;
289 bNodeSocketValueInt *src_int;
290 bNodeSocketValueBoolean *src_bool;
291
292 switch (socket->type) {
293 case SOCK_VECTOR:
294 value_node = blender::bke::node_add_static_node(nullptr, localtree, SH_NODE_RGB);
295 value_socket = ntree_shader_node_find_output(value_node, "Color");
296 BLI_assert(value_socket != nullptr);
297 src_vector = static_cast<bNodeSocketValueVector *>(socket->default_value);
298 dst_rgba = static_cast<bNodeSocketValueRGBA *>(value_socket->default_value);
299 copy_v3_v3(dst_rgba->value, src_vector->value);
300 dst_rgba->value[3] = 1.0f; /* should never be read */
301 break;
302 case SOCK_RGBA:
303 value_node = blender::bke::node_add_static_node(nullptr, localtree, SH_NODE_RGB);
304 value_socket = ntree_shader_node_find_output(value_node, "Color");
305 BLI_assert(value_socket != nullptr);
306 src_rgba = static_cast<bNodeSocketValueRGBA *>(socket->default_value);
307 dst_rgba = static_cast<bNodeSocketValueRGBA *>(value_socket->default_value);
308 copy_v4_v4(dst_rgba->value, src_rgba->value);
309 break;
310 case SOCK_BOOLEAN:
311 /* HACK: Support as float. */
312 value_node = blender::bke::node_add_static_node(nullptr, localtree, SH_NODE_VALUE);
313 value_socket = ntree_shader_node_find_output(value_node, "Value");
314 BLI_assert(value_socket != nullptr);
315 src_bool = static_cast<bNodeSocketValueBoolean *>(socket->default_value);
316 dst_float = static_cast<bNodeSocketValueFloat *>(value_socket->default_value);
317 dst_float->value = float(src_bool->value);
318 break;
319 case SOCK_INT:
320 /* HACK: Support as float. */
321 value_node = blender::bke::node_add_static_node(nullptr, localtree, SH_NODE_VALUE);
322 value_socket = ntree_shader_node_find_output(value_node, "Value");
323 BLI_assert(value_socket != nullptr);
324 src_int = static_cast<bNodeSocketValueInt *>(socket->default_value);
325 dst_float = static_cast<bNodeSocketValueFloat *>(value_socket->default_value);
326 dst_float->value = float(src_int->value);
327 break;
328 case SOCK_FLOAT:
329 value_node = blender::bke::node_add_static_node(nullptr, localtree, SH_NODE_VALUE);
330 value_socket = ntree_shader_node_find_output(value_node, "Value");
331 BLI_assert(value_socket != nullptr);
332 src_float = static_cast<bNodeSocketValueFloat *>(socket->default_value);
333 dst_float = static_cast<bNodeSocketValueFloat *>(value_socket->default_value);
334 dst_float->value = src_float->value;
335 break;
336 default:
337 return false;
338 }
339 blender::bke::node_add_link(localtree, value_node, value_socket, node, socket);
340 return true;
341}
342
344{
345 bNodeTree *group_ntree = (bNodeTree *)group_node->id;
346 bool removed_link = false;
347
348 LISTBASE_FOREACH (bNode *, node, &group_ntree->nodes) {
349 const bool is_group = ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && (node->id != nullptr);
350
351 LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
352 if (!is_group && (sock->flag & SOCK_HIDE_VALUE) == 0) {
353 continue;
354 }
355 /* If socket is linked to a group input node and sockets id match. */
356 if (sock && sock->link && sock->link->fromnode->type == NODE_GROUP_INPUT) {
357 if (STREQ(isock->identifier, sock->link->fromsock->identifier)) {
358 if (is_group) {
359 /* Recursively unlink sockets within the nested group. */
361 }
362 else {
363 blender::bke::node_remove_link(group_ntree, sock->link);
364 removed_link = true;
365 }
366 }
367 }
368 }
369 }
370
371 if (removed_link) {
372 BKE_ntree_update_main_tree(G.main, group_ntree, nullptr);
373 }
374}
375
376/* Node groups once expanded looses their input sockets values.
377 * To fix this, link value/rgba nodes into the sockets and copy the group sockets values. */
379{
380 bool link_added = false;
381
382 LISTBASE_FOREACH (bNode *, node, &localtree->nodes) {
383 const bool is_group = ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && (node->id != nullptr);
384 const bool is_group_output = node->type == NODE_GROUP_OUTPUT && (node->flag & NODE_DO_OUTPUT);
385
386 if (is_group) {
387 /* Do it recursively. */
389 }
390
391 if (is_group || is_group_output) {
392 LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) {
393 if (socket->link != nullptr && !(socket->link->flag & NODE_LINK_MUTED)) {
394 bNodeLink *link = socket->link;
395 /* Fix the case where the socket is actually converting the data. (see #71374)
396 * We only do the case of lossy conversion to float. */
397 if ((socket->type == SOCK_FLOAT) && (link->fromsock->type != link->tosock->type)) {
398 if (link->fromsock->type == SOCK_RGBA) {
399 bNode *tmp = blender::bke::node_add_static_node(nullptr, localtree, SH_NODE_RGBTOBW);
401 link->fromnode,
402 link->fromsock,
403 tmp,
404 static_cast<bNodeSocket *>(tmp->inputs.first));
406 localtree, tmp, static_cast<bNodeSocket *>(tmp->outputs.first), node, socket);
407 }
408 else if (link->fromsock->type == SOCK_VECTOR) {
410 nullptr, localtree, SH_NODE_VECTOR_MATH);
412 bNodeSocket *dot_input1 = static_cast<bNodeSocket *>(tmp->inputs.first);
413 bNodeSocket *dot_input2 = static_cast<bNodeSocket *>(dot_input1->next);
414 bNodeSocketValueVector *input2_socket_value = static_cast<bNodeSocketValueVector *>(
415 dot_input2->default_value);
416 copy_v3_fl(input2_socket_value->value, 1.0f / 3.0f);
418 localtree, link->fromnode, link->fromsock, tmp, dot_input1);
420 localtree, tmp, static_cast<bNodeSocket *>(tmp->outputs.last), node, socket);
421 }
422 }
423 continue;
424 }
425
426 if (is_group) {
427 /* Detect the case where an input is plugged into a hidden value socket.
428 * In this case we should just remove the link to trigger the socket default override. */
430 }
431
432 if (ntree_shader_expand_socket_default(localtree, node, socket)) {
433 link_added = true;
434 }
435 }
436 }
437 }
438
439 if (link_added) {
440 BKE_ntree_update_main_tree(G.main, localtree, nullptr);
441 }
442}
443
445{
446 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
447 if (node->type == NODE_GROUP) {
448 if (node->id != nullptr) {
449 ntree_shader_groups_remove_muted_links(reinterpret_cast<bNodeTree *>(node->id));
450 }
451 }
452 }
453 LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
454 if (link->flag & NODE_LINK_MUTED) {
456 }
457 }
458}
459
460static void flatten_group_do(bNodeTree *ntree, bNode *gnode)
461{
462 LinkNode *group_interface_nodes = nullptr;
463 bNodeTree *ngroup = (bNodeTree *)gnode->id;
464
465 /* Add the nodes into the ntree */
466 LISTBASE_FOREACH_MUTABLE (bNode *, node, &ngroup->nodes) {
467 /* Remove interface nodes.
468 * This also removes remaining links to and from interface nodes.
469 * We must delay removal since sockets will reference this node. see: #52092 */
470 if (ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT)) {
471 BLI_linklist_prepend(&group_interface_nodes, node);
472 }
473 /* migrate node */
474 BLI_remlink(&ngroup->nodes, node);
475 BLI_addtail(&ntree->nodes, node);
476 blender::bke::node_unique_id(ntree, node);
477 /* ensure unique node name in the node tree */
478 /* This is very slow and it has no use for GPU nodetree. (see #70609) */
479 // blender::bke::node_unique_name(ntree, node);
480 }
481 ngroup->runtime->nodes_by_id.clear();
482
483 /* Save first and last link to iterate over flattened group links. */
484 bNodeLink *glinks_first = static_cast<bNodeLink *>(ntree->links.last);
485
486 /* Add internal links to the ntree */
487 LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ngroup->links) {
488 BLI_remlink(&ngroup->links, link);
489 BLI_addtail(&ntree->links, link);
490 }
491
492 bNodeLink *glinks_last = static_cast<bNodeLink *>(ntree->links.last);
493
494 /* restore external links to and from the gnode */
495 if (glinks_first != nullptr) {
496 /* input links */
497 for (bNodeLink *link = glinks_first->next; link != glinks_last->next; link = link->next) {
498 if (link->fromnode->type == NODE_GROUP_INPUT) {
499 const char *identifier = link->fromsock->identifier;
500 /* find external links to this input */
501 for (bNodeLink *tlink = static_cast<bNodeLink *>(ntree->links.first);
502 tlink != glinks_first->next;
503 tlink = tlink->next)
504 {
505 if (tlink->tonode == gnode && STREQ(tlink->tosock->identifier, identifier)) {
507 ntree, tlink->fromnode, tlink->fromsock, link->tonode, link->tosock);
508 }
509 }
510 }
511 }
512 /* Also iterate over the new links to cover passthrough links. */
513 glinks_last = static_cast<bNodeLink *>(ntree->links.last);
514 /* output links */
515 for (bNodeLink *tlink = static_cast<bNodeLink *>(ntree->links.first);
516 tlink != glinks_first->next;
517 tlink = tlink->next)
518 {
519 if (tlink->fromnode == gnode) {
520 const char *identifier = tlink->fromsock->identifier;
521 /* find internal links to this output */
522 for (bNodeLink *link = glinks_first->next; link != glinks_last->next; link = link->next) {
523 /* only use active output node */
524 if (link->tonode->type == NODE_GROUP_OUTPUT && (link->tonode->flag & NODE_DO_OUTPUT)) {
525 if (STREQ(link->tosock->identifier, identifier)) {
527 ntree, link->fromnode, link->fromsock, tlink->tonode, tlink->tosock);
528 }
529 }
530 }
531 }
532 }
533 }
534
535 while (group_interface_nodes) {
536 bNode *node = static_cast<bNode *>(BLI_linklist_pop(&group_interface_nodes));
538 }
539
541}
542
543/* Flatten group to only have a simple single tree */
545{
546 /* This is effectively recursive as the flattened groups will add
547 * nodes at the end of the list, which will also get evaluated. */
548 for (bNode *node = static_cast<bNode *>(localtree->nodes.first), *node_next; node;
549 node = node_next)
550 {
551 if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && node->id != nullptr) {
552 flatten_group_do(localtree, node);
553 /* Continue even on new flattened nodes. */
554 node_next = node->next;
555 /* delete the group instance and its localtree. */
556 bNodeTree *ngroup = (bNodeTree *)node->id;
559 BLI_assert(!ngroup->id.py_instance); /* Or call #BKE_libblock_free_data_py. */
560 MEM_freeN(ngroup);
561 }
562 else {
563 node_next = node->next;
564 }
565 }
566
567 BKE_ntree_update_main_tree(G.main, localtree, nullptr);
568}
569
571 bool (*node_filter)(const bNode *node);
573};
574
575static bool ntree_branch_count_and_tag_nodes(bNode *fromnode, bNode *tonode, void *userdata)
576{
577 branchIterData *iter = (branchIterData *)userdata;
578 if (fromnode->runtime->tmp_flag == -1 &&
579 (iter->node_filter == nullptr || iter->node_filter(fromnode)))
580 {
581 fromnode->runtime->tmp_flag = iter->node_count;
582 iter->node_count++;
583 }
584 if (tonode->runtime->tmp_flag == -1 &&
585 (iter->node_filter == nullptr || iter->node_filter(tonode)))
586 {
587 tonode->runtime->tmp_flag = iter->node_count;
588 iter->node_count++;
589 }
590 return true;
591}
592
593/* Create a copy of a branch starting from a given node. */
595 bNode *start_node,
596 bool (*node_filter)(const bNode *node))
597{
598 auto gather_branch_nodes = [](bNode *fromnode, bNode * /*tonode*/, void *userdata) {
599 blender::Set<bNode *> *set = static_cast<blender::Set<bNode *> *>(userdata);
600 set->add(fromnode);
601 return true;
602 };
603 blender::Set<bNode *> branch_nodes = {start_node};
605 ntree, start_node, gather_branch_nodes, &branch_nodes, 0);
606
607 /* Initialize `runtime->tmp_flag`. */
608 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
609 node->runtime->tmp_flag = -1;
610 }
611 /* Count and tag all nodes inside the displacement branch of the tree. */
612 branchIterData iter_data;
613 iter_data.node_filter = node_filter;
614 iter_data.node_count = 0;
616 ntree, start_node, ntree_branch_count_and_tag_nodes, &iter_data, 1);
617 /* Copies of the non-filtered nodes on the branch. */
618 Array<bNode *> nodes_copy(iter_data.node_count);
619
620 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
621 if (node->runtime->tmp_flag >= 0) {
622 int id = node->runtime->tmp_flag;
623 /* Avoid creating unique names in the new tree, since it is very slow.
624 * The names on the new nodes will be invalid. */
625 nodes_copy[id] = blender::bke::node_copy(
627 /* But identifiers must be created for the `bNodeTree::all_nodes()` vector,
628 * so they won't match the original. */
629 blender::bke::node_unique_id(ntree, nodes_copy[id]);
630
631 bNode *copy = nodes_copy[id];
632 copy->runtime->tmp_flag = -2; /* Copy */
633 copy->runtime->original = node->runtime->original;
634 /* Make sure to clear all sockets links as they are invalid. */
635 LISTBASE_FOREACH (bNodeSocket *, sock, &copy->inputs) {
636 sock->link = nullptr;
637 }
638 LISTBASE_FOREACH (bNodeSocket *, sock, &copy->outputs) {
639 sock->link = nullptr;
640 }
641 }
642 }
643
644 /* Unlink the original nodes from this branch and link the copies. */
645 LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
646 bool from_copy = link->fromnode->runtime->tmp_flag >= 0;
647 bool to_copy = link->tonode->runtime->tmp_flag >= 0;
648 if (from_copy && to_copy) {
649 bNode *from_node = nodes_copy[link->fromnode->runtime->tmp_flag];
650 bNode *to_node = nodes_copy[link->tonode->runtime->tmp_flag];
652 ntree,
653 from_node,
654 ntree_shader_node_find_output(from_node, link->fromsock->identifier),
655 to_node,
656 ntree_shader_node_find_input(to_node, link->tosock->identifier));
657 }
658 else if (to_copy) {
659 bNode *to_node = nodes_copy[link->tonode->runtime->tmp_flag];
661 link->fromnode,
662 link->fromsock,
663 to_node,
664 ntree_shader_node_find_input(to_node, link->tosock->identifier));
665 }
666 else if (from_copy && branch_nodes.contains(link->tonode)) {
667 bNode *from_node = nodes_copy[link->fromnode->runtime->tmp_flag];
669 ntree,
670 from_node,
671 ntree_shader_node_find_output(from_node, link->fromsock->identifier),
672 link->tonode,
673 link->tosock);
675 }
676 }
677}
678
679/* Generate emission node to convert regular data to closure sockets.
680 * Returns validity of the tree.
681 */
683{
684 bool modified = false;
685 LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
686 if ((link->fromsock->type != SOCK_SHADER) && (link->tosock->type == SOCK_SHADER)) {
687 bNode *emission_node = blender::bke::node_add_static_node(nullptr, ntree, SH_NODE_EMISSION);
688 bNodeSocket *in_sock = ntree_shader_node_find_input(emission_node, "Color");
689 bNodeSocket *out_sock = ntree_shader_node_find_output(emission_node, "Emission");
690 blender::bke::node_add_link(ntree, link->fromnode, link->fromsock, emission_node, in_sock);
691 blender::bke::node_add_link(ntree, emission_node, out_sock, link->tonode, link->tosock);
693 modified = true;
694 }
695 else if ((link->fromsock->type == SOCK_SHADER) && (link->tosock->type != SOCK_SHADER)) {
696 /* Meh. Not directly visible to the user. But better than nothing. */
697 fprintf(stderr, "Shader Nodetree Error: Invalid implicit socket conversion\n");
698 BKE_ntree_update_main_tree(G.main, ntree, nullptr);
699 return false;
700 }
701 }
702 if (modified) {
703 BKE_ntree_update_main_tree(G.main, ntree, nullptr);
704 }
705 return true;
706}
707
708/* Socket already has a link to it. Add weights together. */
710 bNode * /*fromnode*/,
711 bNodeSocket *fromsock,
712 bNode **tonode,
713 bNodeSocket **tosock)
714{
715 bNode *addnode = blender::bke::node_add_static_node(nullptr, ntree, SH_NODE_MATH);
716 addnode->custom1 = NODE_MATH_ADD;
717 addnode->runtime->tmp_flag = -2; /* Copy */
718 bNodeSocket *addsock_out = ntree_shader_node_output_get(addnode, 0);
719 bNodeSocket *addsock_in0 = ntree_shader_node_input_get(addnode, 0);
720 bNodeSocket *addsock_in1 = ntree_shader_node_input_get(addnode, 1);
721 bNodeLink *oldlink = fromsock->link;
722 blender::bke::node_add_link(ntree, oldlink->fromnode, oldlink->fromsock, addnode, addsock_in0);
723 blender::bke::node_add_link(ntree, *tonode, *tosock, addnode, addsock_in1);
724 blender::bke::node_remove_link(ntree, oldlink);
725 *tonode = addnode;
726 *tosock = addsock_out;
727}
728
729static bool ntree_weight_tree_tag_nodes(bNode *fromnode, bNode *tonode, void *userdata)
730{
731 int *node_count = (int *)userdata;
732 bool to_node_from_weight_tree = ELEM(tonode->type,
733 SH_NODE_ADD_SHADER,
734 SH_NODE_MIX_SHADER,
738 if (tonode->runtime->tmp_flag == -1 && to_node_from_weight_tree) {
739 tonode->runtime->tmp_flag = *node_count;
740 *node_count += (tonode->type == SH_NODE_MIX_SHADER) ? 4 : 1;
741 }
742 if (fromnode->runtime->tmp_flag == -1 &&
743 ELEM(fromnode->type, SH_NODE_ADD_SHADER, SH_NODE_MIX_SHADER))
744 {
745 fromnode->runtime->tmp_flag = *node_count;
746 *node_count += (fromnode->type == SH_NODE_MIX_SHADER) ? 4 : 1;
747 }
748 return to_node_from_weight_tree;
749}
750
751/* Invert evaluation order of the weight tree (add & mix closure nodes) to feed the closure nodes
752 * with their respective weights. */
753static void ntree_shader_weight_tree_invert(bNodeTree *ntree, bNode *output_node)
754{
755 bNodeLink *displace_link = nullptr;
756 bNodeSocket *displace_output = ntree_shader_node_find_input(output_node, "Displacement");
757 if (displace_output && displace_output->link) {
758 /* Remove any displacement link to avoid tagging it later on. */
759 displace_link = displace_output->link;
760 displace_output->link = nullptr;
761 }
762 bNodeLink *thickness_link = nullptr;
763 bNodeSocket *thickness_output = ntree_shader_node_find_input(output_node, "Thickness");
764 if (thickness_output && thickness_output->link) {
765 /* Remove any thickness link to avoid tagging it later on. */
766 thickness_link = thickness_output->link;
767 thickness_output->link = nullptr;
768 }
769 /* Init tmp flag. */
770 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
771 node->runtime->tmp_flag = -1;
772 }
773 /* Tag nodes from the weight tree. Only tag output node and mix/add shader nodes. */
774 output_node->runtime->tmp_flag = 0;
775 int node_count = 1;
777 ntree, output_node, ntree_weight_tree_tag_nodes, &node_count, 0);
778 /* Make a mirror copy of the weight tree. */
779 Array<bNode *> nodes_copy(node_count);
780 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
781 if (node->runtime->tmp_flag >= 0) {
782 int id = node->runtime->tmp_flag;
783
784 switch (node->type) {
789 /* Start the tree with full weight. */
790 nodes_copy[id] = blender::bke::node_add_static_node(nullptr, ntree, SH_NODE_VALUE);
791 nodes_copy[id]->runtime->tmp_flag = -2; /* Copy */
793 ->value = 1.0f;
794 break;
795 }
796 case SH_NODE_ADD_SHADER: {
797 /* Simple passthrough node. Each original inputs will get the same weight. */
798 /* TODO(fclem): Better use some kind of reroute node? */
799 nodes_copy[id] = blender::bke::node_add_static_node(nullptr, ntree, SH_NODE_MATH);
800 nodes_copy[id]->custom1 = NODE_MATH_ADD;
801 nodes_copy[id]->runtime->tmp_flag = -2; /* Copy */
803 ->value = 0.0f;
804 break;
805 }
806 case SH_NODE_MIX_SHADER: {
807 /* We need multiple nodes to emulate the mix node in reverse. */
808 bNode *fromnode, *tonode;
809 bNodeSocket *fromsock, *tosock;
810 int id_start = id;
811 /* output = (factor * input_weight) */
812 nodes_copy[id] = blender::bke::node_add_static_node(nullptr, ntree, SH_NODE_MATH);
813 nodes_copy[id]->custom1 = NODE_MATH_MULTIPLY;
814 nodes_copy[id]->runtime->tmp_flag = -2; /* Copy */
815 id++;
816 /* output = ((1.0 - factor) * input_weight) <=> (input_weight - factor * input_weight) */
817 nodes_copy[id] = blender::bke::node_add_static_node(nullptr, ntree, SH_NODE_MATH);
818 nodes_copy[id]->custom1 = NODE_MATH_SUBTRACT;
819 nodes_copy[id]->runtime->tmp_flag = -2; /* Copy */
820 id++;
821 /* Node sanitizes the input mix factor by clamping it. */
822 nodes_copy[id] = blender::bke::node_add_static_node(nullptr, ntree, SH_NODE_MATH);
823 nodes_copy[id]->custom1 = NODE_MATH_ADD;
824 nodes_copy[id]->custom2 = SHD_MATH_CLAMP;
825 nodes_copy[id]->runtime->tmp_flag = -2; /* Copy */
827 ->value = 0.0f;
828 /* Copy default value if no link present. */
829 bNodeSocket *fac_sock = ntree_shader_node_find_input(node, "Fac");
830 if (!fac_sock->link) {
831 float default_value = ((bNodeSocketValueFloat *)fac_sock->default_value)->value;
832 bNodeSocket *dst_sock = ntree_shader_node_input_get(nodes_copy[id], 1);
833 ((bNodeSocketValueFloat *)dst_sock->default_value)->value = default_value;
834 }
835 id++;
836 /* Reroute the weight input to the 3 processing nodes. Simplify linking later-on. */
837 /* TODO(fclem): Better use some kind of reroute node? */
838 nodes_copy[id] = blender::bke::node_add_static_node(nullptr, ntree, SH_NODE_MATH);
839 nodes_copy[id]->custom1 = NODE_MATH_ADD;
840 nodes_copy[id]->runtime->tmp_flag = -2; /* Copy */
842 ->value = 0.0f;
843 id++;
844 /* Link between nodes for the subtraction. */
845 fromnode = nodes_copy[id_start];
846 tonode = nodes_copy[id_start + 1];
847 fromsock = ntree_shader_node_output_get(fromnode, 0);
848 tosock = ntree_shader_node_input_get(tonode, 1);
849 blender::bke::node_add_link(ntree, fromnode, fromsock, tonode, tosock);
850 /* Link mix input to first node. */
851 fromnode = nodes_copy[id_start + 2];
852 tonode = nodes_copy[id_start];
853 fromsock = ntree_shader_node_output_get(fromnode, 0);
854 tosock = ntree_shader_node_input_get(tonode, 1);
855 blender::bke::node_add_link(ntree, fromnode, fromsock, tonode, tosock);
856 /* Link weight input to both multiply nodes. */
857 fromnode = nodes_copy[id_start + 3];
858 fromsock = ntree_shader_node_output_get(fromnode, 0);
859 tonode = nodes_copy[id_start];
860 tosock = ntree_shader_node_input_get(tonode, 0);
861 blender::bke::node_add_link(ntree, fromnode, fromsock, tonode, tosock);
862 tonode = nodes_copy[id_start + 1];
863 tosock = ntree_shader_node_input_get(tonode, 0);
864 blender::bke::node_add_link(ntree, fromnode, fromsock, tonode, tosock);
865 break;
866 }
867 default:
868 BLI_assert(0);
869 break;
870 }
871 }
872 }
873 /* Recreate links between copied nodes. */
874 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
875 if (node->runtime->tmp_flag >= 0) {
876 /* Naming can be confusing here. We use original node-link name for from/to prefix.
877 * The final link is in reversed order. */
878 int socket_index;
879 LISTBASE_FOREACH_INDEX (bNodeSocket *, sock, &node->inputs, socket_index) {
880 bNodeSocket *tosock;
881 bNode *tonode;
882
883 switch (node->type) {
888 case SH_NODE_ADD_SHADER: {
889 tonode = nodes_copy[node->runtime->tmp_flag];
890 tosock = ntree_shader_node_output_get(tonode, 0);
891 break;
892 }
893 case SH_NODE_MIX_SHADER: {
894 if (socket_index == 0) {
895 /* Mix Factor. */
896 tonode = nodes_copy[node->runtime->tmp_flag + 2];
897 tosock = ntree_shader_node_input_get(tonode, 1);
898 }
899 else if (socket_index == 1) {
900 /* Shader 1. */
901 tonode = nodes_copy[node->runtime->tmp_flag + 1];
902 tosock = ntree_shader_node_output_get(tonode, 0);
903 }
904 else {
905 /* Shader 2. */
906 tonode = nodes_copy[node->runtime->tmp_flag];
907 tosock = ntree_shader_node_output_get(tonode, 0);
908 }
909 break;
910 }
911 default:
912 BLI_assert(0);
913 break;
914 }
915
916 if (sock->link) {
917 bNodeSocket *fromsock;
918 bNode *fromnode = sock->link->fromnode;
919
920 switch (fromnode->type) {
921 case SH_NODE_ADD_SHADER: {
922 fromnode = nodes_copy[fromnode->runtime->tmp_flag];
923 fromsock = ntree_shader_node_input_get(fromnode, 1);
924 if (fromsock->link) {
925 ntree_weight_tree_merge_weight(ntree, fromnode, fromsock, &tonode, &tosock);
926 }
927 break;
928 }
929 case SH_NODE_MIX_SHADER: {
930 fromnode = nodes_copy[fromnode->runtime->tmp_flag + 3];
931 fromsock = ntree_shader_node_input_get(fromnode, 1);
932 if (fromsock->link) {
933 ntree_weight_tree_merge_weight(ntree, fromnode, fromsock, &tonode, &tosock);
934 }
935 break;
936 }
952 case SH_NODE_EMISSION:
953 case SH_NODE_HOLDOUT:
958 fromsock = ntree_shader_node_find_input(fromnode, "Weight");
959 /* Make "weight" sockets available so that links to it are available as well and are
960 * not ignored in other places. */
961 fromsock->flag &= ~SOCK_UNAVAIL;
962 if (fromsock->link) {
963 ntree_weight_tree_merge_weight(ntree, fromnode, fromsock, &tonode, &tosock);
964 }
965 break;
966 default:
967 fromsock = sock->link->fromsock;
968 break;
969 }
970
971 /* Manually add the link to the socket to avoid calling:
972 * `BKE_ntree_update_main_tree(G.main, oop, nullptr)`. */
973 fromsock->link = blender::bke::node_add_link(ntree, fromnode, fromsock, tonode, tosock);
974 BLI_assert(fromsock->link);
975 }
976 }
977 }
978 }
979 /* Restore displacement & thickness link. */
980 if (displace_link) {
982 ntree, displace_link->fromnode, displace_link->fromsock, output_node, displace_output);
983 }
984 if (thickness_link) {
986 ntree, thickness_link->fromnode, thickness_link->fromsock, output_node, thickness_output);
987 }
988 BKE_ntree_update_main_tree(G.main, ntree, nullptr);
989}
990
991static bool closure_node_filter(const bNode *node)
992{
993 switch (node->type) {
1002 case SH_NODE_BSDF_HAIR:
1006 case SH_NODE_BSDF_TOON:
1009 case SH_NODE_BSDF_SHEEN:
1011 case SH_NODE_EMISSION:
1012 case SH_NODE_HOLDOUT:
1017 return true;
1018 default:
1019 return false;
1020 }
1021}
1022
1023/* Shader to rgba needs their associated closure duplicated and the weight tree generated for. */
1025{
1026 Vector<bNode *> shader_to_rgba_nodes;
1027 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
1028 if (node->type == SH_NODE_SHADERTORGB) {
1029 shader_to_rgba_nodes.append(node);
1030 }
1031 }
1032
1033 for (bNode *shader_to_rgba : shader_to_rgba_nodes) {
1034 bNodeSocket *closure_input = ntree_shader_node_input_get(shader_to_rgba, 0);
1035 if (closure_input->link == nullptr) {
1036 continue;
1037 }
1038 ntree_shader_copy_branch(ntree, shader_to_rgba, closure_node_filter);
1039 BKE_ntree_update_main_tree(G.main, ntree, nullptr);
1040
1041 ntree_shader_weight_tree_invert(ntree, shader_to_rgba);
1042 }
1043}
1044
1046 int16_t &max_depth,
1047 int16_t depth_level = 0)
1048{
1049 if (node->type == SH_NODE_SHADERTORGB) {
1050 depth_level++;
1051 max_depth = std::max(max_depth, depth_level);
1052 }
1053
1054 if (node->runtime->tmp_flag >= depth_level) {
1055 /* We already iterated this branch at this or a greater depth. */
1056 return;
1057 }
1058 node->runtime->tmp_flag = std::max(node->runtime->tmp_flag, depth_level);
1059
1060 LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
1061 bNodeLink *link = sock->link;
1062 if (link == nullptr) {
1063 continue;
1064 }
1065 if ((link->flag & NODE_LINK_VALID) == 0) {
1066 /* Skip links marked as cyclic. */
1067 continue;
1068 }
1069 iter_shader_to_rgba_depth_count(link->fromnode, max_depth, depth_level);
1070 }
1071}
1072
1073static void shader_node_disconnect_input(bNodeTree *ntree, bNode *node, int index)
1074{
1075 bNodeLink *link = ntree_shader_node_input_get(node, index)->link;
1076 if (link) {
1077 blender::bke::node_remove_link(ntree, link);
1078 }
1079}
1080
1082 bNode *node,
1083 int factor_socket_index,
1084 int a_socket_index,
1085 int b_socket_index,
1086 bool clamp_factor)
1087{
1088 bNodeSocket *factor_socket = ntree_shader_node_input_get(node, factor_socket_index);
1089 if (factor_socket->link == nullptr) {
1090 float factor = 0.5;
1091
1092 if (factor_socket->type == SOCK_FLOAT) {
1093 factor = factor_socket->default_value_typed<bNodeSocketValueFloat>()->value;
1094 if (clamp_factor) {
1095 factor = clamp_f(factor, 0.0f, 1.0f);
1096 }
1097 }
1098 else if (factor_socket->type == SOCK_VECTOR) {
1099 const float *vfactor = factor_socket->default_value_typed<bNodeSocketValueVector>()->value;
1100 float vfactor_copy[3];
1101 for (int i = 0; i < 3; i++) {
1102 if (clamp_factor) {
1103 vfactor_copy[i] = clamp_f(vfactor[i], 0.0f, 1.0f);
1104 }
1105 else {
1106 vfactor_copy[i] = vfactor[i];
1107 }
1108 }
1109 if (vfactor_copy[0] == vfactor_copy[1] && vfactor_copy[0] == vfactor_copy[2]) {
1110 factor = vfactor_copy[0];
1111 }
1112 }
1113
1114 if (factor == 1.0f && a_socket_index >= 0) {
1115 shader_node_disconnect_input(ntree, node, a_socket_index);
1116 }
1117 else if (factor == 0.0f && b_socket_index >= 0) {
1118 shader_node_disconnect_input(ntree, node, b_socket_index);
1119 }
1120 }
1121}
1122
1124{
1125 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
1126 if (node->typeinfo->type == SH_NODE_MIX_SHADER) {
1127 shader_node_disconnect_inactive_mix_branch(ntree, node, 0, 1, 2, true);
1128 }
1129 else if (node->typeinfo->type == SH_NODE_MIX) {
1130 const NodeShaderMix *storage = static_cast<NodeShaderMix *>(node->storage);
1131 if (storage->data_type == SOCK_FLOAT) {
1132 shader_node_disconnect_inactive_mix_branch(ntree, node, 0, 2, 3, storage->clamp_factor);
1133 /* Disconnect links from data_type-specific sockets that are not currently in use */
1134 for (int i : {1, 4, 5, 6, 7}) {
1135 shader_node_disconnect_input(ntree, node, i);
1136 }
1137 }
1138 else if (storage->data_type == SOCK_VECTOR) {
1139 int factor_socket = storage->factor_mode == NODE_MIX_MODE_UNIFORM ? 0 : 1;
1141 ntree, node, factor_socket, 4, 5, storage->clamp_factor);
1142 /* Disconnect links from data_type-specific sockets that are not currently in use */
1143 int unused_factor_socket = factor_socket == 0 ? 1 : 0;
1144 for (int i : {unused_factor_socket, 2, 3, 6, 7}) {
1145 shader_node_disconnect_input(ntree, node, i);
1146 }
1147 }
1148 else if (storage->data_type == SOCK_RGBA) {
1149 /* Branch A can't be optimized-out, since its alpha is always used regardless of factor */
1150 shader_node_disconnect_inactive_mix_branch(ntree, node, 0, -1, 7, storage->clamp_factor);
1151 /* Disconnect links from data_type-specific sockets that are not currently in use */
1152 for (int i : {1, 2, 3, 4, 5}) {
1153 shader_node_disconnect_input(ntree, node, i);
1154 }
1155 }
1156 }
1157 }
1158}
1159
1160static bool ntree_branch_node_tag(bNode *fromnode, bNode *tonode, void * /*userdata*/)
1161{
1162 fromnode->runtime->tmp_flag = 1;
1163 tonode->runtime->tmp_flag = 1;
1164 return true;
1165}
1166
1167/* Avoid adding more node execution when multiple outputs are present. */
1168/* NOTE(@fclem): This is also a workaround for the old EEVEE SSS implementation where only the
1169 * first executed SSS node gets a SSS profile. */
1170static void ntree_shader_pruned_unused(bNodeTree *ntree, bNode *output_node)
1171{
1173
1174 bool changed = false;
1175
1176 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
1177 node->runtime->tmp_flag = 0;
1178 }
1179
1180 /* Avoid deleting the output node if it is the only node in the tree. */
1181 if (output_node) {
1182 output_node->runtime->tmp_flag = 1;
1184 ntree, output_node, ntree_branch_node_tag, nullptr, 0);
1185 }
1186
1187 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
1188 if (node->type == SH_NODE_OUTPUT_AOV) {
1189 node->runtime->tmp_flag = 1;
1191 }
1192 }
1193
1194 LISTBASE_FOREACH_MUTABLE (bNode *, node, &ntree->nodes) {
1195 if (node->runtime->tmp_flag == 0) {
1197 changed = true;
1198 }
1199 }
1200
1201 if (changed) {
1202 BKE_ntree_update_main_tree(G.main, ntree, nullptr);
1203 }
1204}
1205
1207{
1209
1212 ntree_shader_groups_flatten(localtree);
1213
1214 bNode *output = ntreeShaderOutputNode(localtree, SHD_OUTPUT_EEVEE);
1215
1216 /* Tree is valid if it contains no undefined implicit socket type cast. */
1217 bool valid_tree = ntree_shader_implicit_closure_cast(localtree);
1218
1219 if (valid_tree) {
1220 ntree_shader_pruned_unused(localtree, output);
1221 if (output != nullptr) {
1223 ntree_shader_weight_tree_invert(localtree, output);
1224 }
1225 }
1226
1227 exec = ntreeShaderBeginExecTree(localtree);
1228 /* Execute nodes ordered by the number of ShaderToRGB nodes found in their path,
1229 * so all closures can be properly evaluated. */
1230 int16_t max_depth = 0;
1231 LISTBASE_FOREACH (bNode *, node, &localtree->nodes) {
1232 node->runtime->tmp_flag = -1;
1233 }
1234 if (output != nullptr) {
1235 iter_shader_to_rgba_depth_count(output, max_depth);
1236 }
1237 LISTBASE_FOREACH (bNode *, node, &localtree->nodes) {
1238 if (node->type == SH_NODE_OUTPUT_AOV) {
1239 iter_shader_to_rgba_depth_count(node, max_depth);
1240 }
1241 }
1242 for (int depth = max_depth; depth >= 0; depth--) {
1243 ntreeExecGPUNodes(exec, mat, output, &depth);
1244 LISTBASE_FOREACH (bNode *, node, &localtree->nodes) {
1245 if (node->type == SH_NODE_OUTPUT_AOV) {
1246 ntreeExecGPUNodes(exec, mat, node, &depth);
1247 }
1248 }
1249 }
1251}
1252
1254 bNodeTree *ntree,
1255 bNodeInstanceKey parent_key)
1256{
1257 /* ensures only a single output node is enabled */
1259
1260 /* common base initialization */
1261 bNodeTreeExec *exec = ntree_exec_begin(context, ntree, parent_key);
1262
1263 /* allocate the thread stack listbase array */
1264 exec->threadstack = static_cast<ListBase *>(
1265 MEM_callocN(BLENDER_MAX_THREADS * sizeof(ListBase), "thread stack array"));
1266
1267 LISTBASE_FOREACH (bNode *, node, &exec->nodetree->nodes) {
1268 node->runtime->need_exec = 1;
1269 }
1270
1271 return exec;
1272}
1273
1275{
1276 bNodeExecContext context;
1278
1279 /* XXX hack: prevent exec data from being generated twice.
1280 * this should be handled by the renderer!
1281 */
1282 if (ntree->runtime->execdata) {
1283 return ntree->runtime->execdata;
1284 }
1285
1286 context.previews = ntree->previews;
1287
1289
1290 /* XXX: this should not be necessary, but is still used for compositor/shader/texture nodes,
1291 * which only store the `ntree` pointer. Should be fixed at some point!
1292 */
1293 ntree->runtime->execdata = exec;
1294
1295 return exec;
1296}
1297
1299{
1300 if (exec->threadstack) {
1301 for (int a = 0; a < BLENDER_MAX_THREADS; a++) {
1302 LISTBASE_FOREACH (bNodeThreadStack *, nts, &exec->threadstack[a]) {
1303 if (nts->stack) {
1304 MEM_freeN(nts->stack);
1305 }
1306 }
1307 BLI_freelistN(&exec->threadstack[a]);
1308 }
1309
1310 MEM_freeN(exec->threadstack);
1311 exec->threadstack = nullptr;
1312 }
1313
1315}
1316
1318{
1319 if (exec) {
1320 /* exec may get freed, so assign ntree */
1321 bNodeTree *ntree = exec->nodetree;
1323
1324 /* XXX: clear node-tree back-pointer to exec data,
1325 * same problem as noted in #ntreeBeginExecTree. */
1326 ntree->runtime->execdata = nullptr;
1327 }
1328}
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:705
General operations, lookup, etc. for materials.
struct Material * BKE_object_material_get(struct Object *ob, short act)
#define SH_NODE_MIX_SHADER
Definition BKE_node.hh:917
#define SH_NODE_BSDF_METALLIC
Definition BKE_node.hh:999
#define SH_NODE_HOLDOUT
Definition BKE_node.hh:942
#define NODE_CLASS_OUTPUT
Definition BKE_node.hh:405
#define NODE_REROUTE
Definition BKE_node.hh:804
#define SH_NODE_OUTPUT_WORLD
Definition BKE_node.hh:914
#define NODE_CLASS_INTERFACE
Definition BKE_node.hh:416
#define NODE_CUSTOM_GROUP
Definition BKE_node.hh:807
#define SH_NODE_BSDF_PRINCIPLED
Definition BKE_node.hh:976
#define SH_NODE_EMISSION
Definition BKE_node.hh:927
#define NODE_CLASS_CONVERTER
Definition BKE_node.hh:410
#define SH_NODE_BSDF_SHEEN
Definition BKE_node.hh:926
#define SH_NODE_ADD_SHADER
Definition BKE_node.hh:939
#define SH_NODE_SUBSURFACE_SCATTERING
Definition BKE_node.hh:960
#define SH_NODE_VOLUME_ABSORPTION
Definition BKE_node.hh:944
#define SH_NODE_VECTOR_MATH
Definition BKE_node.hh:905
#define SH_NODE_VALUE
Definition BKE_node.hh:892
#define SH_NODE_MATH
Definition BKE_node.hh:904
#define SH_NODE_BSDF_TOON
Definition BKE_node.hh:962
#define SH_NODE_BSDF_TRANSPARENT
Definition BKE_node.hh:925
#define SH_NODE_BSDF_DIFFUSE
Definition BKE_node.hh:921
#define NODE_GROUP_OUTPUT
Definition BKE_node.hh:806
#define SH_NODE_SHADERTORGB
Definition BKE_node.hh:896
#define SH_NODE_OUTPUT_MATERIAL
Definition BKE_node.hh:913
#define SH_NODE_BSDF_TRANSLUCENT
Definition BKE_node.hh:924
#define SH_NODE_BSDF_HAIR_PRINCIPLED
Definition BKE_node.hh:984
#define SH_NODE_BSDF_HAIR
Definition BKE_node.hh:968
#define SH_NODE_BACKGROUND
Definition BKE_node.hh:919
#define SH_NODE_BSDF_RAY_PORTAL
Definition BKE_node.hh:997
#define SH_NODE_BSDF_GLOSSY
Definition BKE_node.hh:920
#define NODE_CLASS_OP_VECTOR
Definition BKE_node.hh:407
#define SH_NODE_RGB
Definition BKE_node.hh:891
#define NODE_GROUP
Definition BKE_node.hh:800
#define SH_NODE_EEVEE_SPECULAR
Definition BKE_node.hh:978
#define NODE_CLASS_LAYOUT
Definition BKE_node.hh:420
#define NODE_CLASS_OP_COLOR
Definition BKE_node.hh:406
#define SH_NODE_BSDF_GLASS
Definition BKE_node.hh:923
#define NODE_CLASS_INPUT
Definition BKE_node.hh:404
#define NODE_CLASS_GROUP
Definition BKE_node.hh:409
#define SH_NODE_VOLUME_PRINCIPLED
Definition BKE_node.hh:982
#define NODE_GROUP_INPUT
Definition BKE_node.hh:805
#define NODE_CLASS_TEXTURE
Definition BKE_node.hh:414
#define SH_NODE_BSDF_REFRACTION
Definition BKE_node.hh:956
#define SH_NODE_OUTPUT_LIGHT
Definition BKE_node.hh:915
#define NODE_CLASS_SHADER
Definition BKE_node.hh:417
#define SH_NODE_VOLUME_SCATTER
Definition BKE_node.hh:945
#define SH_NODE_RGBTOBW
Definition BKE_node.hh:895
#define SH_NODE_OUTPUT_AOV
Definition BKE_node.hh:990
#define NODE_CLASS_SCRIPT
Definition BKE_node.hh:415
void BKE_ntree_update_tag_all(bNodeTree *ntree)
void BKE_ntree_update_main_tree(Main *bmain, bNodeTree *ntree, NodeTreeUpdateExtraParams *params)
bool BKE_scene_use_shading_nodes_custom(Scene *scene)
Definition scene.cc:2759
#define BLI_assert(a)
Definition BLI_assert.h:50
#define LISTBASE_FOREACH(type, var, list)
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:496
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:130
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 STRNCPY(dst, src)
Definition BLI_string.h:593
#define BLENDER_MAX_THREADS
Definition BLI_threads.h:20
#define ELEM(...)
#define STREQ(a, b)
@ NTREE_SHADER
@ NODE_VECTOR_MATH_DOT_PRODUCT
@ NODE_DO_OUTPUT
@ NODE_MUTED
@ NODE_MATH_ADD
@ NODE_MATH_MULTIPLY
@ NODE_MATH_SUBTRACT
@ SHD_OUTPUT_ALL
@ SHD_OUTPUT_EEVEE
@ NODE_LINK_MUTED
@ NODE_LINK_VALID
@ SHD_MATH_CLAMP
@ NODE_MIX_MODE_UNIFORM
@ SOCK_HIDE_VALUE
eNodeSocketDatatype
@ SOCK_INT
@ SOCK_VECTOR
@ SOCK_BOOLEAN
@ SOCK_SHADER
@ SOCK_FLOAT
@ SOCK_RGBA
@ OB_LAMP
@ SNODE_SHADER_LINESTYLE
@ SNODE_SHADER_OBJECT
bool contains(const Key &key) const
Definition BLI_set.hh:291
bool add(const Key &key)
Definition BLI_set.hh:248
void append(const T &value)
OperationNode * node
FreestyleLineStyle linestyle
draw_view in_light_buf[] float
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
#define G(x, y, z)
void node_tree_set_output(bNodeTree *ntree)
Definition node.cc:3650
bNode * node_add_static_node(const bContext *C, bNodeTree *ntree, int type)
Definition node.cc:2642
void node_internal_relink(bNodeTree *ntree, bNode *node)
Definition node.cc:3019
bNode * node_copy(bNodeTree *dst_tree, const bNode &src_node, int flag, bool use_unique)
Definition node.cc:2895
bNodeLink * node_add_link(bNodeTree *ntree, bNode *fromnode, bNodeSocket *fromsock, bNode *tonode, bNodeSocket *tosock)
Definition node.cc:2912
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:2561
bool node_is_static_socket_type(const bNodeSocketType *stype)
Definition node.cc:2117
void(*)(void *calldata, int nclass, const char *name) bNodeClassCallback
Definition BKE_node.hh:446
void node_tree_type_add(bNodeTreeType *nt)
Definition node.cc:1633
const bNodeInstanceKey NODE_INSTANCE_KEY_BASE
Definition node.cc:4020
void node_remove_link(bNodeTree *ntree, bNodeLink *link)
Definition node.cc:2958
void node_tree_free_tree(bNodeTree *ntree)
Definition node.cc:3626
void node_tree_free_local_node(bNodeTree *ntree, bNode *node)
Definition node.cc:3531
void node_unique_id(bNodeTree *ntree, bNode *node)
Definition node.cc:2599
void ntree_update_reroute_nodes(bNodeTree *ntree)
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:237
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)
blender::bke::bNodeTreeType * ntreeType_Shader
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, 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:1612
signed short int16_t
Definition stdint.h:76
StructRNA * srna
Definition RNA_types.hh:780
struct bNodeTree * nodetree
Definition DNA_ID.h:413
void * py_instance
Definition DNA_ID.h:482
void * last
void * first
struct bNodeTree * nodetree
struct bNodeLink * link
struct bNodeSocket * next
void * default_value
char identifier[64]
bNodeTreeRuntimeHandle * runtime
NodeInstanceHashHandle * previews
ListBase nodes
ListBase links
int16_t custom1
ListBase inputs
struct ID * id
bNodeRuntimeHandle * runtime
ListBase outputs
int32_t identifier
int16_t type
Defines a socket type.
Definition BKE_node.hh:151
void(* update)(bNodeTree *ntree)
Definition BKE_node.hh:473
void(* foreach_nodeclass)(void *calldata, bNodeClassCallback func)
Definition BKE_node.hh:461
bool(* poll)(const bContext *C, bNodeTreeType *ntreetype)
Definition BKE_node.hh:463
void(* get_from_context)(const bContext *C, bNodeTreeType *ntreetype, bNodeTree **r_ntree, ID **r_id, ID **r_from)
Definition BKE_node.hh:465
void(* localize)(bNodeTree *localtree, bNodeTree *ntree)
Definition BKE_node.hh:469
bool(* validate_link)(eNodeSocketDatatype from, eNodeSocketDatatype to)
Definition BKE_node.hh:475
bool(* valid_socket_type)(bNodeTreeType *ntreetype, bNodeSocketType *socket_type)
Definition BKE_node.hh:480
bool(* node_filter)(const bNode *node)
void * ntreeGPUMaterialNodes
Definition stubs.c:42
#define N_(msgid)