12#include <fmt/format.h>
57 const bNode &node,
const bool build_meta_data)
99 const bNode &node,
const bool build_meta_data)
121 if (entry->encoded_hash == encoded_hash) {
189 layer_name.copy_utf8_truncated(layer->
name);
201 std::string first_layer_name;
207 if (first_layer_name.empty()) {
208 first_layer_name = layer_name;
211 if (layer_name == node_cryptomatte->
layer_name) {
218 const char *cstr = first_layer_name.c_str();
226 return session_ptr.release();
314 if (this->
context().use_gpu()) {
331 const Result &first_layer = layers[0];
350 const Result &first_layer = layers[0];
378 float2 first_rank = first_layer.load_pixel<float4>(texel + lower_bound).xy();
379 float id_of_first_rank = first_rank.x;
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);
388 output.store_pixel(texel, float4(id_of_first_rank, green, blue, 1.0f));
396 if (this->
context().use_gpu()) {
427 for (
const Result &layer : layers) {
428 layer.bind_as_texture(shader,
"layer_tx");
435 layer.unbind_as_texture();
460 for (
const Result &layer_result : layers) {
471 float4 layer = layer_result.load_pixel<float4>(texel + lower_bound);
474 float2 first_rank = layer.xy();
475 float2 second_rank = layer.zw();
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;
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;
491 if (identifier_of_second_rank == identifier) {
492 total_coverage += coverage_of_second_rank;
507 if (this->
context().use_gpu()) {
517 GPUShader *shader =
context().get_shader(
"compositor_cryptomatte_image");
544 output.allocate_texture(domain);
547 float4 input_color = input.load_pixel<float4, true>(texel);
548 float input_matte = matte.load_pixel<float>(texel);
551 output.store_pixel(texel, input_color * input_matte);
562 identifiers.
append(cryptomatte_entry->encoded_hash);
584 .default_value({0.0f, 0.0f, 0.0f, 1.0f})
585 .compositor_domain_priority(0);
602 node->
id = &scene->
id;
621 const bNode *src_node)
634 const char **r_disabled_hint)
640 for (scene =
static_cast<Scene *
>(
G.main->scenes.first); scene;
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");
652 return scene !=
nullptr;
654 *r_disabled_hint =
RPT_(
"Not a compositor node tree");
669 using BaseCryptoMatteOperation::BaseCryptoMatteOperation;
702 int view_layer_index = 0;
706 const char *cryptomatte_type =
nullptr;
707 const std::string layer_prefix = std::string(view_layer->name) +
".";
719 if (!cryptomatte_type) {
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);
734 layers.
append(pass_result);
760 if (!image_buffer || !image->
rr) {
776 const bool is_unnamed_layer = render_layer->name[0] ==
'\0';
777 if (!is_unnamed_layer && !
StringRefNull(type_name).startswith(render_layer->name)) {
788 if (combined_name == type_name || !
StringRef(combined_name).startswith(type_name)) {
792 pass_names.
append(render_pass->name);
803 image_user_for_layer.
layer = layer_index;
804 for (
const std::string &pass_name : pass_names) {
806 context(), image, &image_user_for_layer, pass_name.c_str());
807 layers.
append(pass_result);
817 if (render_layer->
name[0] ==
'\0') {
818 return std::string(render_pass->
name);
820 return std::string(render_layer->
name) +
"." + std::string(render_pass->
name);
831 return std::string(type_name);
839 return int2(compositing_region.
xmin, compositing_region.
ymin);
881 const int2 image_size =
int2(image_buffer->
x, image_buffer->
y);
883 return Domain(image_size);
897 return image_user_for_frame;
934 "Generate matte for individual objects and materials using Cryptomatte render passes";
937 ntype.
declare = file_ns::cmp_node_cryptomatte_declare;
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);
987 file_ns::node_init_cryptomatte(ntree, node);
1002 using BaseCryptoMatteOperation::BaseCryptoMatteOperation;
1013 for (
const bNodeSocket *input_socket :
bnode().input_sockets().drop_front(1)) {
1019 if (
input.is_single_value()) {
1045 ntype.
ui_name =
"Cryptomatte (Legacy)";
1046 ntype.
ui_description =
"Deprecated. Use Cryptomatte Node instead";
1050 ntype.
initfunc = legacy_file_ns::node_init_cryptomatte_legacy;
1052 ntype,
"NodeCryptomatte", file_ns::node_free_cryptomatte, file_ns::node_copy_cryptomatte);
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(dst, format,...)
char * BLI_strncpy(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_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_texture_clear(GPUTexture *texture, eGPUDataFormat data_format, const void *data)
Read Guarded memory(de)allocation.
#define NOD_REGISTER_NODE(REGISTER_FUNC)
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)
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
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 allocate_texture(Domain domain, bool from_pool=true)
void store_pixel(const int2 &texel, const T &pixel_value)
void unbind_as_texture() const
void bind_as_texture(GPUShader *shader, const char *texture_name) const
bool is_allocated() const
void set_precision(ResultPrecision precision)
T load_pixel(const int2 &texel) const
void bind_as_image(GPUShader *shader, const char *image_name, bool read=false) const
void unbind_as_image() 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)
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(GPUShader *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_free_cryptomatte(bNode *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 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)
NodeCryptomatte_Runtime runtime
struct bNodeTree * nodetree
std::string ui_description
NodeGetCompositorOperationFunction get_compositor_operation
void(* initfunc)(bNodeTree *ntree, bNode *node)
const char * enum_name_legacy
bool(* poll)(const bNodeType *ntype, const bNodeTree *nodetree, const char **r_disabled_hint)
NodeGatherSocketLinkOperationsFunction gather_link_search_ops
NodeDeclareFunction declare
void(* updatefunc)(bNodeTree *ntree, bNode *node)
void(* initfunc_api)(const bContext *C, PointerRNA *ptr)