Blender  V2.93
COM_CryptomatteNode.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * Copyright 2018, Blender Foundation.
17  */
18 
19 #include "COM_CryptomatteNode.h"
20 #include "BKE_node.h"
21 #include "BLI_assert.h"
22 #include "BLI_hash_mm3.h"
23 #include "BLI_listbase.h"
24 #include "BLI_string.h"
25 #include "COM_ConvertOperation.h"
28 #include "COM_RenderLayersProg.h"
30 #include "COM_SetColorOperation.h"
31 #include <iterator>
32 #include <string>
33 
34 namespace blender::compositor {
35 
40  const CompositorContext &context) const
41 {
42  NodeOutput *output_image_socket = this->getOutputSocket(0);
43 
44  bNode *node = this->getbNode();
45  NodeCryptomatte *cryptomatte_settings = static_cast<NodeCryptomatte *>(node->storage);
46 
47  CryptomatteOperation *cryptomatte_operation = create_cryptomatte_operation(
48  converter, context, *node, cryptomatte_settings);
49  converter.addOperation(cryptomatte_operation);
50 
51  NodeOutput *output_matte_socket = this->getOutputSocket(1);
52  SeparateChannelOperation *extract_mask_operation = new SeparateChannelOperation;
53  extract_mask_operation->setChannel(3);
54  converter.addOperation(extract_mask_operation);
55  converter.addLink(cryptomatte_operation->getOutputSocket(0),
56  extract_mask_operation->getInputSocket(0));
57  converter.mapOutputSocket(output_matte_socket, extract_mask_operation->getOutputSocket(0));
58 
59  NodeInput *input_image_socket = this->getInputSocket(0);
60  SetAlphaMultiplyOperation *apply_mask_operation = new SetAlphaMultiplyOperation();
61  converter.mapInputSocket(input_image_socket, apply_mask_operation->getInputSocket(0));
62  converter.addOperation(apply_mask_operation);
63  converter.addLink(extract_mask_operation->getOutputSocket(0),
64  apply_mask_operation->getInputSocket(1));
65  converter.mapOutputSocket(output_image_socket, apply_mask_operation->getOutputSocket(0));
66 
67  NodeOutput *output_pick_socket = this->getOutputSocket(2);
68  SetAlphaMultiplyOperation *extract_pick_operation = new SetAlphaMultiplyOperation();
69  converter.addOperation(extract_pick_operation);
70  converter.addInputValue(extract_pick_operation->getInputSocket(1), 1.0f);
71  converter.addLink(cryptomatte_operation->getOutputSocket(0),
72  extract_pick_operation->getInputSocket(0));
73  converter.mapOutputSocket(output_pick_socket, extract_pick_operation->getOutputSocket(0));
74 }
75 
76 /* \} */
77 
80 static std::string prefix_from_node(const CompositorContext &context, const bNode &node)
81 {
82  char prefix[MAX_NAME];
83  ntreeCompositCryptomatteLayerPrefix(context.getScene(), &node, prefix, sizeof(prefix));
84  return std::string(prefix, BLI_strnlen(prefix, sizeof(prefix)));
85 }
86 
87 static std::string combined_layer_pass_name(RenderLayer *render_layer, RenderPass *render_pass)
88 {
89  if (render_layer->name[0] == '\0') {
90  return std::string(render_pass->name,
91  BLI_strnlen(render_pass->name, sizeof(render_pass->name)));
92  }
93 
94  std::string combined_name =
95  blender::StringRef(render_layer->name,
96  BLI_strnlen(render_layer->name, sizeof(render_layer->name))) +
97  "." +
98  blender::StringRef(render_pass->name,
99  BLI_strnlen(render_pass->name, sizeof(render_pass->name)));
100  return combined_name;
101 }
102 
103 void CryptomatteNode::input_operations_from_render_source(
104  const CompositorContext &context,
105  const bNode &node,
106  Vector<NodeOperation *> &r_input_operations)
107 {
108  Scene *scene = (Scene *)node.id;
109  if (!scene) {
110  return;
111  }
112 
114  Render *render = RE_GetSceneRender(scene);
115  RenderResult *render_result = render ? RE_AcquireResultRead(render) : nullptr;
116 
117  if (!render_result) {
118  return;
119  }
120 
121  short view_layer_id = 0;
122  const std::string prefix = prefix_from_node(context, node);
123  LISTBASE_FOREACH_INDEX (ViewLayer *, view_layer, &scene->view_layers, view_layer_id) {
124  RenderLayer *render_layer = RE_GetRenderLayer(render_result, view_layer->name);
125  if (render_layer) {
126  LISTBASE_FOREACH (RenderPass *, render_pass, &render_layer->passes) {
127  const std::string combined_name = combined_layer_pass_name(render_layer, render_pass);
128  if (blender::StringRef(combined_name).startswith(prefix)) {
129  RenderLayersProg *op = new RenderLayersProg(
130  render_pass->name, DataType::Color, render_pass->channels);
131  op->setScene(scene);
132  op->setLayerId(view_layer_id);
133  op->setRenderData(context.getRenderData());
134  op->setViewName(context.getViewName());
135  r_input_operations.append(op);
136  }
137  }
138  }
139  }
140  RE_ReleaseResult(render);
141 }
142 
143 void CryptomatteNode::input_operations_from_image_source(
144  const CompositorContext &context,
145  const bNode &node,
146  Vector<NodeOperation *> &r_input_operations)
147 {
148  NodeCryptomatte *cryptomatte_settings = (NodeCryptomatte *)node.storage;
149  Image *image = (Image *)node.id;
150  if (!image) {
151  return;
152  }
153 
154  BLI_assert(GS(image->id.name) == ID_IM);
155  if (image->type != IMA_TYPE_MULTILAYER) {
156  return;
157  }
158 
159  ImageUser *iuser = &cryptomatte_settings->iuser;
160  BKE_image_user_frame_calc(image, iuser, context.getFramenumber());
161  ImBuf *ibuf = BKE_image_acquire_ibuf(image, iuser, nullptr);
162 
163  if (image->rr) {
164  int view = 0;
165  if (BLI_listbase_count_at_most(&image->rr->views, 2) > 1) {
166  if (iuser->view == 0) {
167  /* Heuristic to match image name with scene names, check if the view name exists in the
168  * image. */
170  &image->rr->views, context.getViewName(), offsetof(RenderView, name));
171  if (view == -1) {
172  view = 0;
173  }
174  }
175  else {
176  view = iuser->view - 1;
177  }
178  }
179 
180  const std::string prefix = prefix_from_node(context, node);
181  int layer_index;
182  LISTBASE_FOREACH_INDEX (RenderLayer *, render_layer, &image->rr->layers, layer_index) {
183  if (!blender::StringRef(prefix).startswith(blender::StringRef(
184  render_layer->name, BLI_strnlen(render_layer->name, sizeof(render_layer->name))))) {
185  continue;
186  }
187  LISTBASE_FOREACH (RenderPass *, render_pass, &render_layer->passes) {
188  const std::string combined_name = combined_layer_pass_name(render_layer, render_pass);
189  if (blender::StringRef(combined_name).startswith(prefix)) {
190  MultilayerColorOperation *op = new MultilayerColorOperation(
191  render_layer, render_pass, view);
192  op->setImage(image);
193  op->setImageUser(iuser);
194  iuser->layer = layer_index;
195  op->setFramenumber(context.getFramenumber());
196  r_input_operations.append(op);
197  }
198  }
199  break;
200  }
201  }
202  BKE_image_release_ibuf(image, ibuf, nullptr);
203 }
204 
205 Vector<NodeOperation *> CryptomatteNode::create_input_operations(const CompositorContext &context,
206  const bNode &node)
207 {
208  Vector<NodeOperation *> input_operations;
209  switch (node.custom1) {
211  input_operations_from_render_source(context, node, input_operations);
212  break;
214  input_operations_from_image_source(context, node, input_operations);
215  break;
216  }
217 
218  if (input_operations.is_empty()) {
219  SetColorOperation *op = new SetColorOperation();
220  op->setChannel1(0.0f);
221  op->setChannel2(1.0f);
222  op->setChannel3(0.0f);
223  op->setChannel4(0.0f);
224  input_operations.append(op);
225  }
226  return input_operations;
227 }
229  NodeConverter &converter,
230  const CompositorContext &context,
231  const bNode &node,
232  const NodeCryptomatte *cryptomatte_settings) const
233 {
234  Vector<NodeOperation *> input_operations = create_input_operations(context, node);
235  CryptomatteOperation *operation = new CryptomatteOperation(input_operations.size());
236  LISTBASE_FOREACH (CryptomatteEntry *, cryptomatte_entry, &cryptomatte_settings->entries) {
237  operation->addObjectIndex(cryptomatte_entry->encoded_hash);
238  }
239  for (int i = 0; i < input_operations.size(); ++i) {
240  converter.addOperation(input_operations[i]);
241  converter.addLink(input_operations[i]->getOutputSocket(), operation->getInputSocket(i));
242  }
243  return operation;
244 }
245 
246 /* \} */
247 
252  NodeConverter &converter,
254  const bNode &UNUSED(node),
255  const NodeCryptomatte *cryptomatte_settings) const
256 {
257  const int num_inputs = inputs.size() - 1;
258  CryptomatteOperation *operation = new CryptomatteOperation(num_inputs);
259  if (cryptomatte_settings) {
260  LISTBASE_FOREACH (CryptomatteEntry *, cryptomatte_entry, &cryptomatte_settings->entries) {
261  operation->addObjectIndex(cryptomatte_entry->encoded_hash);
262  }
263  }
264 
265  for (int i = 0; i < num_inputs; i++) {
266  converter.mapInputSocket(this->getInputSocket(i + 1), operation->getInputSocket(i));
267  }
268 
269  return operation;
270 }
271 
272 /* \} */
273 
274 } // namespace blender::compositor
void BKE_image_release_ibuf(struct Image *ima, struct ImBuf *ibuf, void *lock)
Definition: image.c:5113
struct ImBuf * BKE_image_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, void **r_lock)
Definition: image.c:5100
void BKE_image_user_frame_calc(struct Image *ima, struct ImageUser *iuser, int cfra)
Definition: image.c:5335
void ntreeCompositCryptomatteLayerPrefix(const Scene *scene, const bNode *node, char *r_prefix, size_t prefix_len)
#define CMP_CRYPTOMATTE_SRC_RENDER
Definition: BKE_node.h:1259
#define CMP_CRYPTOMATTE_SRC_IMAGE
Definition: BKE_node.h:1260
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
Definition: BLI_listbase.h:180
int BLI_listbase_count_at_most(const struct ListBase *listbase, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_findstringindex(const struct ListBase *listbase, const char *id, const int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
size_t BLI_strnlen(const char *str, const size_t maxlen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: string.c:878
#define UNUSED(x)
@ ID_IM
Definition: DNA_ID_enums.h:65
@ ID_SCE
Definition: DNA_ID_enums.h:57
#define MAX_NAME
Definition: DNA_defs.h:62
@ IMA_TYPE_MULTILAYER
static AppView * view
int64_t size() const
Definition: BLI_vector.hh:662
void append(const T &value)
Definition: BLI_vector.hh:438
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 convertToOperations(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 mapInputSocket(NodeInput *node_socket, NodeOperationInput *operation_socket)
void addInputValue(NodeOperationInput *input, float value)
void addOperation(NodeOperation *operation)
void mapOutputSocket(NodeOutput *node_socket, NodeOperationOutput *operation_socket)
void addLink(NodeOperationOutput *from, NodeOperationInput *to)
NodeInput are sockets that can receive data/input.
Definition: COM_Node.h:210
NodeOperationInput * getInputSocket(unsigned int index)
NodeOperationOutput * getOutputSocket(unsigned int index=0)
NodeOutput are sockets that can send data/input.
Definition: COM_Node.h:258
Vector< NodeInput * > inputs
the list of actual input-sockets
Definition: COM_Node.h:68
NodeOutput * getOutputSocket(const unsigned int index=0) const
Definition: COM_Node.cc:108
bNode * getbNode() const
get the reference to the SDNA bNode struct
Definition: COM_Node.h:82
NodeInput * getInputSocket(const unsigned int index) const
Definition: COM_Node.cc:113
OperationNode * node
Scene scene
#define GS(x)
Definition: iris.c:241
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)
RenderResult * RE_AcquireResultRead(Render *re)
Definition: pipeline.c:343
Render * RE_GetSceneRender(const Scene *scene)
Definition: pipeline.c:591
RenderLayer * RE_GetRenderLayer(RenderResult *rr, const char *name)
Definition: pipeline.c:276
void RE_ReleaseResult(Render *re)
Definition: pipeline.c:379
char name[66]
Definition: DNA_ID.h:283
ListBase passes
Definition: RE_pipeline.h:108
char name[RE_MAXNAME]
Definition: RE_pipeline.h:100
char name[64]
Definition: RE_pipeline.h:80
ListBase view_layers