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