Blender V4.3
blenkernel/intern/compositor.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include <string>
6
7#include <fmt/format.h>
8
9#include "BLI_index_range.hh"
10#include "BLI_math_base.hh"
11#include "BLI_set.hh"
12#include "BLI_string_ref.hh"
13
14#include "BKE_compositor.hh"
15#include "BKE_cryptomatte.hh"
16#include "BKE_node.hh"
17#include "BKE_node_runtime.hh"
18
19#include "DNA_layer_types.h"
20#include "DNA_node_types.h"
21#include "DNA_scene_types.h"
22
24
25/* Adds the pass names of the passes used by the given Render Layer node to the given used passes.
26 * This essentially adds the identifiers of the outputs that are logically linked, their the
27 * identifiers are the names of the passes. Note however that the Image output is actually the
28 * Combined pass, but named as Image for compatibility reasons. */
29static void add_passes_used_by_render_layer_node(const bNode *node, Set<std::string> &used_passes)
30{
31 for (const bNodeSocket *output : node->output_sockets()) {
32 if (output->is_logically_linked()) {
33 if (StringRef(output->identifier) == "Image") {
34 used_passes.add(RE_PASSNAME_COMBINED);
35 }
36 else {
37 used_passes.add(output->identifier);
38 }
39 }
40 }
41}
42
43/* Adds the pass names of all Cryptomatte layers needed by the given node to the given used passes.
44 * Only passes in the given viewer layers are added. */
46 const ViewLayer *view_layer,
47 Set<std::string> &used_passes)
48{
49 if (node->custom1 != CMP_NODE_CRYPTOMATTE_SOURCE_RENDER) {
50 return;
51 }
52
53 Scene *scene = reinterpret_cast<Scene *>(node->id);
54 if (!scene) {
55 return;
56 }
57
60
62 if (layer_names.is_empty()) {
63 return;
64 }
65
66 /* If the stored layer name doesn't corresponds to an existing Cryptomatte layer, fallback to the
67 * name of the first layer. */
68 const NodeCryptomatte *data = static_cast<NodeCryptomatte *>(node->storage);
69 const std::string layer_name = layer_names.contains(data->layer_name) ? data->layer_name :
70 layer_names[0];
71
72 /* Does not use passes from the given view layer, so no need to add anything. */
73 if (!StringRef(layer_name).startswith(view_layer->name)) {
74 return;
75 }
76
77 /* Find out which type of Cryptomatte layers the node needs. Also ensure the type is enabled in
78 * the view layer, because the node can use one of the types as a placeholder. */
79 const char *cryptomatte_type_name = nullptr;
82 cryptomatte_type_name = RE_PASSNAME_CRYPTOMATTE_OBJECT;
83 }
84 }
85 else if (StringRef(layer_name).endswith(RE_PASSNAME_CRYPTOMATTE_ASSET)) {
87 cryptomatte_type_name = RE_PASSNAME_CRYPTOMATTE_ASSET;
88 }
89 }
92 cryptomatte_type_name = RE_PASSNAME_CRYPTOMATTE_MATERIAL;
93 }
94 }
95
96 if (!cryptomatte_type_name) {
97 return;
98 }
99
100 /* Each layer stores two ranks/levels, so do ceiling division by two. */
101 const int cryptomatte_layers_count = int(math::ceil(view_layer->cryptomatte_levels / 2.0f));
102 for (const int i : IndexRange(cryptomatte_layers_count)) {
103 used_passes.add(fmt::format("{}{:02}", cryptomatte_type_name, i));
104 }
105}
106
107/* Adds the pass names of the passes used by the given compositor node tree to the given used
108 * passes. This is called recursively for node groups. */
110 const ViewLayer *view_layer,
111 Set<const bNodeTree *> &node_trees_already_searched,
112 Set<std::string> &used_passes)
113{
114 if (node_tree == nullptr) {
115 return;
116 }
117
118 node_tree->ensure_topology_cache();
119 for (const bNode *node : node_tree->all_nodes()) {
120 if (node->is_muted()) {
121 continue;
122 }
123
124 switch (node->type) {
125 case NODE_GROUP:
126 case NODE_CUSTOM_GROUP: {
127 const bNodeTree *node_group_tree = reinterpret_cast<const bNodeTree *>(node->id);
128 if (node_trees_already_searched.add(node_group_tree)) {
130 node_group_tree, view_layer, node_trees_already_searched, used_passes);
131 }
132 break;
133 }
135 add_passes_used_by_render_layer_node(node, used_passes);
136 break;
138 add_passes_used_by_cryptomatte_node(node, view_layer, used_passes);
139 break;
140 default:
141 break;
142 }
143 }
144}
145
146Set<std::string> get_used_passes(const Scene &scene, const ViewLayer *view_layer)
147{
148 Set<std::string> used_passes;
149 Set<const bNodeTree *> node_trees_already_searched;
150 add_used_passes_recursive(scene.nodetree, view_layer, node_trees_already_searched, used_passes);
151 return used_passes;
152}
153
154} // namespace blender::bke::compositor
struct CryptomatteSession * BKE_cryptomatte_init_from_scene(const struct Scene *scene, bool build_meta_data)
#define NODE_CUSTOM_GROUP
Definition BKE_node.hh:807
#define CMP_NODE_CRYPTOMATTE
Definition BKE_node.hh:1111
#define NODE_GROUP
Definition BKE_node.hh:800
#define CMP_NODE_R_LAYERS
Definition BKE_node.hh:1032
@ VIEW_LAYER_CRYPTOMATTE_MATERIAL
@ VIEW_LAYER_CRYPTOMATTE_ASSET
@ VIEW_LAYER_CRYPTOMATTE_OBJECT
@ CMP_NODE_CRYPTOMATTE_SOURCE_RENDER
#define RE_PASSNAME_COMBINED
#define RE_PASSNAME_CRYPTOMATTE_MATERIAL
#define RE_PASSNAME_CRYPTOMATTE_ASSET
#define RE_PASSNAME_CRYPTOMATTE_OBJECT
bool add(const Key &key)
Definition BLI_set.hh:248
constexpr bool startswith(StringRef prefix) const
constexpr bool endswith(StringRef suffix) const
bool contains(const T &value) const
bool is_empty() const
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
static void add_passes_used_by_cryptomatte_node(const bNode *node, const ViewLayer *view_layer, Set< std::string > &used_passes)
static void add_used_passes_recursive(const bNodeTree *node_tree, const ViewLayer *view_layer, Set< const bNodeTree * > &node_trees_already_searched, Set< std::string > &used_passes)
Set< std::string > get_used_passes(const Scene &scene, const ViewLayer *view_layer)
static void add_passes_used_by_render_layer_node(const bNode *node, Set< std::string > &used_passes)
std::unique_ptr< CryptomatteSession, CryptomatteSessionDeleter > CryptomatteSessionPtr
const blender::Vector< std::string > & BKE_cryptomatte_layer_names_get(const CryptomatteSession &session)
T ceil(const T &a)
short cryptomatte_flag
short cryptomatte_levels
char name[64]