12#include <fmt/format.h>
63 const bNode &node,
const bool build_meta_data)
105 const bNode &node,
const bool build_meta_data)
127 if (entry->encoded_hash == encoded_hash) {
195 layer_name.copy_utf8_truncated(layer->
name);
207 std::string first_layer_name;
213 if (first_layer_name.empty()) {
214 first_layer_name = layer_name;
217 if (layer_name == node_cryptomatte->
layer_name) {
224 const char *cstr = first_layer_name.c_str();
232 return session_ptr.release();
320 if (this->
context().use_gpu()) {
338 const Result &first_layer = layers[0];
357 const Result &first_layer = layers[0];
385 float2 first_rank = first_layer.load_pixel<float4>(texel + lower_bound).xy();
386 float id_of_first_rank = first_rank.x;
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);
395 output.store_pixel(texel, float4(id_of_first_rank, green, blue, 1.0f));
403 if (this->
context().use_gpu()) {
434 for (
const Result &layer : layers) {
435 layer.bind_as_texture(shader,
"layer_tx");
442 layer.unbind_as_texture();
467 for (
const Result &layer_result : layers) {
478 float4 layer = layer_result.load_pixel<float4>(texel + lower_bound);
481 float2 first_rank = layer.xy();
482 float2 second_rank = layer.zw();
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;
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;
498 if (identifier_of_second_rank == identifier) {
499 total_coverage += coverage_of_second_rank;
514 if (this->
context().use_gpu()) {
551 output.allocate_texture(domain);
554 float4 input_color = input.load_pixel<float4, true>(texel);
555 float input_matte = matte.load_pixel<float>(texel);
558 output.store_pixel(texel, input_color * input_matte);
569 identifiers.
append(cryptomatte_entry->encoded_hash);
591 .default_value({0.0f, 0.0f, 0.0f, 1.0f})
592 .structure_type(StructureType::Dynamic);
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);
610 node->
id = &scene->
id;
629 const bNode *src_node)
655 row.
text =
RPT_(
"Node Unsupported");
657 "The Cryptomatte node in render mode is only supported for scene compositing");
658 row.
icon = ICON_ERROR;
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;
685 using BaseCryptoMatteOperation::BaseCryptoMatteOperation;
718 int view_layer_index = 0;
722 const char *cryptomatte_type =
nullptr;
723 const std::string layer_prefix = std::string(view_layer->name) +
".";
735 if (!cryptomatte_type) {
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);
750 layers.
append(pass_result);
776 if (!image_buffer || !image->
rr) {
792 const bool is_unnamed_layer = render_layer->name[0] ==
'\0';
793 if (!is_unnamed_layer && !
StringRefNull(type_name).startswith(render_layer->name)) {
804 if (combined_name == type_name || !
StringRef(combined_name).startswith(type_name)) {
808 pass_names.
append(render_pass->name);
819 image_user_for_layer.
layer = layer_index;
820 for (
const std::string &pass_name : pass_names) {
822 context(), image, &image_user_for_layer, pass_name.c_str());
823 layers.
append(pass_result);
833 if (render_layer->
name[0] ==
'\0') {
834 return std::string(render_pass->
name);
836 return std::string(render_layer->
name) +
"." + std::string(render_pass->
name);
847 return std::string(type_name);
896 const int2 image_size =
int2(image_buffer->
x, image_buffer->
y);
898 return Domain(image_size);
912 return image_user_for_frame;
949 "Generate matte for individual objects and materials using Cryptomatte render passes";
952 ntype.
declare = file_ns::cmp_node_cryptomatte_declare;
954 ntype.
initfunc = file_ns::node_init_cryptomatte;
955 ntype.
initfunc_api = file_ns::node_init_api_cryptomatte;
957 ntype.
updatefunc = file_ns::node_update_cryptomatte;
959 ntype,
"NodeCryptomatte", file_ns::node_free_cryptomatte, file_ns::node_copy_cryptomatte);
1002 file_ns::node_init_cryptomatte(ntree, node);
1017 using BaseCryptoMatteOperation::BaseCryptoMatteOperation;
1028 for (
const bNodeSocket *input_socket :
bnode().input_sockets().drop_front(1)) {
1034 if (
input.is_single_value()) {
1060 ntype.
ui_name =
"Cryptomatte (Legacy)";
1061 ntype.
ui_description =
"Deprecated. Use Cryptomatte Node instead";
1065 ntype.
initfunc = legacy_file_ns::node_init_cryptomatte_legacy;
1067 ntype,
"NodeCryptomatte", file_ns::node_free_cryptomatte, file_ns::node_copy_cryptomatte);
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)
#define NODE_STORAGE_FUNCS(StorageT)
#define CMP_NODE_CRYPTOMATTE
#define CMP_NODE_CRYPTOMATTE_LEGACY
#define BLI_assert_unreachable()
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE void BLI_listbase_clear(ListBase *lb)
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
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
@ CMP_NODE_CRYPTOMATTE_SOURCE_IMAGE
@ CMP_NODE_CRYPTOMATTE_SOURCE_RENDER
#define RE_PASSNAME_CRYPTOMATTE_MATERIAL
#define RE_PASSNAME_CRYPTOMATTE_ASSET
#define RE_PASSNAME_CRYPTOMATTE_OBJECT
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_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)
Read Guarded memory(de)allocation.
#define NOD_REGISTER_NODE(REGISTER_FUNC)
void append(const T &value)
void append(const T &value)
Result get(Context &context, Image *image, const ImageUser *image_user, const char *pass_name)
StaticCacheManager & cache_manager()
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)
const bNode & bnode() const
NodeOperation(Context &context, DNode node)
Result & get_result(StringRef identifier)
Context & context() const
Result & get_input(StringRef identifier) const
virtual Domain compute_domain()
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)
void unbind_as_texture() const
bool is_allocated() const
void bind_as_texture(gpu::Shader *shader, const char *texture_name) const
void set_precision(ResultPrecision precision)
T load_pixel(const int2 &texel) const
void unbind_as_image() const
void bind_as_image(gpu::Shader *shader, const char *image_name, bool read=false) const
void steal_data(Result &source)
CachedImageContainer cached_images
void compute_pick_gpu(const Vector< Result > &layers)
Vector< float > get_identifiers()
void compute_pick_cpu(const Vector< Result > &layers)
virtual int2 get_layers_lower_bound()
Result compute_matte_gpu(const Vector< Result > &layers)
void compute_image_gpu(const Result &matte)
Result compute_matte(const Vector< Result > &layers)
virtual Vector< Result > get_layers()=0
virtual Result & get_input_image()=0
void compute_image(const Result &matte)
void compute_image_cpu(const Result &matte)
void compute_pick(const Vector< Result > &layers)
Result compute_matte_cpu(const Vector< Result > &layers)
NodeOperation(Context &context, DNode node)
std::string get_combined_layer_pass_name(RenderLayer *render_layer, RenderPass *render_pass)
Vector< Result > get_layers_from_image()
Result & get_input_image() override
int2 get_layers_lower_bound() override
std::string get_type_name()
ImageUser get_image_user()
Domain compute_domain() override
CMPNodeCryptomatteSource get_source()
Domain compute_image_domain()
Vector< Result > get_layers_from_render()
Vector< Result > get_layers() override
Result & get_input_image() override
Vector< Result > get_layers() override
void * MEM_callocN(size_t len, const char *str)
void * MEM_dupallocN(const void *vmemh)
void MEM_freeN(void *vmemh)
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)
void node_type_size(bNodeType &ntype, int width, int minwidth, int maxwidth)
void node_register_type(bNodeType &ntype)
void node_type_socket_templates(bNodeType *ntype, bNodeSocketTemplate *inputs, bNodeSocketTemplate *outputs)
bNodeSocket * node_add_static_socket(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out, int type, int subtype, StringRefNull identifier, StringRefNull name)
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))
void compute_dispatch_threads_at_least(gpu::Shader *shader, int2 threads_range, int2 local_size=int2(16))
void parallel_for(const int2 range, const Function &function)
bool is_socket_available(const bNodeSocket *socket)
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 ¶meters)
static void node_free_cryptomatte(bNode *node)
static void cmp_node_cryptomatte_declare(NodeDeclarationBuilder &b)
static void node_init_cryptomatte(bNodeTree *, bNode *node)
static bke::bNodeSocketTemplate cmp_node_cryptomatte_out[]
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
NodeCryptomatte_Runtime runtime
std::string ui_description
NodeGetCompositorOperationFunction get_compositor_operation
void(* initfunc)(bNodeTree *ntree, bNode *node)
NodeExtraInfoFunction get_extra_info
const char * enum_name_legacy
NodeGatherSocketLinkOperationsFunction gather_link_search_ops
NodeDeclareFunction declare
void(* updatefunc)(bNodeTree *ntree, bNode *node)
void(* initfunc_api)(const bContext *C, PointerRNA *ptr)