Blender V4.5
node_composite_cryptomatte.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
8
9#include <cstring>
10#include <string>
11
12#include <fmt/format.h>
13
14#include "BKE_node.hh"
16
17#include "BLI_assert.h"
18#include "BLI_listbase.h"
19#include "BLI_math_vector.h"
21#include "BLI_string.h"
22#include "BLI_string_ref.hh"
23#include "BLI_utildefines.h"
24#include "BLI_vector.hh"
25
26#include "IMB_imbuf_types.hh"
27
28#include "GPU_shader.hh"
29#include "GPU_texture.hh"
30
31#include "DNA_image_types.h"
32#include "DNA_scene_types.h"
33
34#include "BKE_context.hh"
35#include "BKE_cryptomatte.hh"
36#include "BKE_global.hh"
37#include "BKE_image.hh"
38#include "BKE_lib_id.hh"
39#include "BKE_library.hh"
40#include "BKE_main.hh"
41
42#include "MEM_guardedalloc.h"
43
44#include "RE_pipeline.h"
45
46#include "COM_node_operation.hh"
47#include "COM_result.hh"
48#include "COM_utilities.hh"
49
50#include <optional>
51
52/* -------------------------------------------------------------------- */
55
57 const bNode &node, const bool build_meta_data)
58{
60
61 Scene *scene = (Scene *)node.id;
62 if (!scene) {
63 return session;
64 }
65 BLI_assert(GS(scene->id.name) == ID_SCE);
66
68 BKE_cryptomatte_init_from_scene(scene, build_meta_data));
69 return session;
70}
71
73 const bNode &node)
74{
76 Image *image = (Image *)node.id;
77 if (!image) {
78 return session;
79 }
80 BLI_assert(GS(image->id.name) == ID_IM);
81
82 /* Construct an image user to retrieve the first image in the sequence, since the frame number
83 * might correspond to a non-existing image. We explicitly do not support the case where the
84 * image sequence has a changing structure. */
85 ImageUser image_user = {};
86 image_user.framenr = BKE_image_sequence_guess_offset(image);
87
88 ImBuf *ibuf = BKE_image_acquire_ibuf(image, &image_user, nullptr);
89 RenderResult *render_result = image->rr;
90 if (render_result) {
93 }
94 BKE_image_release_ibuf(image, ibuf, nullptr);
95 return session;
96}
97
99 const bNode &node, const bool build_meta_data)
100{
102 if (node.type_legacy != CMP_NODE_CRYPTOMATTE) {
103 return session;
104 }
105
106 switch (node.custom1) {
108 return cryptomatte_init_from_node_render(node, build_meta_data);
109 }
110
113 }
114 }
115 return session;
116}
117
118static CryptomatteEntry *cryptomatte_find(const NodeCryptomatte &n, float encoded_hash)
119{
121 if (entry->encoded_hash == encoded_hash) {
122 return entry;
123 }
124 }
125 return nullptr;
126}
127
128static void cryptomatte_add(bNode &node, NodeCryptomatte &node_cryptomatte, float encoded_hash)
129{
130 /* Check if entry already exist. */
131 if (cryptomatte_find(node_cryptomatte, encoded_hash)) {
132 return;
133 }
134
136 entry->encoded_hash = encoded_hash;
138 true);
139 if (session) {
140 BKE_cryptomatte_find_name(session.get(), encoded_hash, entry->name, sizeof(entry->name));
141 }
142
143 BLI_addtail(&node_cryptomatte.entries, entry);
144}
145
146static void cryptomatte_remove(NodeCryptomatte &n, float encoded_hash)
147{
148 CryptomatteEntry *entry = cryptomatte_find(n, encoded_hash);
149 if (!entry) {
150 return;
151 }
152 BLI_remlink(&n.entries, entry);
153 MEM_freeN(entry);
154}
155
157{
159 NodeCryptomatte *n = static_cast<NodeCryptomatte *>(node->storage);
160 if (n->runtime.add[0] != 0.0f) {
161 cryptomatte_add(*node, *n, n->runtime.add[0]);
162 zero_v3(n->runtime.add);
163 }
164}
165
176{
178 NodeCryptomatte *n = static_cast<NodeCryptomatte *>(node->storage);
180
182 false);
183
184 if (session) {
185 for (blender::StringRef layer_name :
187 {
189 layer_name.copy_utf8_truncated(layer->name);
190 BLI_addtail(&n->runtime.layers, layer);
191 }
192 }
193}
194
195void ntreeCompositCryptomatteLayerPrefix(const bNode *node, char *r_prefix, size_t prefix_maxncpy)
196{
198 NodeCryptomatte *node_cryptomatte = (NodeCryptomatte *)node->storage;
200 false);
201 std::string first_layer_name;
202
203 if (session) {
204 for (blender::StringRef layer_name :
206 {
207 if (first_layer_name.empty()) {
208 first_layer_name = layer_name;
209 }
210
211 if (layer_name == node_cryptomatte->layer_name) {
212 BLI_strncpy(r_prefix, node_cryptomatte->layer_name, prefix_maxncpy);
213 return;
214 }
215 }
216 }
217
218 const char *cstr = first_layer_name.c_str();
219 BLI_strncpy(r_prefix, cstr, prefix_maxncpy);
220}
221
223{
225 true);
226 return session_ptr.release();
227}
228
230
232
233using namespace blender::compositor;
234
236 public:
238
239 /* Should return the input image result. */
240 virtual Result &get_input_image() = 0;
241
242 /* Should returns all the Cryptomatte layers in order. */
244
245 /* If only a subset area of the Cryptomatte layers is to be considered, this method should return
246 * the lower bound of that area. The upper bound will be derived from the operation domain. */
248 {
249 return int2(0);
250 }
251
252 void execute() override
253 {
254 Vector<Result> layers = get_layers();
255 if (layers.is_empty()) {
257 return;
258 }
259
260 Result &output_pick = get_result("Pick");
261 if (output_pick.should_compute()) {
262 compute_pick(layers);
263 }
264
265 Result &matte_output = get_result("Matte");
266 Result &image_output = get_result("Image");
267 if (!matte_output.should_compute() && !image_output.should_compute()) {
268 return;
269 }
270
271 Result matte = compute_matte(layers);
272
273 if (image_output.should_compute()) {
274 compute_image(matte);
275 }
276
277 if (matte_output.should_compute()) {
278 matte_output.steal_data(matte);
279 }
280 else {
281 matte.release();
282 }
283 }
284
286 {
287 Result &pick = get_result("Pick");
288 if (pick.should_compute()) {
289 pick.allocate_invalid();
290 }
291
292 Result &matte = get_result("Matte");
293 if (matte.should_compute()) {
294 matte.allocate_invalid();
295 }
296
297 Result &image = get_result("Image");
298 if (image.should_compute()) {
299 image.allocate_invalid();
300 }
301 }
302
303 /* Computes the pick result, which is a special human-viewable image that the user can pick
304 * entities from using the Cryptomatte picker operator. See the shader for more information. */
305 void compute_pick(const Vector<Result> &layers)
306 {
307 Result &output_pick = get_result("Pick");
308 /* Promote to full precision since it stores the identifiers of the first Cryptomatte rank,
309 * which is a 32-bit float. See the shader for more information. */
311 /* Inform viewers that the pick result should not be color managed. */
312 output_pick.meta_data.is_non_color_data = true;
313
314 if (this->context().use_gpu()) {
315 this->compute_pick_gpu(layers);
316 }
317 else {
318 this->compute_pick_cpu(layers);
319 }
320 }
321
323 {
324 /* See this->compute_pick for why full precision is necessary. */
325 GPUShader *shader = context().get_shader("compositor_cryptomatte_pick", ResultPrecision::Full);
326 GPU_shader_bind(shader);
327
328 const int2 lower_bound = this->get_layers_lower_bound();
329 GPU_shader_uniform_2iv(shader, "lower_bound", lower_bound);
330
331 const Result &first_layer = layers[0];
332 first_layer.bind_as_texture(shader, "first_layer_tx");
333
334 const Domain domain = compute_domain();
335 Result &output_pick = get_result("Pick");
336 output_pick.allocate_texture(domain);
337 output_pick.bind_as_image(shader, "output_img");
338
340
342 first_layer.unbind_as_texture();
343 output_pick.unbind_as_image();
344 }
345
347 {
348 const int2 lower_bound = this->get_layers_lower_bound();
349
350 const Result &first_layer = layers[0];
351
352 const Domain domain = this->compute_domain();
353 Result &output = this->get_result("Pick");
354 output.allocate_texture(domain);
355
356 /* Blender provides a Cryptomatte picker operator (UI_OT_eyedropper_color) that can pick a
357 * Cryptomatte entity from an image. That image is a specially encoded image that the picker
358 * operator can understand. In particular, its red channel is the identifier of the entity in
359 * the first rank, while the green and blue channels are arbitrary [0, 1] compressed versions
360 * of the identifier to make the image more humane-viewable, but they are actually ignored by
361 * the picker operator, as can be seen in functions like eyedropper_color_sample_text_update,
362 * where only the red channel is considered.
363 *
364 * This shader just computes this special image given the first Cryptomatte layer. The output
365 * needs to be in full precision since the identifier is a 32-bit float.
366 *
367 * This is the same concept as the "keyable" image described in section "Matte Extraction:
368 * Implementation Details" in the original Cryptomatte publication:
369 *
370 * Friedman, Jonah, and Andrew C. Jones. "Fully automatic id mattes with support for motion
371 * blur and transparency." ACM SIGGRAPH 2015 Posters. 2015. 1-1.
372 *
373 * Except we put the identifier in the red channel by convention instead of the suggested blue
374 * channel. */
375 parallel_for(domain.size, [&](const int2 texel) {
376 /* Each layer stores two ranks, each rank contains a pair, the identifier and the coverage of
377 * the entity identified by the identifier. */
378 float2 first_rank = first_layer.load_pixel<float4>(texel + lower_bound).xy();
379 float id_of_first_rank = first_rank.x;
380
381 /* There is no logic to this, we just compute arbitrary compressed versions of the identifier
382 * in the [0, 1] range to make the image more human-viewable. */
383 uint32_t hash_value;
384 std::memcpy(&hash_value, &id_of_first_rank, sizeof(uint32_t));
385 float green = float(hash_value << 8) / float(0xFFFFFFFFu);
386 float blue = float(hash_value << 16) / float(0xFFFFFFFFu);
387
388 output.store_pixel(texel, float4(id_of_first_rank, green, blue, 1.0f));
389 });
390 }
391
392 /* Computes and returns the matte by accumulating the coverage of all entities whose identifiers
393 * are selected by the user, across all layers. See the shader for more information. */
395 {
396 if (this->context().use_gpu()) {
397 return this->compute_matte_gpu(layers);
398 }
399
400 return this->compute_matte_cpu(layers);
401 }
402
404 {
405 const Domain domain = compute_domain();
407 output_matte.allocate_texture(domain);
408
409 /* Clear the matte to zero to ready it to accumulate the coverage. */
410 const float4 zero_color = float4(0.0f);
411 GPU_texture_clear(output_matte, GPU_DATA_FLOAT, zero_color);
412
413 Vector<float> identifiers = get_identifiers();
414 /* The user haven't selected any entities, return the currently zero matte. */
415 if (identifiers.is_empty()) {
416 return output_matte;
417 }
418
419 GPUShader *shader = context().get_shader("compositor_cryptomatte_matte");
420 GPU_shader_bind(shader);
421
422 const int2 lower_bound = this->get_layers_lower_bound();
423 GPU_shader_uniform_2iv(shader, "lower_bound", lower_bound);
424 GPU_shader_uniform_1i(shader, "identifiers_count", identifiers.size());
425 GPU_shader_uniform_1f_array(shader, "identifiers", identifiers.size(), identifiers.data());
426
427 for (const Result &layer : layers) {
428 layer.bind_as_texture(shader, "layer_tx");
429
430 /* Bind the matte with read access, since we will be accumulating in it. */
431 output_matte.bind_as_image(shader, "matte_img", true);
432
434
435 layer.unbind_as_texture();
436 output_matte.unbind_as_image();
437 }
438
440
441 return output_matte;
442 }
443
445 {
446 const Domain domain = compute_domain();
448 matte.allocate_texture(domain);
449
450 /* Clear the matte to zero to ready it to accumulate the coverage. */
451 parallel_for(domain.size, [&](const int2 texel) { matte.store_pixel(texel, 0.0f); });
452
453 Vector<float> identifiers = get_identifiers();
454 /* The user haven't selected any entities, return the currently zero matte. */
455 if (identifiers.is_empty()) {
456 return matte;
457 }
458
459 const int2 lower_bound = this->get_layers_lower_bound();
460 for (const Result &layer_result : layers) {
461 /* Loops over all identifiers selected by the user, and accumulate the coverage of ranks
462 * whose identifiers match that of the user selected identifiers.
463 *
464 * This is described in section "Matte Extraction: Implementation Details" in the original
465 * Cryptomatte publication:
466 *
467 * Friedman, Jonah, and Andrew C. Jones. "Fully automatic id mattes with support for motion
468 * blur and transparency." ACM SIGGRAPH 2015 Posters. 2015. 1-1.
469 */
470 parallel_for(domain.size, [&](const int2 texel) {
471 float4 layer = layer_result.load_pixel<float4>(texel + lower_bound);
472
473 /* Each Cryptomatte layer stores two ranks. */
474 float2 first_rank = layer.xy();
475 float2 second_rank = layer.zw();
476
477 /* Each Cryptomatte rank stores a pair of an identifier and the coverage of the entity
478 * identified by that identifier. */
479 float identifier_of_first_rank = first_rank.x;
480 float coverage_of_first_rank = first_rank.y;
481 float identifier_of_second_rank = second_rank.x;
482 float coverage_of_second_rank = second_rank.y;
483
484 /* Loop over all identifiers selected by the user, if the identifier of either of the ranks
485 * match it, accumulate its coverage. */
486 float total_coverage = 0.0f;
487 for (const float &identifier : identifiers) {
488 if (identifier_of_first_rank == identifier) {
489 total_coverage += coverage_of_first_rank;
490 }
491 if (identifier_of_second_rank == identifier) {
492 total_coverage += coverage_of_second_rank;
493 }
494 }
495
496 /* Add the total coverage to the coverage accumulated by previous layers. */
497 matte.store_pixel(texel, matte.load_pixel<float>(texel) + total_coverage);
498 });
499 }
500
501 return matte;
502 }
503
504 /* Computes the output image result by pre-multiplying the matte to the image. */
505 void compute_image(const Result &matte)
506 {
507 if (this->context().use_gpu()) {
508 this->compute_image_gpu(matte);
509 }
510 else {
511 this->compute_image_cpu(matte);
512 }
513 }
514
515 void compute_image_gpu(const Result &matte)
516 {
517 GPUShader *shader = context().get_shader("compositor_cryptomatte_image");
518 GPU_shader_bind(shader);
519
520 Result &input_image = get_input_image();
521 input_image.bind_as_texture(shader, "input_tx");
522
523 matte.bind_as_texture(shader, "matte_tx");
524
525 const Domain domain = compute_domain();
526 Result &image_output = get_result("Image");
527 image_output.allocate_texture(domain);
528 image_output.bind_as_image(shader, "output_img");
529
531
533 input_image.unbind_as_texture();
534 matte.unbind_as_texture();
535 image_output.unbind_as_image();
536 }
537
538 void compute_image_cpu(const Result &matte)
539 {
541
542 const Domain domain = compute_domain();
543 Result &output = get_result("Image");
544 output.allocate_texture(domain);
545
546 parallel_for(domain.size, [&](const int2 texel) {
547 float4 input_color = input.load_pixel<float4, true>(texel);
548 float input_matte = matte.load_pixel<float>(texel);
549
550 /* Premultiply the alpha to the image. */
551 output.store_pixel(texel, input_color * input_matte);
552 });
553 }
554
555 /* Get the identifiers of the entities selected by the user to generate a matte from. The
556 * identifiers are hashes of the names of the entities encoded in floats. See the "ID Generation"
557 * section of the Cryptomatte specification for more information. */
559 {
560 Vector<float> identifiers;
561 LISTBASE_FOREACH (CryptomatteEntry *, cryptomatte_entry, &node_storage(bnode()).entries) {
562 identifiers.append(cryptomatte_entry->encoded_hash);
563 }
564 return identifiers;
565 }
566};
567
568} // namespace blender::nodes::node_composite_base_cryptomatte_cc
569
571
573
574static bke::bNodeSocketTemplate cmp_node_cryptomatte_out[] = {
575 {SOCK_RGBA, N_("Image")},
576 {SOCK_FLOAT, N_("Matte")},
577 {SOCK_RGBA, N_("Pick")},
578 {-1, ""},
579};
580
582{
583 b.add_input<decl::Color>("Image")
584 .default_value({0.0f, 0.0f, 0.0f, 1.0f})
585 .compositor_domain_priority(0);
586 b.add_output<decl::Color>("Image");
587 b.add_output<decl::Float>("Matte");
588 b.add_output<decl::Color>("Pick");
589}
590
591static void node_init_cryptomatte(bNodeTree * /*ntree*/, bNode *node)
592{
594 node->storage = user;
595}
596
598{
599 Scene *scene = CTX_data_scene(C);
600 bNode *node = static_cast<bNode *>(ptr->data);
602 node->id = &scene->id;
603 id_us_plus(node->id);
604}
605
606static void node_free_cryptomatte(bNode *node)
607{
609 NodeCryptomatte *nc = static_cast<NodeCryptomatte *>(node->storage);
610
611 if (nc) {
615 MEM_freeN(nc);
616 }
617}
618
619static void node_copy_cryptomatte(bNodeTree * /*dst_ntree*/,
620 bNode *dest_node,
621 const bNode *src_node)
622{
623 NodeCryptomatte *src_nc = static_cast<NodeCryptomatte *>(src_node->storage);
624 NodeCryptomatte *dest_nc = static_cast<NodeCryptomatte *>(MEM_dupallocN(src_nc));
625
626 BLI_duplicatelist(&dest_nc->entries, &src_nc->entries);
628 dest_nc->matte_id = static_cast<char *>(MEM_dupallocN(src_nc->matte_id));
629 dest_node->storage = dest_nc;
630}
631
632static bool node_poll_cryptomatte(const blender::bke::bNodeType * /*ntype*/,
633 const bNodeTree *ntree,
634 const char **r_disabled_hint)
635{
636 if (STREQ(ntree->idname, "CompositorNodeTree")) {
637 Scene *scene;
638
639 /* See node_composit_poll_rlayers. */
640 for (scene = static_cast<Scene *>(G.main->scenes.first); scene;
641 scene = static_cast<Scene *>(scene->id.next))
642 {
643 if (scene->nodetree == ntree) {
644 break;
645 }
646 }
647
648 if (scene == nullptr) {
649 *r_disabled_hint = RPT_(
650 "The node tree must be the compositing node tree of any scene in the file");
651 }
652 return scene != nullptr;
653 }
654 *r_disabled_hint = RPT_("Not a compositor node tree");
655 return false;
656}
657
658static void node_update_cryptomatte(bNodeTree *ntree, bNode *node)
659{
660 cmp_node_update_default(ntree, node);
662}
663
664using namespace blender::compositor;
666
668 public:
669 using BaseCryptoMatteOperation::BaseCryptoMatteOperation;
670
672 {
673 return get_input("Image");
674 }
675
676 /* Returns all the relevant Cryptomatte layers from the selected source. */
678 {
679 switch (get_source()) {
681 return get_layers_from_render();
683 return get_layers_from_image();
684 }
685
687 return Vector<Result>();
688 }
689
690 /* Returns all the relevant Cryptomatte layers from the selected layer. */
692 {
693 Vector<Result> layers;
694
695 Scene *scene = get_scene();
696 if (!scene) {
697 return layers;
698 }
699
700 const std::string type_name = get_type_name();
701
702 int view_layer_index = 0;
703 LISTBASE_FOREACH_INDEX (ViewLayer *, view_layer, &scene->view_layers, view_layer_index) {
704 /* Find out which type of Cryptomatte layer the node uses, if non matched, then this is not
705 * the view layer used by the node and we check other view layers. */
706 const char *cryptomatte_type = nullptr;
707 const std::string layer_prefix = std::string(view_layer->name) + ".";
708 if (type_name == layer_prefix + RE_PASSNAME_CRYPTOMATTE_OBJECT) {
709 cryptomatte_type = RE_PASSNAME_CRYPTOMATTE_OBJECT;
710 }
711 else if (type_name == layer_prefix + RE_PASSNAME_CRYPTOMATTE_ASSET) {
712 cryptomatte_type = RE_PASSNAME_CRYPTOMATTE_ASSET;
713 }
714 else if (type_name == layer_prefix + RE_PASSNAME_CRYPTOMATTE_MATERIAL) {
715 cryptomatte_type = RE_PASSNAME_CRYPTOMATTE_MATERIAL;
716 }
717
718 /* Not the view layer used by the node. */
719 if (!cryptomatte_type) {
720 continue;
721 }
722
723 /* Each layer stores two ranks/levels, so do ceiling division by two. */
724 const int cryptomatte_layers_count = int(math::ceil(view_layer->cryptomatte_levels / 2.0f));
725 for (int i = 0; i < cryptomatte_layers_count; i++) {
726 const std::string pass_name = fmt::format("{}{:02}", cryptomatte_type, i);
727 Result pass_result = context().get_pass(scene, view_layer_index, pass_name.c_str());
728
729 /* If this Cryptomatte layer wasn't found, then all later Cryptomatte layers can't be used
730 * even if they were found. */
731 if (!pass_result.is_allocated()) {
732 return layers;
733 }
734 layers.append(pass_result);
735 }
736
737 /* The target view later was processed already, no need to check other view layers. */
738 return layers;
739 }
740
741 return layers;
742 }
743
744 /* Returns all the relevant Cryptomatte layers from the selected EXR image. */
746 {
747 Vector<Result> layers;
748
749 Image *image = this->get_image();
750 if (!image || image->type != IMA_TYPE_MULTILAYER) {
751 return layers;
752 }
753
754 /* The render result structure of the image is populated as a side effect of the acquisition of
755 * an image buffer, so acquire an image buffer and immediately release it since it is not
756 * actually needed. */
757 ImageUser image_user_for_layer = this->get_image_user();
758 ImBuf *image_buffer = BKE_image_acquire_ibuf(image, &image_user_for_layer, nullptr);
759 BKE_image_release_ibuf(image, image_buffer, nullptr);
760 if (!image_buffer || !image->rr) {
761 return layers;
762 }
763
764 RenderResult *render_result = BKE_image_acquire_renderresult(nullptr, image);
765
766 /* Gather all pass names first before retrieving the images because render layers might get
767 * freed when retrieving the images. */
768 Vector<std::string> pass_names;
769
770 int layer_index;
771 const std::string type_name = this->get_type_name();
772 LISTBASE_FOREACH_INDEX (RenderLayer *, render_layer, &render_result->layers, layer_index) {
773 /* If the Cryptomatte type name doesn't start with the layer name, then it is not a
774 * Cryptomatte layer. Unless it is an unnamed layer, in which case, we need to check its
775 * passes. */
776 const bool is_unnamed_layer = render_layer->name[0] == '\0';
777 if (!is_unnamed_layer && !StringRefNull(type_name).startswith(render_layer->name)) {
778 continue;
779 }
780
781 LISTBASE_FOREACH (RenderPass *, render_pass, &render_layer->passes) {
782 /* If the combined pass name doesn't start with the Cryptomatte type name, then it is not a
783 * Cryptomatte layer. Furthermore, if it is equal to the Cryptomatte type name with no
784 * suffix, then it can be ignored, because it is a deprecated Cryptomatte preview layer
785 * according to the "EXR File: Layer Naming" section of the Cryptomatte specification. */
786 const std::string combined_name = this->get_combined_layer_pass_name(render_layer,
787 render_pass);
788 if (combined_name == type_name || !StringRef(combined_name).startswith(type_name)) {
789 continue;
790 }
791
792 pass_names.append(render_pass->name);
793 }
794
795 /* If we already found Cryptomatte layers, no need to check other render layers. */
796 if (!pass_names.is_empty()) {
797 break;
798 }
799 }
800
801 BKE_image_release_renderresult(nullptr, image, render_result);
802
803 image_user_for_layer.layer = layer_index;
804 for (const std::string &pass_name : pass_names) {
805 Result pass_result = context().cache_manager().cached_images.get(
806 context(), image, &image_user_for_layer, pass_name.c_str());
807 layers.append(pass_result);
808 }
809
810 return layers;
811 }
812
813 /* Returns the combined name of the render layer and pass using the EXR convention of a period
814 * separator. */
815 std::string get_combined_layer_pass_name(RenderLayer *render_layer, RenderPass *render_pass)
816 {
817 if (render_layer->name[0] == '\0') {
818 return std::string(render_pass->name);
819 }
820 return std::string(render_layer->name) + "." + std::string(render_pass->name);
821 }
822
823 /* Get the selected type name of the Cryptomatte from the metadata of the image/render. This type
824 * name will be used to identify the corresponding layers in the source image/render. See the
825 * "EXR File: Layer Naming" section of the Cryptomatte specification for more information on what
826 * this represents. */
827 std::string get_type_name()
828 {
829 char type_name[MAX_NAME];
830 ntreeCompositCryptomatteLayerPrefix(&bnode(), type_name, sizeof(type_name));
831 return std::string(type_name);
832 }
833
835 {
836 switch (get_source()) {
838 const rcti compositing_region = this->context().get_compositing_region();
839 return int2(compositing_region.xmin, compositing_region.ymin);
840 }
842 return int2(0);
843 }
844
846 return int2(0);
847 }
848
849 /* The domain should be centered with the same size as the source. In case of invalid source,
850 * fall back to the domain inferred from the input. */
852 {
853 switch (get_source()) {
855 return Domain(context().get_compositing_region_size());
857 return compute_image_domain();
858 }
859
861 return Domain::identity();
862 }
863
864 /* In case of an image source, the domain should be centered with the same size as the source
865 * image. In case of an invalid image, fall back to the domain inferred from the input. */
867 {
869
870 Image *image = get_image();
871 if (!image) {
873 }
874
875 ImageUser image_user = this->get_image_user();
876 ImBuf *image_buffer = BKE_image_acquire_ibuf(image, &image_user, nullptr);
877 if (!image_buffer) {
879 }
880
881 const int2 image_size = int2(image_buffer->x, image_buffer->y);
882 BKE_image_release_ibuf(image, image_buffer, nullptr);
883 return Domain(image_size);
884 }
885
887 {
889
890 Image *image = this->get_image();
891 BLI_assert(image);
892
893 /* Compute the effective frame number of the image if it was animated. */
894 ImageUser image_user_for_frame = node_storage(bnode()).iuser;
895 BKE_image_user_frame_calc(image, &image_user_for_frame, this->context().get_frame_number());
896
897 return image_user_for_frame;
898 }
899
901 {
903 return reinterpret_cast<Scene *>(bnode().id);
904 }
905
907 {
909 return reinterpret_cast<Image *>(bnode().id);
910 }
911
916};
917
919{
920 return new CryptoMatteOperation(context, node);
921}
922
923} // namespace blender::nodes::node_composite_cryptomatte_cc
924
926{
928
929 static blender::bke::bNodeType ntype;
930
931 cmp_node_type_base(&ntype, "CompositorNodeCryptomatteV2", CMP_NODE_CRYPTOMATTE);
932 ntype.ui_name = "Cryptomatte";
933 ntype.ui_description =
934 "Generate matte for individual objects and materials using Cryptomatte render passes";
935 ntype.enum_name_legacy = "CRYPTOMATTE_V2";
936 ntype.nclass = NODE_CLASS_MATTE;
937 ntype.declare = file_ns::cmp_node_cryptomatte_declare;
938 blender::bke::node_type_size(ntype, 240, 100, 700);
939 ntype.initfunc = file_ns::node_init_cryptomatte;
940 ntype.initfunc_api = file_ns::node_init_api_cryptomatte;
941 ntype.poll = file_ns::node_poll_cryptomatte;
942 ntype.updatefunc = file_ns::node_update_cryptomatte;
944 ntype, "NodeCryptomatte", file_ns::node_free_cryptomatte, file_ns::node_copy_cryptomatte);
945 ntype.get_compositor_operation = file_ns::get_compositor_operation;
946
948}
950
951
952
953/* -------------------------------------------------------------------- */
956
958{
959 BLI_assert(node->type_legacy == CMP_NODE_CRYPTOMATTE_LEGACY);
960 NodeCryptomatte *n = static_cast<NodeCryptomatte *>(node->storage);
961 char sockname[32];
962 n->inputs_num++;
963 SNPRINTF(sockname, "Crypto %.2d", n->inputs_num - 1);
965 *ntree, *node, SOCK_IN, SOCK_RGBA, PROP_NONE, "", sockname);
966 return sock;
967}
968
970{
972 NodeCryptomatte *n = static_cast<NodeCryptomatte *>(node->storage);
973 if (n->inputs_num < 2) {
974 return 0;
975 }
976 bNodeSocket *sock = static_cast<bNodeSocket *>(node->inputs.last);
977 blender::bke::node_remove_socket(*ntree, *node, *sock);
978 n->inputs_num--;
979 return 1;
980}
981
983
985{
987 file_ns::node_init_cryptomatte(ntree, node);
988
989 bke::node_add_static_socket(*ntree, *node, SOCK_IN, SOCK_RGBA, PROP_NONE, "image", "Image");
990
991 /* Add three inputs by default, as recommended by the Cryptomatte specification. */
995}
996
997using namespace blender::compositor;
999
1001 public:
1002 using BaseCryptoMatteOperation::BaseCryptoMatteOperation;
1003
1005 {
1006 return get_input("image");
1007 }
1008
1010 {
1011 Vector<Result> layers;
1012 /* Add all valid results of all inputs except the first input, which is the input image. */
1013 for (const bNodeSocket *input_socket : bnode().input_sockets().drop_front(1)) {
1014 if (!is_socket_available(input_socket)) {
1015 continue;
1016 }
1017
1018 const Result input = get_input(input_socket->identifier);
1019 if (input.is_single_value()) {
1020 /* If this Cryptomatte layer is not valid, because it is not an image, then all later
1021 * Cryptomatte layers can't be used even if they were valid. */
1022 break;
1023 }
1024 layers.append(input);
1025 }
1026 return layers;
1027 }
1028};
1029
1031{
1032 return new LegacyCryptoMatteOperation(context, node);
1033}
1034
1035} // namespace blender::nodes::node_composite_legacy_cryptomatte_cc
1036
1038{
1041
1042 static blender::bke::bNodeType ntype;
1043
1044 cmp_node_type_base(&ntype, "CompositorNodeCryptomatte", CMP_NODE_CRYPTOMATTE_LEGACY);
1045 ntype.ui_name = "Cryptomatte (Legacy)";
1046 ntype.ui_description = "Deprecated. Use Cryptomatte Node instead";
1047 ntype.enum_name_legacy = "CRYPTOMATTE";
1048 ntype.nclass = NODE_CLASS_MATTE;
1049 blender::bke::node_type_socket_templates(&ntype, nullptr, file_ns::cmp_node_cryptomatte_out);
1050 ntype.initfunc = legacy_file_ns::node_init_cryptomatte_legacy;
1052 ntype, "NodeCryptomatte", file_ns::node_free_cryptomatte, file_ns::node_copy_cryptomatte);
1053 ntype.gather_link_search_ops = nullptr;
1054 ntype.get_compositor_operation = legacy_file_ns::get_compositor_operation;
1055
1057}
1059
1060
Scene * CTX_data_scene(const bContext *C)
bool BKE_cryptomatte_find_name(const struct CryptomatteSession *session, float encoded_hash, char *r_name, int name_maxncpy)
struct CryptomatteSession * BKE_cryptomatte_init_from_render_result(const struct RenderResult *render_result)
struct CryptomatteSession * BKE_cryptomatte_init_from_scene(const struct Scene *scene, bool build_meta_data)
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)
void BKE_image_release_renderresult(Scene *scene, Image *ima, RenderResult *render_result)
int BKE_image_sequence_guess_offset(Image *image)
RenderResult * BKE_image_acquire_renderresult(Scene *scene, Image *ima)
void id_us_plus(ID *id)
Definition lib_id.cc:353
#define NODE_CLASS_MATTE
Definition BKE_node.hh:440
#define NODE_STORAGE_FUNCS(StorageT)
Definition BKE_node.hh:1215
#define CMP_NODE_CRYPTOMATTE
#define CMP_NODE_CRYPTOMATTE_LEGACY
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE void BLI_listbase_clear(ListBase *lb)
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:497
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:131
void void void void void void BLI_duplicatelist(ListBase *dst, const ListBase *src) ATTR_NONNULL(1
MINLINE void zero_v3(float r[3])
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:599
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
#define ELEM(...)
#define STREQ(a, b)
#define RPT_(msgid)
float[3] Vector
@ ID_IM
@ ID_SCE
@ IMA_TYPE_MULTILAYER
CMPNodeCryptomatteSource
@ CMP_NODE_CRYPTOMATTE_SOURCE_IMAGE
@ CMP_NODE_CRYPTOMATTE_SOURCE_RENDER
@ SOCK_IN
@ SOCK_FLOAT
@ SOCK_RGBA
#define RE_PASSNAME_CRYPTOMATTE_MATERIAL
#define RE_PASSNAME_CRYPTOMATTE_ASSET
#define RE_PASSNAME_CRYPTOMATTE_OBJECT
void GPU_shader_uniform_1i(GPUShader *sh, const char *name, int value)
void GPU_shader_bind(GPUShader *shader, const blender::gpu::shader::SpecializationConstants *constants_state=nullptr)
void GPU_shader_uniform_1f_array(GPUShader *sh, const char *name, int len, const float *val)
void GPU_shader_uniform_2iv(GPUShader *sh, const char *name, const int data[2])
void GPU_shader_unbind()
void GPU_texture_clear(GPUTexture *texture, eGPUDataFormat data_format, const void *data)
@ GPU_DATA_FLOAT
Read Guarded memory(de)allocation.
#define NOD_REGISTER_NODE(REGISTER_FUNC)
@ PROP_NONE
Definition RNA_types.hh:221
#define C
Definition RandGen.cpp:29
int64_t size() const
void append(const T &value)
bool is_empty() const
Result get(Context &context, Image *image, const ImageUser *image_user, const char *pass_name)
Result create_result(ResultType type, ResultPrecision precision)
GPUShader * get_shader(const char *info_name, ResultPrecision precision)
virtual Result get_pass(const Scene *scene, int view_layer, const char *pass_name)=0
virtual rcti get_compositing_region() const =0
static Domain identity()
Definition domain.cc:25
NodeOperation(Context &context, DNode node)
Result & get_result(StringRef identifier)
Definition operation.cc:39
Result & get_input(StringRef identifier) const
Definition operation.cc:138
virtual Domain compute_domain()
Definition operation.cc:56
void allocate_texture(Domain domain, bool from_pool=true)
Definition result.cc:309
void store_pixel(const int2 &texel, const T &pixel_value)
void unbind_as_texture() const
Definition result.cc:389
void bind_as_texture(GPUShader *shader, const char *texture_name) const
Definition result.cc:365
bool is_allocated() const
Definition result.cc:630
void set_precision(ResultPrecision precision)
Definition result.cc:618
T load_pixel(const int2 &texel) const
void bind_as_image(GPUShader *shader, const char *image_name, bool read=false) const
Definition result.cc:376
void unbind_as_image() const
Definition result.cc:395
void steal_data(Result &source)
Definition result.cc:418
std::string get_combined_layer_pass_name(RenderLayer *render_layer, RenderPass *render_pass)
#define input
#define output
#define MEM_SAFE_FREE(v)
#define MAX_NAME
#define GS(a)
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_dupallocN(const void *vmemh)
Definition mallocn.cc:143
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
#define G(x, y, z)
std::unique_ptr< CryptomatteSession, CryptomatteSessionDeleter > CryptomatteSessionPtr
const blender::Vector< std::string > & BKE_cryptomatte_layer_names_get(const CryptomatteSession &session)
void node_remove_socket(bNodeTree &ntree, bNode &node, bNodeSocket &sock)
Definition node.cc:3575
void node_type_size(bNodeType &ntype, int width, int minwidth, int maxwidth)
Definition node.cc:5573
void node_register_type(bNodeType &ntype)
Definition node.cc:2748
void node_type_socket_templates(bNodeType *ntype, bNodeSocketTemplate *inputs, bNodeSocketTemplate *outputs)
Definition node.cc:5541
bNodeSocket * node_add_static_socket(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out, int type, int subtype, StringRefNull identifier, StringRefNull name)
Definition node.cc:3529
void node_type_storage(bNodeType &ntype, std::optional< StringRefNull > storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
Definition node.cc:5603
void compute_dispatch_threads_at_least(GPUShader *shader, int2 threads_range, int2 local_size=int2(16))
Definition utilities.cc:170
void parallel_for(const int2 range, const Function &function)
bool is_socket_available(const bNodeSocket *socket)
Definition utilities.cc:25
T ceil(const T &a)
static void node_update_cryptomatte(bNodeTree *ntree, bNode *node)
static void node_copy_cryptomatte(bNodeTree *, bNode *dest_node, const bNode *src_node)
static void node_init_api_cryptomatte(const bContext *C, PointerRNA *ptr)
static NodeOperation * get_compositor_operation(Context &context, DNode node)
static void cmp_node_cryptomatte_declare(NodeDeclarationBuilder &b)
static bool node_poll_cryptomatte(const blender::bke::bNodeType *, const bNodeTree *ntree, const char **r_disabled_hint)
static void node_init_cryptomatte(bNodeTree *, bNode *node)
static void node_init_cryptomatte_legacy(bNodeTree *ntree, bNode *node)
static NodeOperation * get_compositor_operation(Context &context, DNode node)
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
void ntreeCompositCryptomatteLayerPrefix(const bNode *node, char *r_prefix, size_t prefix_maxncpy)
static blender::bke::cryptomatte::CryptomatteSessionPtr cryptomatte_init_from_node_render(const bNode &node, const bool build_meta_data)
static CryptomatteEntry * cryptomatte_find(const NodeCryptomatte &n, float encoded_hash)
int ntreeCompositCryptomatteRemoveSocket(bNodeTree *ntree, bNode *node)
void ntreeCompositCryptomatteSyncFromRemove(bNode *node)
static void register_node_type_cmp_cryptomatte_legacy()
CryptomatteSession * ntreeCompositCryptomatteSession(bNode *node)
static void register_node_type_cmp_cryptomatte()
bNodeSocket * ntreeCompositCryptomatteAddSocket(bNodeTree *ntree, bNode *node)
void ntreeCompositCryptomatteUpdateLayerNames(bNode *node)
static void cryptomatte_remove(NodeCryptomatte &n, float encoded_hash)
static blender::bke::cryptomatte::CryptomatteSessionPtr cryptomatte_init_from_node(const bNode &node, const bool build_meta_data)
static void cryptomatte_add(bNode &node, NodeCryptomatte &node_cryptomatte, float encoded_hash)
void ntreeCompositCryptomatteSyncFromAdd(bNode *node)
static blender::bke::cryptomatte::CryptomatteSessionPtr cryptomatte_init_from_node_image(const bNode &node)
void cmp_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
void cmp_node_update_default(bNodeTree *, bNode *node)
void * next
Definition DNA_ID.h:407
char name[66]
Definition DNA_ID.h:415
struct RenderResult * rr
void * last
NodeCryptomatte_Runtime runtime
char name[RE_MAXNAME]
Definition RE_pipeline.h:81
char name[64]
Definition RE_pipeline.h:50
ListBase layers
struct bNodeTree * nodetree
ListBase view_layers
char idname[64]
int16_t custom1
ListBase inputs
struct ID * id
int16_t type_legacy
void * storage
Defines a node type.
Definition BKE_node.hh:226
std::string ui_description
Definition BKE_node.hh:232
NodeGetCompositorOperationFunction get_compositor_operation
Definition BKE_node.hh:336
void(* initfunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:277
const char * enum_name_legacy
Definition BKE_node.hh:235
bool(* poll)(const bNodeType *ntype, const bNodeTree *nodetree, const char **r_disabled_hint)
Definition BKE_node.hh:309
NodeGatherSocketLinkOperationsFunction gather_link_search_ops
Definition BKE_node.hh:371
NodeDeclareFunction declare
Definition BKE_node.hh:355
void(* updatefunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:269
void(* initfunc_api)(const bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:290
int ymin
int xmin
i
Definition text_draw.cc:230
#define N_(msgid)
PointerRNA * ptr
Definition wm_files.cc:4227