Blender  V3.3
COM_CryptomatteNode.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2018 Blender Foundation. */
3 
4 #include "BKE_node.h"
5 
6 #include "NOD_composite.h"
7 
8 #include "COM_ConvertOperation.h"
9 #include "COM_CryptomatteNode.h"
11 #include "COM_RenderLayersProg.h"
13 #include "COM_SetColorOperation.h"
14 
15 namespace blender::compositor {
16 
17 /* -------------------------------------------------------------------- */
22  const CompositorContext &context) const
23 {
24  NodeOutput *output_image_socket = this->get_output_socket(0);
25 
26  bNode *node = this->get_bnode();
27  NodeCryptomatte *cryptomatte_settings = static_cast<NodeCryptomatte *>(node->storage);
28 
29  CryptomatteOperation *cryptomatte_operation = create_cryptomatte_operation(
30  converter, context, *node, cryptomatte_settings);
31  converter.add_operation(cryptomatte_operation);
32 
33  NodeOutput *output_matte_socket = this->get_output_socket(1);
34  SeparateChannelOperation *extract_mask_operation = new SeparateChannelOperation;
35  extract_mask_operation->set_channel(3);
36  converter.add_operation(extract_mask_operation);
37  converter.add_link(cryptomatte_operation->get_output_socket(0),
38  extract_mask_operation->get_input_socket(0));
39  converter.map_output_socket(output_matte_socket, extract_mask_operation->get_output_socket(0));
40 
41  NodeInput *input_image_socket = this->get_input_socket(0);
42  SetAlphaMultiplyOperation *apply_mask_operation = new SetAlphaMultiplyOperation();
43  converter.map_input_socket(input_image_socket, apply_mask_operation->get_input_socket(0));
44  converter.add_operation(apply_mask_operation);
45  converter.add_link(extract_mask_operation->get_output_socket(0),
46  apply_mask_operation->get_input_socket(1));
47  converter.map_output_socket(output_image_socket, apply_mask_operation->get_output_socket(0));
48 
49  NodeOutput *output_pick_socket = this->get_output_socket(2);
50  SetAlphaMultiplyOperation *extract_pick_operation = new SetAlphaMultiplyOperation();
51  converter.add_operation(extract_pick_operation);
52  converter.add_input_value(extract_pick_operation->get_input_socket(1), 1.0f);
53  converter.add_link(cryptomatte_operation->get_output_socket(0),
54  extract_pick_operation->get_input_socket(0));
55  converter.map_output_socket(output_pick_socket, extract_pick_operation->get_output_socket(0));
56 }
57 
60 /* -------------------------------------------------------------------- */
64 static std::string prefix_from_node(const CompositorContext &context, const bNode &node)
65 {
66  char prefix[MAX_NAME];
67  ntreeCompositCryptomatteLayerPrefix(context.get_scene(), &node, prefix, sizeof(prefix));
68  return std::string(prefix, BLI_strnlen(prefix, sizeof(prefix)));
69 }
70 
71 static std::string combined_layer_pass_name(RenderLayer *render_layer, RenderPass *render_pass)
72 {
73  if (render_layer->name[0] == '\0') {
74  return std::string(render_pass->name,
75  BLI_strnlen(render_pass->name, sizeof(render_pass->name)));
76  }
77 
78  std::string combined_name =
79  blender::StringRef(render_layer->name,
80  BLI_strnlen(render_layer->name, sizeof(render_layer->name))) +
81  "." +
82  blender::StringRef(render_pass->name,
83  BLI_strnlen(render_pass->name, sizeof(render_pass->name)));
84  return combined_name;
85 }
86 
87 void CryptomatteNode::input_operations_from_render_source(
88  const CompositorContext &context,
89  const bNode &node,
90  Vector<NodeOperation *> &r_input_operations)
91 {
92  Scene *scene = (Scene *)node.id;
93  if (!scene) {
94  return;
95  }
96 
98  Render *render = RE_GetSceneRender(scene);
99  RenderResult *render_result = render ? RE_AcquireResultRead(render) : nullptr;
100 
101  if (!render_result) {
102  return;
103  }
104 
105  short view_layer_id = 0;
106  const std::string prefix = prefix_from_node(context, node);
107  LISTBASE_FOREACH_INDEX (ViewLayer *, view_layer, &scene->view_layers, view_layer_id) {
108  RenderLayer *render_layer = RE_GetRenderLayer(render_result, view_layer->name);
109  if (render_layer) {
110  LISTBASE_FOREACH (RenderPass *, render_pass, &render_layer->passes) {
111  if (context.has_explicit_view() && !STREQ(render_pass->view, context.get_view_name())) {
112  continue;
113  }
114 
115  const std::string combined_name = combined_layer_pass_name(render_layer, render_pass);
116  if (blender::StringRef(combined_name).startswith(prefix)) {
117  RenderLayersProg *op = new RenderLayersProg(
118  render_pass->name, DataType::Color, render_pass->channels);
119  op->set_scene(scene);
120  op->set_layer_id(view_layer_id);
121  op->set_render_data(context.get_render_data());
122  op->set_view_name(context.get_view_name());
123  r_input_operations.append(op);
124  }
125  }
126  }
127  }
128  RE_ReleaseResult(render);
129 }
130 
131 void CryptomatteNode::input_operations_from_image_source(
132  const CompositorContext &context,
133  const bNode &node,
134  Vector<NodeOperation *> &r_input_operations)
135 {
136  NodeCryptomatte *cryptomatte_settings = (NodeCryptomatte *)node.storage;
137  Image *image = (Image *)node.id;
138  if (!image) {
139  return;
140  }
141 
142  BLI_assert(GS(image->id.name) == ID_IM);
143  if (image->type != IMA_TYPE_MULTILAYER) {
144  return;
145  }
146 
147  ImageUser *iuser = &cryptomatte_settings->iuser;
148  BKE_image_user_frame_calc(image, iuser, context.get_framenumber());
149  ImBuf *ibuf = BKE_image_acquire_ibuf(image, iuser, nullptr);
150 
151  if (image->rr) {
152  int view = 0;
153  if (BLI_listbase_count_at_most(&image->rr->views, 2) > 1) {
154  if (iuser->view == 0) {
155  /* Heuristic to match image name with scene names, check if the view name exists in the
156  * image. */
158  &image->rr->views, context.get_view_name(), offsetof(RenderView, name));
159  if (view == -1) {
160  view = 0;
161  }
162  }
163  else {
164  view = iuser->view - 1;
165  }
166  }
167 
168  const std::string prefix = prefix_from_node(context, node);
169  int layer_index;
170  LISTBASE_FOREACH_INDEX (RenderLayer *, render_layer, &image->rr->layers, layer_index) {
171  if (!blender::StringRef(prefix).startswith(blender::StringRef(
172  render_layer->name, BLI_strnlen(render_layer->name, sizeof(render_layer->name))))) {
173  continue;
174  }
175  LISTBASE_FOREACH (RenderPass *, render_pass, &render_layer->passes) {
176  const std::string combined_name = combined_layer_pass_name(render_layer, render_pass);
177  if (blender::StringRef(combined_name).startswith(prefix)) {
178  MultilayerColorOperation *op = new MultilayerColorOperation(
179  render_layer, render_pass, view);
180  op->set_image(image);
181  op->set_image_user(iuser);
182  iuser->layer = layer_index;
183  op->set_framenumber(context.get_framenumber());
184  r_input_operations.append(op);
185  }
186  }
187  break;
188  }
189  }
190  BKE_image_release_ibuf(image, ibuf, nullptr);
191 }
192 
193 Vector<NodeOperation *> CryptomatteNode::create_input_operations(const CompositorContext &context,
194  const bNode &node)
195 {
196  Vector<NodeOperation *> input_operations;
197  switch (node.custom1) {
199  input_operations_from_render_source(context, node, input_operations);
200  break;
202  input_operations_from_image_source(context, node, input_operations);
203  break;
204  }
205 
206  if (input_operations.is_empty()) {
207  SetColorOperation *op = new SetColorOperation();
208  op->set_channel1(0.0f);
209  op->set_channel2(1.0f);
210  op->set_channel3(0.0f);
211  op->set_channel4(0.0f);
212  input_operations.append(op);
213  }
214  return input_operations;
215 }
217  NodeConverter &converter,
218  const CompositorContext &context,
219  const bNode &node,
220  const NodeCryptomatte *cryptomatte_settings) const
221 {
222  Vector<NodeOperation *> input_operations = create_input_operations(context, node);
223  CryptomatteOperation *operation = new CryptomatteOperation(input_operations.size());
224  LISTBASE_FOREACH (CryptomatteEntry *, cryptomatte_entry, &cryptomatte_settings->entries) {
225  operation->add_object_index(cryptomatte_entry->encoded_hash);
226  }
227  for (int i = 0; i < input_operations.size(); ++i) {
228  converter.add_operation(input_operations[i]);
229  converter.add_link(input_operations[i]->get_output_socket(), operation->get_input_socket(i));
230  }
231  return operation;
232 }
233 
236 /* -------------------------------------------------------------------- */
241  NodeConverter &converter,
243  const bNode &UNUSED(node),
244  const NodeCryptomatte *cryptomatte_settings) const
245 {
246  const int num_inputs = inputs_.size() - 1;
247  CryptomatteOperation *operation = new CryptomatteOperation(num_inputs);
248  if (cryptomatte_settings) {
249  LISTBASE_FOREACH (CryptomatteEntry *, cryptomatte_entry, &cryptomatte_settings->entries) {
250  operation->add_object_index(cryptomatte_entry->encoded_hash);
251  }
252  }
253 
254  for (int i = 0; i < num_inputs; i++) {
255  converter.map_input_socket(this->get_input_socket(i + 1), operation->get_input_socket(i));
256  }
257 
258  return operation;
259 }
260 
263 } // namespace blender::compositor
void BKE_image_release_ibuf(struct Image *ima, struct ImBuf *ibuf, void *lock)
struct ImBuf * BKE_image_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, void **r_lock)
void BKE_image_user_frame_calc(struct Image *ima, struct ImageUser *iuser, int cfra)
#define CMP_CRYPTOMATTE_SRC_RENDER
Definition: BKE_node.h:1331
#define CMP_CRYPTOMATTE_SRC_IMAGE
Definition: BKE_node.h:1332
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
Definition: BLI_listbase.h:344
int BLI_listbase_count_at_most(const struct ListBase *listbase, int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_findstringindex(const struct ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
size_t BLI_strnlen(const char *str, size_t maxlen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: string.c:899
#define UNUSED(x)
#define STREQ(a, b)
@ ID_IM
Definition: DNA_ID_enums.h:53
@ ID_SCE
Definition: DNA_ID_enums.h:45
#define MAX_NAME
Definition: DNA_defs.h:48
@ IMA_TYPE_MULTILAYER
static AppView * view
int64_t size() const
Definition: BLI_vector.hh:694
void append(const T &value)
Definition: BLI_vector.hh:433
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:190
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:238
NodeOutput * get_output_socket(unsigned int index=0) const
Definition: COM_Node.cc:84
bNode * get_bnode() const
get the reference to the SDNA bNode struct
Definition: COM_Node.h:64
NodeInput * get_input_socket(unsigned int index) const
Definition: COM_Node.cc:89
Vector< NodeInput * > inputs_
the list of actual input-sockets
Definition: COM_Node.h:50
OperationNode * node
Scene scene
depth_tx normal_tx diffuse_light_tx specular_light_tx volume_light_tx environment_tx ambient_occlusion_tx aov_value_tx in_weight_img image(1, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D_ARRAY, "out_weight_img") .image(3
#define GS(x)
Definition: iris.c:225
static std::string combined_layer_pass_name(RenderLayer *render_layer, RenderPass *render_pass)
static std::string prefix_from_node(const CompositorContext &context, const bNode &node)
void ntreeCompositCryptomatteLayerPrefix(const Scene *scene, const bNode *node, char *r_prefix, size_t prefix_len)
RenderResult * RE_AcquireResultRead(Render *re)
Definition: pipeline.c:314
Render * RE_GetSceneRender(const Scene *scene)
Definition: pipeline.c:551
RenderLayer * RE_GetRenderLayer(RenderResult *rr, const char *name)
Definition: pipeline.c:244
void RE_ReleaseResult(Render *re)
Definition: pipeline.c:351
char name[66]
Definition: DNA_ID.h:378
ListBase passes
Definition: RE_pipeline.h:95
char name[RE_MAXNAME]
Definition: RE_pipeline.h:87
char name[64]
Definition: RE_pipeline.h:65
ListBase view_layers