Changeset View
Changeset View
Standalone View
Standalone View
source/blender/nodes/composite/nodes/node_composite_cryptomatte.cc
| Show All 34 Lines | |||||
| #include "BKE_lib_id.h" | #include "BKE_lib_id.h" | ||||
| #include "BKE_library.h" | #include "BKE_library.h" | ||||
| #include "BKE_main.h" | #include "BKE_main.h" | ||||
| #include <optional> | #include <optional> | ||||
| /** \name Cryptomatte | /** \name Cryptomatte | ||||
| * \{ */ | * \{ */ | ||||
| static blender::bke::cryptomatte::CryptomatteSessionPtr cryptomatte_init_from_node_render( | |||||
| static blender::bke::cryptomatte::CryptomatteSessionPtr cryptomatte_init_from_node( | const bNode &node, const bool use_meta_data) | ||||
| const bNode &node, const int frame_number, const bool use_meta_data) | |||||
| { | { | ||||
| blender::bke::cryptomatte::CryptomatteSessionPtr session; | blender::bke::cryptomatte::CryptomatteSessionPtr session; | ||||
| if (node.type != CMP_NODE_CRYPTOMATTE) { | |||||
| return session; | |||||
| } | |||||
| NodeCryptomatte *node_cryptomatte = static_cast<NodeCryptomatte *>(node.storage); | |||||
| switch (node.custom1) { | |||||
| case CMP_CRYPTOMATTE_SRC_RENDER: { | |||||
| Scene *scene = (Scene *)node.id; | Scene *scene = (Scene *)node.id; | ||||
| if (!scene) { | if (!scene) { | ||||
| return session; | return session; | ||||
| } | } | ||||
| BLI_assert(GS(scene->id.name) == ID_SCE); | BLI_assert(GS(scene->id.name) == ID_SCE); | ||||
| if (use_meta_data) { | if (use_meta_data) { | ||||
| Render *render = (scene) ? RE_GetSceneRender(scene) : nullptr; | Render *render = (scene) ? RE_GetSceneRender(scene) : nullptr; | ||||
| RenderResult *render_result = render ? RE_AcquireResultRead(render) : nullptr; | RenderResult *render_result = render ? RE_AcquireResultRead(render) : nullptr; | ||||
| if (render_result) { | if (render_result) { | ||||
| session = blender::bke::cryptomatte::CryptomatteSessionPtr( | session = blender::bke::cryptomatte::CryptomatteSessionPtr( | ||||
| BKE_cryptomatte_init_from_render_result(render_result)); | BKE_cryptomatte_init_from_render_result(render_result)); | ||||
| } | } | ||||
| if (render) { | if (render) { | ||||
| RE_ReleaseResult(render); | RE_ReleaseResult(render); | ||||
| } | } | ||||
| } | } | ||||
| if (session == nullptr) { | if (session == nullptr) { | ||||
| session = blender::bke::cryptomatte::CryptomatteSessionPtr( | session = blender::bke::cryptomatte::CryptomatteSessionPtr( | ||||
| BKE_cryptomatte_init_from_scene(scene)); | BKE_cryptomatte_init_from_scene(scene)); | ||||
| } | } | ||||
| return session; | |||||
| break; | |||||
| } | } | ||||
| case CMP_CRYPTOMATTE_SRC_IMAGE: { | static blender::bke::cryptomatte::CryptomatteSessionPtr cryptomatte_init_from_node_image( | ||||
| const Scene &scene, const bNode &node) | |||||
| { | |||||
| blender::bke::cryptomatte::CryptomatteSessionPtr session; | |||||
| Image *image = (Image *)node.id; | Image *image = (Image *)node.id; | ||||
| if (!image) { | if (!image) { | ||||
| break; | return session; | ||||
| } | } | ||||
| BLI_assert(GS(image->id.name) == ID_IM); | BLI_assert(GS(image->id.name) == ID_IM); | ||||
| NodeCryptomatte *node_cryptomatte = static_cast<NodeCryptomatte *>(node.storage); | |||||
| ImageUser *iuser = &node_cryptomatte->iuser; | ImageUser *iuser = &node_cryptomatte->iuser; | ||||
| BKE_image_user_frame_calc(image, iuser, frame_number); | BKE_image_user_frame_calc(image, iuser, scene.r.cfra); | ||||
| ImBuf *ibuf = BKE_image_acquire_ibuf(image, iuser, nullptr); | ImBuf *ibuf = BKE_image_acquire_ibuf(image, iuser, nullptr); | ||||
| RenderResult *render_result = image->rr; | RenderResult *render_result = image->rr; | ||||
| if (render_result) { | if (render_result) { | ||||
| session = blender::bke::cryptomatte::CryptomatteSessionPtr( | session = blender::bke::cryptomatte::CryptomatteSessionPtr( | ||||
| BKE_cryptomatte_init_from_render_result(render_result)); | BKE_cryptomatte_init_from_render_result(render_result)); | ||||
| } | } | ||||
| BKE_image_release_ibuf(image, ibuf, nullptr); | BKE_image_release_ibuf(image, ibuf, nullptr); | ||||
| break; | return session; | ||||
| } | |||||
| static blender::bke::cryptomatte::CryptomatteSessionPtr cryptomatte_init_from_node( | |||||
| const Scene &scene, const bNode &node, const bool use_meta_data) | |||||
| { | |||||
| blender::bke::cryptomatte::CryptomatteSessionPtr session; | |||||
| if (node.type != CMP_NODE_CRYPTOMATTE) { | |||||
| return session; | |||||
| } | |||||
| switch (node.custom1) { | |||||
| case CMP_CRYPTOMATTE_SRC_RENDER: { | |||||
| return cryptomatte_init_from_node_render(node, use_meta_data); | |||||
| } | |||||
| case CMP_CRYPTOMATTE_SRC_IMAGE: { | |||||
| return cryptomatte_init_from_node_image(scene, node); | |||||
| } | } | ||||
| } | } | ||||
| return session; | return session; | ||||
| } | } | ||||
| extern "C" { | extern "C" { | ||||
| static CryptomatteEntry *cryptomatte_find(const NodeCryptomatte &n, float encoded_hash) | static CryptomatteEntry *cryptomatte_find(const NodeCryptomatte &n, float encoded_hash) | ||||
| { | { | ||||
| LISTBASE_FOREACH (CryptomatteEntry *, entry, &n.entries) { | LISTBASE_FOREACH (CryptomatteEntry *, entry, &n.entries) { | ||||
| if (entry->encoded_hash == encoded_hash) { | if (entry->encoded_hash == encoded_hash) { | ||||
| return entry; | return entry; | ||||
| } | } | ||||
| } | } | ||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| static void cryptomatte_add(bNode &node, NodeCryptomatte &node_cryptomatte, float encoded_hash) | static void cryptomatte_add(const Scene &scene, | ||||
| bNode &node, | |||||
| NodeCryptomatte &node_cryptomatte, | |||||
| float encoded_hash) | |||||
| { | { | ||||
| /* Check if entry already exist. */ | /* Check if entry already exist. */ | ||||
| if (cryptomatte_find(node_cryptomatte, encoded_hash)) { | if (cryptomatte_find(node_cryptomatte, encoded_hash)) { | ||||
| return; | return; | ||||
| } | } | ||||
| CryptomatteEntry *entry = static_cast<CryptomatteEntry *>( | CryptomatteEntry *entry = static_cast<CryptomatteEntry *>( | ||||
| MEM_callocN(sizeof(CryptomatteEntry), __func__)); | MEM_callocN(sizeof(CryptomatteEntry), __func__)); | ||||
| entry->encoded_hash = encoded_hash; | entry->encoded_hash = encoded_hash; | ||||
| /* TODO(jbakker): Get current frame from scene. */ | |||||
| blender::bke::cryptomatte::CryptomatteSessionPtr session = cryptomatte_init_from_node( | blender::bke::cryptomatte::CryptomatteSessionPtr session = cryptomatte_init_from_node( | ||||
| node, 0, true); | scene, node, true); | ||||
| if (session) { | if (session) { | ||||
| BKE_cryptomatte_find_name(session.get(), encoded_hash, entry->name, sizeof(entry->name)); | BKE_cryptomatte_find_name(session.get(), encoded_hash, entry->name, sizeof(entry->name)); | ||||
| } | } | ||||
| BLI_addtail(&node_cryptomatte.entries, entry); | BLI_addtail(&node_cryptomatte.entries, entry); | ||||
| } | } | ||||
| static void cryptomatte_remove(NodeCryptomatte &n, float encoded_hash) | static void cryptomatte_remove(NodeCryptomatte &n, float encoded_hash) | ||||
| Show All 11 Lines | |||||
| static bNodeSocketTemplate cmp_node_cryptomatte_out[] = { | static bNodeSocketTemplate cmp_node_cryptomatte_out[] = { | ||||
| {SOCK_RGBA, N_("Image")}, | {SOCK_RGBA, N_("Image")}, | ||||
| {SOCK_FLOAT, N_("Matte")}, | {SOCK_FLOAT, N_("Matte")}, | ||||
| {SOCK_RGBA, N_("Pick")}, | {SOCK_RGBA, N_("Pick")}, | ||||
| {-1, ""}, | {-1, ""}, | ||||
| }; | }; | ||||
| void ntreeCompositCryptomatteSyncFromAdd(bNode *node) | void ntreeCompositCryptomatteSyncFromAdd(const Scene *scene, bNode *node) | ||||
| { | { | ||||
| BLI_assert(ELEM(node->type, CMP_NODE_CRYPTOMATTE, CMP_NODE_CRYPTOMATTE_LEGACY)); | BLI_assert(ELEM(node->type, CMP_NODE_CRYPTOMATTE, CMP_NODE_CRYPTOMATTE_LEGACY)); | ||||
| NodeCryptomatte *n = static_cast<NodeCryptomatte *>(node->storage); | NodeCryptomatte *n = static_cast<NodeCryptomatte *>(node->storage); | ||||
| if (n->runtime.add[0] != 0.0f) { | if (n->runtime.add[0] != 0.0f) { | ||||
| cryptomatte_add(*node, *n, n->runtime.add[0]); | cryptomatte_add(*scene, *node, *n, n->runtime.add[0]); | ||||
| zero_v3(n->runtime.add); | zero_v3(n->runtime.add); | ||||
| } | } | ||||
| } | } | ||||
| void ntreeCompositCryptomatteSyncFromRemove(bNode *node) | void ntreeCompositCryptomatteSyncFromRemove(bNode *node) | ||||
| { | { | ||||
| BLI_assert(ELEM(node->type, CMP_NODE_CRYPTOMATTE, CMP_NODE_CRYPTOMATTE_LEGACY)); | BLI_assert(ELEM(node->type, CMP_NODE_CRYPTOMATTE, CMP_NODE_CRYPTOMATTE_LEGACY)); | ||||
| NodeCryptomatte *n = static_cast<NodeCryptomatte *>(node->storage); | NodeCryptomatte *n = static_cast<NodeCryptomatte *>(node->storage); | ||||
| if (n->runtime.remove[0] != 0.0f) { | if (n->runtime.remove[0] != 0.0f) { | ||||
| cryptomatte_remove(*n, n->runtime.remove[0]); | cryptomatte_remove(*n, n->runtime.remove[0]); | ||||
| zero_v3(n->runtime.remove); | zero_v3(n->runtime.remove); | ||||
| } | } | ||||
| } | } | ||||
| void ntreeCompositCryptomatteUpdateLayerNames(bNode *node) | void ntreeCompositCryptomatteUpdateLayerNames(const Scene *scene, bNode *node) | ||||
| { | { | ||||
| BLI_assert(node->type == CMP_NODE_CRYPTOMATTE); | BLI_assert(node->type == CMP_NODE_CRYPTOMATTE); | ||||
| NodeCryptomatte *n = static_cast<NodeCryptomatte *>(node->storage); | NodeCryptomatte *n = static_cast<NodeCryptomatte *>(node->storage); | ||||
| BLI_freelistN(&n->runtime.layers); | BLI_freelistN(&n->runtime.layers); | ||||
| blender::bke::cryptomatte::CryptomatteSessionPtr session = cryptomatte_init_from_node( | blender::bke::cryptomatte::CryptomatteSessionPtr session = cryptomatte_init_from_node( | ||||
| *node, 0, false); | *scene, *node, false); | ||||
| if (session) { | if (session) { | ||||
| for (blender::StringRef layer_name : | for (blender::StringRef layer_name : | ||||
| blender::bke::cryptomatte::BKE_cryptomatte_layer_names_get(*session)) { | blender::bke::cryptomatte::BKE_cryptomatte_layer_names_get(*session)) { | ||||
| CryptomatteLayer *layer = static_cast<CryptomatteLayer *>( | CryptomatteLayer *layer = static_cast<CryptomatteLayer *>( | ||||
| MEM_callocN(sizeof(CryptomatteLayer), __func__)); | MEM_callocN(sizeof(CryptomatteLayer), __func__)); | ||||
| layer_name.copy(layer->name); | layer_name.copy(layer->name); | ||||
| BLI_addtail(&n->runtime.layers, layer); | BLI_addtail(&n->runtime.layers, layer); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| void ntreeCompositCryptomatteLayerPrefix(const bNode *node, char *r_prefix, size_t prefix_len) | void ntreeCompositCryptomatteLayerPrefix(const Scene *scene, | ||||
| const bNode *node, | |||||
| char *r_prefix, | |||||
| size_t prefix_len) | |||||
| { | { | ||||
| BLI_assert(node->type == CMP_NODE_CRYPTOMATTE); | BLI_assert(node->type == CMP_NODE_CRYPTOMATTE); | ||||
| NodeCryptomatte *node_cryptomatte = (NodeCryptomatte *)node->storage; | NodeCryptomatte *node_cryptomatte = (NodeCryptomatte *)node->storage; | ||||
| blender::bke::cryptomatte::CryptomatteSessionPtr session = cryptomatte_init_from_node( | blender::bke::cryptomatte::CryptomatteSessionPtr session = cryptomatte_init_from_node( | ||||
| *node, 0, false); | *scene, *node, false); | ||||
| std::string first_layer_name; | std::string first_layer_name; | ||||
| if (session) { | if (session) { | ||||
| for (blender::StringRef layer_name : | for (blender::StringRef layer_name : | ||||
| blender::bke::cryptomatte::BKE_cryptomatte_layer_names_get(*session)) { | blender::bke::cryptomatte::BKE_cryptomatte_layer_names_get(*session)) { | ||||
| if (first_layer_name.empty()) { | if (first_layer_name.empty()) { | ||||
| first_layer_name = layer_name; | first_layer_name = layer_name; | ||||
| } | } | ||||
| if (layer_name == node_cryptomatte->layer_name) { | if (layer_name == node_cryptomatte->layer_name) { | ||||
| BLI_strncpy(r_prefix, node_cryptomatte->layer_name, prefix_len); | BLI_strncpy(r_prefix, node_cryptomatte->layer_name, prefix_len); | ||||
| return; | return; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| const char *cstr = first_layer_name.c_str(); | const char *cstr = first_layer_name.c_str(); | ||||
| BLI_strncpy(r_prefix, cstr, prefix_len); | BLI_strncpy(r_prefix, cstr, prefix_len); | ||||
| } | } | ||||
| CryptomatteSession *ntreeCompositCryptomatteSession(bNode *node) | CryptomatteSession *ntreeCompositCryptomatteSession(const Scene *scene, bNode *node) | ||||
| { | { | ||||
| blender::bke::cryptomatte::CryptomatteSessionPtr session_ptr = cryptomatte_init_from_node( | blender::bke::cryptomatte::CryptomatteSessionPtr session_ptr = cryptomatte_init_from_node( | ||||
| *node, 0, true); | *scene, *node, true); | ||||
| return session_ptr.release(); | return session_ptr.release(); | ||||
| } | } | ||||
| static void node_init_cryptomatte(bNodeTree *UNUSED(ntree), bNode *node) | static void node_init_cryptomatte(bNodeTree *UNUSED(ntree), bNode *node) | ||||
| { | { | ||||
| NodeCryptomatte *user = static_cast<NodeCryptomatte *>( | NodeCryptomatte *user = static_cast<NodeCryptomatte *>( | ||||
| MEM_callocN(sizeof(NodeCryptomatte), __func__)); | MEM_callocN(sizeof(NodeCryptomatte), __func__)); | ||||
| node->storage = user; | node->storage = user; | ||||
| ▲ Show 20 Lines • Show All 128 Lines • Show Last 20 Lines | |||||