Blender V4.3
COM_CryptomatteNode.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2018 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BLI_string.h"
6
7#include "BKE_node.hh"
8
9#include "NOD_composite.hh"
10
12#include "COM_CryptomatteNode.h"
17
18namespace blender::compositor {
19
20/* -------------------------------------------------------------------- */
25 const CompositorContext &context) const
26{
27 NodeOutput *output_image_socket = this->get_output_socket(0);
28
29 const bNode *node = this->get_bnode();
30 const NodeCryptomatte *cryptomatte_settings = static_cast<const NodeCryptomatte *>(
31 node->storage);
32
34 converter, context, *node, cryptomatte_settings);
35 converter.add_operation(cryptomatte_operation);
36
37 NodeOutput *output_matte_socket = this->get_output_socket(1);
38 SeparateChannelOperation *extract_mask_operation = new SeparateChannelOperation;
39 extract_mask_operation->set_channel(3);
40 converter.add_operation(extract_mask_operation);
41 converter.add_link(cryptomatte_operation->get_output_socket(0),
42 extract_mask_operation->get_input_socket(0));
43 converter.map_output_socket(output_matte_socket, extract_mask_operation->get_output_socket(0));
44
45 NodeInput *input_image_socket = this->get_input_socket(0);
46 SetAlphaMultiplyOperation *apply_mask_operation = new SetAlphaMultiplyOperation();
47 converter.map_input_socket(input_image_socket, apply_mask_operation->get_input_socket(0));
48 converter.add_operation(apply_mask_operation);
49 converter.add_link(extract_mask_operation->get_output_socket(0),
50 apply_mask_operation->get_input_socket(1));
51 converter.map_output_socket(output_image_socket, apply_mask_operation->get_output_socket(0));
52
53 NodeOutput *output_pick_socket = this->get_output_socket(2);
54 CryptomattePickOperation *extract_pick_operation = new CryptomattePickOperation();
55 converter.add_operation(extract_pick_operation);
56 converter.add_input_value(extract_pick_operation->get_input_socket(1), 1.0f);
57 converter.add_link(cryptomatte_operation->get_output_socket(0),
58 extract_pick_operation->get_input_socket(0));
59 converter.map_output_socket(output_pick_socket, extract_pick_operation->get_output_socket(0));
60}
61
64/* -------------------------------------------------------------------- */
68static std::string prefix_from_node(const bNode &node)
69{
70 char prefix[MAX_NAME];
71 ntreeCompositCryptomatteLayerPrefix(&node, prefix, sizeof(prefix));
72 return std::string(prefix, BLI_strnlen(prefix, sizeof(prefix)));
73}
74
75static std::string combined_layer_pass_name(RenderLayer *render_layer, RenderPass *render_pass)
76{
77 if (render_layer->name[0] == '\0') {
78 return std::string(render_pass->name,
79 BLI_strnlen(render_pass->name, sizeof(render_pass->name)));
80 }
81
82 std::string combined_name =
83 blender::StringRef(render_layer->name,
84 BLI_strnlen(render_layer->name, sizeof(render_layer->name))) +
85 "." +
86 blender::StringRef(render_pass->name,
87 BLI_strnlen(render_pass->name, sizeof(render_pass->name)));
88 return combined_name;
89}
90
91void CryptomatteNode::input_operations_from_render_source(
92 const CompositorContext &context,
93 const bNode &node,
94 Vector<NodeOperation *> &r_input_operations)
95{
96 Scene *scene = (Scene *)node.id;
97 if (!scene) {
98 return;
99 }
100
101 BLI_assert(GS(scene->id.name) == ID_SCE);
102 Render *render = RE_GetSceneRender(scene);
103 RenderResult *render_result = render ? RE_AcquireResultRead(render) : nullptr;
104
105 if (!render_result) {
106 if (render) {
107 RE_ReleaseResult(render);
108 }
109 return;
110 }
111
112 short view_layer_id = 0;
113 const std::string prefix = prefix_from_node(node);
114 LISTBASE_FOREACH_INDEX (ViewLayer *, view_layer, &scene->view_layers, view_layer_id) {
115 RenderLayer *render_layer = RE_GetRenderLayer(render_result, view_layer->name);
116 if (render_layer) {
117 LISTBASE_FOREACH (RenderPass *, render_pass, &render_layer->passes) {
118 if (context.has_explicit_view() && !STREQ(render_pass->view, context.get_view_name())) {
119 continue;
120 }
121
122 const std::string combined_name = combined_layer_pass_name(render_layer, render_pass);
123 if (combined_name != prefix && blender::StringRef(combined_name).startswith(prefix)) {
124 RenderLayersProg *op = new RenderLayersProg(
125 render_pass->name, DataType::Color, render_pass->channels);
126 op->set_scene(scene);
127 op->set_layer_id(view_layer_id);
128 op->set_render_data(context.get_render_data());
129 op->set_view_name(context.get_view_name());
130 r_input_operations.append(op);
131 }
132 }
133 }
134 }
135 RE_ReleaseResult(render);
136}
137
138void CryptomatteNode::input_operations_from_image_source(
139 const CompositorContext &context,
140 const bNode &node,
141 Vector<NodeOperation *> &r_input_operations)
142{
143 NodeCryptomatte *cryptomatte_settings = (NodeCryptomatte *)node.storage;
144 Image *image = (Image *)node.id;
145 if (!image) {
146 return;
147 }
148
149 BLI_assert(GS(image->id.name) == ID_IM);
150 if (image->type != IMA_TYPE_MULTILAYER) {
151 return;
152 }
153
154 ImageUser *iuser = &cryptomatte_settings->iuser;
155 BKE_image_user_frame_calc(image, iuser, context.get_framenumber());
156 ImBuf *ibuf = BKE_image_acquire_ibuf(image, iuser, nullptr);
157
158 if (image->rr) {
159 const std::string prefix = prefix_from_node(node);
160 int layer_index;
161 LISTBASE_FOREACH_INDEX (RenderLayer *, render_layer, &image->rr->layers, layer_index) {
162 if (!blender::StringRef(prefix).startswith(blender::StringRef(
163 render_layer->name, BLI_strnlen(render_layer->name, sizeof(render_layer->name)))))
164 {
165 continue;
166 }
167 LISTBASE_FOREACH (RenderPass *, render_pass, &render_layer->passes) {
168 const std::string combined_name = combined_layer_pass_name(render_layer, render_pass);
169 if (combined_name != prefix && blender::StringRef(combined_name).startswith(prefix)) {
170 MultilayerColorOperation *op = new MultilayerColorOperation();
171 iuser->layer = layer_index;
172 op->set_image(image);
173 op->set_image_user(*iuser);
174 op->set_framenumber(context.get_framenumber());
175 op->set_render_data(context.get_render_data());
176 op->set_view_name(context.get_view_name());
177 op->set_layer_name(render_layer->name);
178 op->set_pass_name(render_pass->name);
179 r_input_operations.append(op);
180 }
181 }
182 break;
183 }
184 }
185 BKE_image_release_ibuf(image, ibuf, nullptr);
186}
187
188Vector<NodeOperation *> CryptomatteNode::create_input_operations(const CompositorContext &context,
189 const bNode &node)
190{
191 Vector<NodeOperation *> input_operations;
192 switch (node.custom1) {
194 input_operations_from_render_source(context, node, input_operations);
195 break;
197 input_operations_from_image_source(context, node, input_operations);
198 break;
199 }
200
201 if (input_operations.is_empty()) {
202 SetColorOperation *op = new SetColorOperation();
203 op->set_channel1(0.0f);
204 op->set_channel2(1.0f);
205 op->set_channel3(0.0f);
206 op->set_channel4(0.0f);
207 input_operations.append(op);
208 }
209 return input_operations;
210}
212 NodeConverter &converter,
213 const CompositorContext &context,
214 const bNode &node,
215 const NodeCryptomatte *cryptomatte_settings) const
216{
217 Vector<NodeOperation *> input_operations = create_input_operations(context, node);
218 CryptomatteOperation *operation = new CryptomatteOperation(input_operations.size());
219 LISTBASE_FOREACH (CryptomatteEntry *, cryptomatte_entry, &cryptomatte_settings->entries) {
220 operation->add_object_index(cryptomatte_entry->encoded_hash);
221 }
222 for (int i = 0; i < input_operations.size(); ++i) {
223 converter.add_operation(input_operations[i]);
224 converter.add_link(input_operations[i]->get_output_socket(), operation->get_input_socket(i));
225 }
226 return operation;
227}
228
231/* -------------------------------------------------------------------- */
236 NodeConverter &converter,
237 const CompositorContext & /*context*/,
238 const bNode & /*node*/,
239 const NodeCryptomatte *cryptomatte_settings) const
240{
241 const int num_inputs = inputs_.size() - 1;
242 CryptomatteOperation *operation = new CryptomatteOperation(num_inputs);
243 if (cryptomatte_settings) {
244 LISTBASE_FOREACH (CryptomatteEntry *, cryptomatte_entry, &cryptomatte_settings->entries) {
245 operation->add_object_index(cryptomatte_entry->encoded_hash);
246 }
247 }
248
249 for (int i = 0; i < num_inputs; i++) {
250 converter.map_input_socket(this->get_input_socket(i + 1), operation->get_input_socket(i));
251 }
252
253 return operation;
254}
255
258} // namespace blender::compositor
ImBuf * BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
void BKE_image_user_frame_calc(Image *ima, ImageUser *iuser, int cfra)
void BKE_image_release_ibuf(Image *ima, ImBuf *ibuf, void *lock)
#define BLI_assert(a)
Definition BLI_assert.h:50
#define LISTBASE_FOREACH(type, var, list)
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
int char char int int int int size_t BLI_strnlen(const char *str, size_t maxlen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition string.c:909
#define STREQ(a, b)
@ ID_IM
@ ID_SCE
#define MAX_NAME
Definition DNA_defs.h:50
@ IMA_TYPE_MULTILAYER
@ CMP_NODE_CRYPTOMATTE_SOURCE_IMAGE
@ CMP_NODE_CRYPTOMATTE_SOURCE_RENDER
int64_t size() const
Overall context of the compositor.
virtual CryptomatteOperation * create_cryptomatte_operation(NodeConverter &converter, const CompositorContext &context, const bNode &node, const NodeCryptomatte *cryptomatte_settings) const =0
void convert_to_operations(NodeConverter &converter, const CompositorContext &context) const override
convert node to operation
CryptomatteOperation * create_cryptomatte_operation(NodeConverter &converter, const CompositorContext &context, const bNode &node, const NodeCryptomatte *cryptomatte_settings) const override
CryptomatteOperation * create_cryptomatte_operation(NodeConverter &converter, const CompositorContext &context, const bNode &node, const NodeCryptomatte *cryptomatte_settings) const override
void add_link(NodeOperationOutput *from, NodeOperationInput *to)
void map_output_socket(NodeOutput *node_socket, NodeOperationOutput *operation_socket)
void add_input_value(NodeOperationInput *input, float value)
void add_operation(NodeOperation *operation)
void map_input_socket(NodeInput *node_socket, NodeOperationInput *operation_socket)
NodeInput are sockets that can receive data/input.
Definition COM_Node.h:191
NodeOperationOutput * get_output_socket(unsigned int index=0)
NodeOperationInput * get_input_socket(unsigned int index)
NodeOutput are sockets that can send data/input.
Definition COM_Node.h:239
NodeOutput * get_output_socket(unsigned int index=0) const
Definition COM_Node.cc:85
NodeInput * get_input_socket(unsigned int index) const
Definition COM_Node.cc:90
Vector< NodeInput * > inputs_
the list of actual input-sockets
Definition COM_Node.h:51
const bNode * get_bnode() const
get the reference to the SDNA bNode struct
Definition COM_Node.h:65
#define GS(x)
Definition iris.cc:202
static std::string prefix_from_node(const bNode &node)
static std::string combined_layer_pass_name(RenderLayer *render_layer, RenderPass *render_pass)
void ntreeCompositCryptomatteLayerPrefix(const bNode *node, char *r_prefix, size_t prefix_maxncpy)
RenderResult * RE_AcquireResultRead(Render *re)
RenderLayer * RE_GetRenderLayer(RenderResult *rr, const char *name)
void RE_ReleaseResult(Render *re)
Render * RE_GetSceneRender(const Scene *scene)
ListBase passes
Definition RE_pipeline.h:97
char name[RE_MAXNAME]
Definition RE_pipeline.h:89
char name[64]
Definition RE_pipeline.h:58