Blender V5.0
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_listbase.h"
11#include "BLI_math_base.hh"
12#include "BLI_set.hh"
13#include "BLI_string_ref.hh"
14
15#include "BKE_compositor.hh"
16#include "BKE_context.hh"
17#include "BKE_cryptomatte.hh"
18#include "BKE_node.hh"
20#include "BKE_node_runtime.hh"
21
22#include "WM_api.hh"
23
24#include "DNA_layer_types.h"
25#include "DNA_node_types.h"
26#include "DNA_object_enums.h"
27#include "DNA_scene_types.h"
28#include "DNA_space_types.h"
29#include "DNA_view3d_types.h"
31
33
34/* Adds the pass names of the passes used by the given Render Layer node to the given used passes.
35 * This essentially adds the pass names of the outputs that are logically linked. */
36static void add_passes_used_by_render_layer_node(const bNode *node, Set<std::string> &used_passes)
37{
38 for (const bNodeSocket *output : node->output_sockets()) {
39 if (output->is_logically_linked()) {
40 used_passes.add(static_cast<NodeImageLayer *>(output->storage)->pass_name);
41 }
42 }
43}
44
45/* Adds the pass names of the passes used by the given Group Input node to the given used passes.
46 * This essentially adds the names of the outputs that are logically linked, since the names of the
47 * outputs represent the pass names. This should only be called on group inputs of root node trees.
48 * Note however that the Image output is actually the Combined pass, but named as Image for
49 * compatibility reasons. */
50static void add_passes_used_by_group_input_node(const bNode *node, Set<std::string> &used_passes)
51{
52 for (const bNodeSocket *output : node->output_sockets()) {
53 if (output->is_logically_linked()) {
54 if (StringRef(output->identifier) == "Image") {
55 used_passes.add(RE_PASSNAME_COMBINED);
56 }
57 else {
58 used_passes.add(output->name);
59 }
60 }
61 }
62}
63
64/* Adds the pass names of all Cryptomatte layers needed by the given node to the given used passes.
65 * Only passes in the given viewer layers are added. */
67 const ViewLayer *view_layer,
68 Set<std::string> &used_passes)
69{
71 return;
72 }
73
74 Scene *scene = reinterpret_cast<Scene *>(node->id);
75 if (!scene) {
76 return;
77 }
78
81
83 if (layer_names.is_empty()) {
84 return;
85 }
86
87 /* If the stored layer name doesn't corresponds to an existing Cryptomatte layer, fall back to
88 * the name of the first layer. */
89 const NodeCryptomatte *data = static_cast<NodeCryptomatte *>(node->storage);
90 const std::string layer_name = layer_names.contains(data->layer_name) ? data->layer_name :
91 layer_names[0];
92
93 /* Does not use passes from the given view layer, so no need to add anything. */
94 if (!StringRef(layer_name).startswith(view_layer->name)) {
95 return;
96 }
97
98 /* Find out which type of Cryptomatte layers the node needs. Also ensure the type is enabled in
99 * the view layer, because the node can use one of the types as a placeholder. */
100 const char *cryptomatte_type_name = nullptr;
101 if (StringRef(layer_name).endswith(RE_PASSNAME_CRYPTOMATTE_OBJECT)) {
103 cryptomatte_type_name = RE_PASSNAME_CRYPTOMATTE_OBJECT;
104 }
105 }
106 else if (StringRef(layer_name).endswith(RE_PASSNAME_CRYPTOMATTE_ASSET)) {
108 cryptomatte_type_name = RE_PASSNAME_CRYPTOMATTE_ASSET;
109 }
110 }
111 else if (StringRef(layer_name).endswith(RE_PASSNAME_CRYPTOMATTE_MATERIAL)) {
113 cryptomatte_type_name = RE_PASSNAME_CRYPTOMATTE_MATERIAL;
114 }
115 }
116
117 if (!cryptomatte_type_name) {
118 return;
119 }
120
121 /* Each layer stores two ranks/levels, so do ceiling division by two. */
122 const int cryptomatte_layers_count = int(math::ceil(view_layer->cryptomatte_levels / 2.0f));
123 for (const int i : IndexRange(cryptomatte_layers_count)) {
124 used_passes.add(fmt::format("{}{:02}", cryptomatte_type_name, i));
125 }
126}
127
128/* Adds the pass names of the passes used by the given compositor node tree to the given used
129 * passes. This is called recursively for node groups. */
130static void add_used_passes_recursive(const bNodeTree *node_tree,
131 const ViewLayer *view_layer,
132 const bool is_root_tree,
133 Set<const bNodeTree *> &node_trees_already_searched,
134 Set<std::string> &used_passes)
135{
136 if (node_tree == nullptr) {
137 return;
138 }
139
140 node_tree->ensure_topology_cache();
141 for (const bNode *node : node_tree->all_nodes()) {
142 if (node->is_muted()) {
143 continue;
144 }
145
146 switch (node->type_legacy) {
147 case NODE_GROUP:
148 case NODE_CUSTOM_GROUP: {
149 const bNodeTree *node_group_tree = reinterpret_cast<const bNodeTree *>(node->id);
150 if (node_trees_already_searched.add(node_group_tree)) {
152 node_group_tree, view_layer, false, node_trees_already_searched, used_passes);
153 }
154 break;
155 }
157 add_passes_used_by_render_layer_node(node, used_passes);
158 break;
159 case NODE_GROUP_INPUT:
160 if (is_root_tree) {
161 add_passes_used_by_group_input_node(node, used_passes);
162 }
163 break;
165 add_passes_used_by_cryptomatte_node(node, view_layer, used_passes);
166 break;
167 default:
168 break;
169 }
170 }
171}
172
173Set<std::string> get_used_passes(const Scene &scene, const ViewLayer *view_layer)
174{
175 Set<std::string> used_passes;
176 Set<const bNodeTree *> node_trees_already_searched;
178 scene.compositing_node_group, view_layer, true, node_trees_already_searched, used_passes);
179 return used_passes;
180}
181
183{
184 const Scene *scene = CTX_data_scene(&context);
185 if (!scene->compositing_node_group) {
186 return false;
187 }
188
189 wmWindowManager *window_manager = CTX_wm_manager(&context);
190 LISTBASE_FOREACH (const wmWindow *, window, &window_manager->windows) {
191 const bScreen *screen = WM_window_get_active_screen(window);
192 LISTBASE_FOREACH (const ScrArea *, area, &screen->areabase) {
193 const SpaceLink &space = *static_cast<const SpaceLink *>(area->spacedata.first);
194 if (space.spacetype == SPACE_VIEW3D) {
195 const View3D &view_3d = reinterpret_cast<const View3D &>(space);
196
198 continue;
199 }
200
201 if (!(view_3d.shading.type >= OB_MATERIAL)) {
202 continue;
203 }
204
205 return true;
206 }
207 }
208 }
209
210 return false;
211}
212
213} // namespace blender::bke::compositor
Scene * CTX_data_scene(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
struct CryptomatteSession * BKE_cryptomatte_init_from_scene(const struct Scene *scene, bool build_meta_data)
#define NODE_CUSTOM_GROUP
Definition BKE_node.hh:816
#define NODE_GROUP
Definition BKE_node.hh:811
#define NODE_GROUP_INPUT
Definition BKE_node.hh:814
#define CMP_NODE_CRYPTOMATTE
#define CMP_NODE_R_LAYERS
#define LISTBASE_FOREACH(type, var, list)
@ VIEW_LAYER_CRYPTOMATTE_MATERIAL
@ VIEW_LAYER_CRYPTOMATTE_ASSET
@ VIEW_LAYER_CRYPTOMATTE_OBJECT
@ CMP_NODE_CRYPTOMATTE_SOURCE_RENDER
@ OB_MATERIAL
#define RE_PASSNAME_COMBINED
#define RE_PASSNAME_CRYPTOMATTE_MATERIAL
#define RE_PASSNAME_CRYPTOMATTE_ASSET
#define RE_PASSNAME_CRYPTOMATTE_OBJECT
@ SPACE_VIEW3D
@ V3D_SHADING_USE_COMPOSITOR_DISABLED
BMesh const char void * data
bool add(const Key &key)
Definition BLI_set.hh:248
bool contains(const T &value) const
bool is_empty() const
#define output
static void add_passes_used_by_group_input_node(const bNode *node, Set< std::string > &used_passes)
static void add_passes_used_by_cryptomatte_node(const bNode *node, const ViewLayer *view_layer, Set< std::string > &used_passes)
bool is_viewport_compositor_used(const bContext &context)
static void add_used_passes_recursive(const bNodeTree *node_tree, const ViewLayer *view_layer, const bool is_root_tree, 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)
struct bNodeTree * compositing_node_group
View3DShading shading
short cryptomatte_flag
short cryptomatte_levels
char name[64]
int16_t custom1
struct ID * id
void * storage
ListBase areabase
i
Definition text_draw.cc:230
bScreen * WM_window_get_active_screen(const wmWindow *win)