Fix T88666: Cryptomatte: EXR sequence does not update when scrubbing the timeline.

Cause is that initializing the cryptomatte session would reset the
current frame of an image sequence. The solution is to always use the
scene current frame so it resets to the correct frame.

This was a todo that wasn't solved after it landed in master.
Needs to be backported to 2.93.
This commit is contained in:
Jeroen Bakker 2021-05-31 14:32:39 +02:00
parent e9f2f17e85
commit e0a1c3da46
Notes: blender-bot 2023-02-14 06:46:23 +01:00
Referenced by issue #88449, Blender LTS: Maintenance Task 2.93
Referenced by issue #88666, Cryptomatte: EXR sequence does not update when scrubbing the timeline
5 changed files with 143 additions and 104 deletions

View File

@ -1305,15 +1305,18 @@ void ntreeCompositOutputFileUniqueLayer(struct ListBase *list,
void ntreeCompositColorBalanceSyncFromLGG(bNodeTree *ntree, bNode *node);
void ntreeCompositColorBalanceSyncFromCDL(bNodeTree *ntree, bNode *node);
void ntreeCompositCryptomatteSyncFromAdd(bNode *node);
void ntreeCompositCryptomatteSyncFromAdd(const Scene *scene, bNode *node);
void ntreeCompositCryptomatteSyncFromRemove(bNode *node);
bNodeSocket *ntreeCompositCryptomatteAddSocket(bNodeTree *ntree, bNode *node);
int ntreeCompositCryptomatteRemoveSocket(bNodeTree *ntree, bNode *node);
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);
/* Update the runtime layer names with the cryptomatte layer names of the references
* render layer or image. */
void ntreeCompositCryptomatteUpdateLayerNames(bNode *node);
struct CryptomatteSession *ntreeCompositCryptomatteSession(bNode *node);
void ntreeCompositCryptomatteUpdateLayerNames(const Scene *scene, bNode *node);
struct CryptomatteSession *ntreeCompositCryptomatteSession(const Scene *scene, bNode *node);
/** \} */

View File

@ -77,10 +77,10 @@ void CryptomatteBaseNode::convertToOperations(NodeConverter &converter,
/** \name Cryptomatte V2
* \{ */
static std::string prefix_from_node(const bNode &node)
static std::string prefix_from_node(const CompositorContext &context, const bNode &node)
{
char prefix[MAX_NAME];
ntreeCompositCryptomatteLayerPrefix(&node, prefix, sizeof(prefix));
ntreeCompositCryptomatteLayerPrefix(context.getScene(), &node, prefix, sizeof(prefix));
return std::string(prefix, BLI_strnlen(prefix, sizeof(prefix)));
}
@ -119,7 +119,7 @@ void CryptomatteNode::input_operations_from_render_source(
}
const short cryptomatte_layer_id = 0;
const std::string prefix = prefix_from_node(node);
const std::string prefix = prefix_from_node(context, node);
LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
RenderLayer *render_layer = RE_GetRenderLayer(render_result, view_layer->name);
if (render_layer) {
@ -177,7 +177,7 @@ void CryptomatteNode::input_operations_from_image_source(
}
}
const std::string prefix = prefix_from_node(node);
const std::string prefix = prefix_from_node(context, node);
int layer_index;
LISTBASE_FOREACH_INDEX (RenderLayer *, render_layer, &image->rr->layers, layer_index) {
if (!blender::StringRef(prefix).startswith(blender::StringRef(

View File

@ -118,7 +118,8 @@ static bool eyedropper_init(bContext *C, wmOperator *op)
RNA_property_float_get_array(&eye->ptr, eye->prop, col);
if (eye->ptr.type == &RNA_CompositorNodeCryptomatteV2) {
eye->crypto_node = (bNode *)eye->ptr.data;
eye->cryptomatte_session = ntreeCompositCryptomatteSession(eye->crypto_node);
eye->cryptomatte_session = ntreeCompositCryptomatteSession(CTX_data_scene(C),
eye->crypto_node);
eye->draw_handle_sample_text = WM_draw_cb_activate(CTX_wm_window(C), eyedropper_draw_cb, eye);
}
@ -199,6 +200,57 @@ static bool eyedropper_cryptomatte_sample_renderlayer_fl(RenderLayer *render_lay
return false;
}
static bool eyedropper_cryptomatte_sample_render_fl(const bNode *node,
const char *prefix,
const float fpos[2],
float r_col[3])
{
bool success = false;
Scene *scene = (Scene *)node->id;
BLI_assert(GS(scene->id.name) == ID_SCE);
Render *re = RE_GetSceneRender(scene);
if (re) {
RenderResult *rr = RE_AcquireResultRead(re);
if (rr) {
LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
RenderLayer *render_layer = RE_GetRenderLayer(rr, view_layer->name);
success = eyedropper_cryptomatte_sample_renderlayer_fl(render_layer, prefix, fpos, r_col);
if (success) {
break;
}
}
}
RE_ReleaseResult(re);
}
return success;
}
static bool eyedropper_cryptomatte_sample_image_fl(const bNode *node,
NodeCryptomatte *crypto,
const char *prefix,
const float fpos[2],
float r_col[3])
{
bool success = false;
Image *image = (Image *)node->id;
BLI_assert(GS(image->id.name) == ID_IM);
ImageUser *iuser = &crypto->iuser;
if (image && image->type == IMA_TYPE_MULTILAYER) {
ImBuf *ibuf = BKE_image_acquire_ibuf(image, iuser, NULL);
if (image->rr) {
LISTBASE_FOREACH (RenderLayer *, render_layer, &image->rr->layers) {
success = eyedropper_cryptomatte_sample_renderlayer_fl(render_layer, prefix, fpos, r_col);
if (success) {
break;
}
}
}
BKE_image_release_ibuf(image, ibuf, NULL);
}
return success;
}
static bool eyedropper_cryptomatte_sample_fl(
bContext *C, Eyedropper *eye, int mx, int my, float r_col[3])
@ -255,53 +307,19 @@ static bool eyedropper_cryptomatte_sample_fl(
return false;
}
bool success = false;
/* TODO(jbakker): Migrate this file to cc and use std::string as return param. */
char prefix[MAX_NAME + 1];
ntreeCompositCryptomatteLayerPrefix(node, prefix, sizeof(prefix) - 1);
const Scene *scene = CTX_data_scene(C);
ntreeCompositCryptomatteLayerPrefix(scene, node, prefix, sizeof(prefix) - 1);
prefix[MAX_NAME] = '\0';
if (node->custom1 == CMP_CRYPTOMATTE_SRC_RENDER) {
Scene *scene = (Scene *)node->id;
BLI_assert(GS(scene->id.name) == ID_SCE);
Render *re = RE_GetSceneRender(scene);
if (re) {
RenderResult *rr = RE_AcquireResultRead(re);
if (rr) {
LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
RenderLayer *render_layer = RE_GetRenderLayer(rr, view_layer->name);
success = eyedropper_cryptomatte_sample_renderlayer_fl(
render_layer, prefix, fpos, r_col);
if (success) {
break;
}
}
}
RE_ReleaseResult(re);
}
return eyedropper_cryptomatte_sample_render_fl(node, prefix, fpos, r_col);
}
else if (node->custom1 == CMP_CRYPTOMATTE_SRC_IMAGE) {
Image *image = (Image *)node->id;
BLI_assert(GS(image->id.name) == ID_IM);
ImageUser *iuser = &crypto->iuser;
if (image && image->type == IMA_TYPE_MULTILAYER) {
ImBuf *ibuf = BKE_image_acquire_ibuf(image, iuser, NULL);
if (image->rr) {
LISTBASE_FOREACH (RenderLayer *, render_layer, &image->rr->layers) {
success = eyedropper_cryptomatte_sample_renderlayer_fl(
render_layer, prefix, fpos, r_col);
if (success) {
break;
}
}
}
BKE_image_release_ibuf(image, ibuf, NULL);
}
return eyedropper_cryptomatte_sample_image_fl(node, crypto, prefix, fpos, r_col);
}
return success;
return false;
}
/**

View File

@ -3973,7 +3973,7 @@ static void rna_NodeCryptomatte_layer_name_set(PointerRNA *ptr, int new_value)
}
}
static const EnumPropertyItem *rna_NodeCryptomatte_layer_name_itemf(bContext *UNUSED(C),
static const EnumPropertyItem *rna_NodeCryptomatte_layer_name_itemf(bContext *C,
PointerRNA *ptr,
PropertyRNA *UNUSED(prop),
bool *r_free)
@ -3984,7 +3984,7 @@ static const EnumPropertyItem *rna_NodeCryptomatte_layer_name_itemf(bContext *UN
EnumPropertyItem template = {0, "", 0, "", ""};
int totitem = 0;
ntreeCompositCryptomatteUpdateLayerNames(node);
ntreeCompositCryptomatteUpdateLayerNames(CTX_data_scene(C), node);
int layer_index;
LISTBASE_FOREACH_INDEX (CryptomatteLayer *, layer, &storage->runtime.layers, layer_index) {
template.value = layer_index;
@ -4076,7 +4076,7 @@ static void rna_NodeCryptomatte_matte_set(PointerRNA *ptr, const char *value)
static void rna_NodeCryptomatte_update_add(Main *bmain, Scene *scene, PointerRNA *ptr)
{
ntreeCompositCryptomatteSyncFromAdd(ptr->data);
ntreeCompositCryptomatteSyncFromAdd(scene, ptr->data);
rna_Node_update(bmain, scene, ptr);
}

View File

@ -40,61 +40,74 @@
/** \name Cryptomatte
* \{ */
static blender::bke::cryptomatte::CryptomatteSessionPtr cryptomatte_init_from_node_render(
const bNode &node, const bool use_meta_data)
{
blender::bke::cryptomatte::CryptomatteSessionPtr session;
Scene *scene = (Scene *)node.id;
if (!scene) {
return session;
}
BLI_assert(GS(scene->id.name) == ID_SCE);
if (use_meta_data) {
Render *render = (scene) ? RE_GetSceneRender(scene) : nullptr;
RenderResult *render_result = render ? RE_AcquireResultRead(render) : nullptr;
if (render_result) {
session = blender::bke::cryptomatte::CryptomatteSessionPtr(
BKE_cryptomatte_init_from_render_result(render_result));
}
if (render) {
RE_ReleaseResult(render);
}
}
if (session == nullptr) {
session = blender::bke::cryptomatte::CryptomatteSessionPtr(
BKE_cryptomatte_init_from_scene(scene));
}
return session;
}
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;
if (!image) {
return session;
}
BLI_assert(GS(image->id.name) == ID_IM);
NodeCryptomatte *node_cryptomatte = static_cast<NodeCryptomatte *>(node.storage);
ImageUser *iuser = &node_cryptomatte->iuser;
BKE_image_user_frame_calc(image, iuser, scene.r.cfra);
ImBuf *ibuf = BKE_image_acquire_ibuf(image, iuser, nullptr);
RenderResult *render_result = image->rr;
if (render_result) {
session = blender::bke::cryptomatte::CryptomatteSessionPtr(
BKE_cryptomatte_init_from_render_result(render_result));
}
BKE_image_release_ibuf(image, ibuf, nullptr);
return session;
}
static blender::bke::cryptomatte::CryptomatteSessionPtr cryptomatte_init_from_node(
const bNode &node, const int frame_number, const bool use_meta_data)
const Scene &scene, const bNode &node, const bool use_meta_data)
{
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;
if (!scene) {
return session;
}
BLI_assert(GS(scene->id.name) == ID_SCE);
if (use_meta_data) {
Render *render = (scene) ? RE_GetSceneRender(scene) : nullptr;
RenderResult *render_result = render ? RE_AcquireResultRead(render) : nullptr;
if (render_result) {
session = blender::bke::cryptomatte::CryptomatteSessionPtr(
BKE_cryptomatte_init_from_render_result(render_result));
}
if (render) {
RE_ReleaseResult(render);
}
}
if (session == nullptr) {
session = blender::bke::cryptomatte::CryptomatteSessionPtr(
BKE_cryptomatte_init_from_scene(scene));
}
break;
return cryptomatte_init_from_node_render(node, use_meta_data);
}
case CMP_CRYPTOMATTE_SRC_IMAGE: {
Image *image = (Image *)node.id;
if (!image) {
break;
}
BLI_assert(GS(image->id.name) == ID_IM);
ImageUser *iuser = &node_cryptomatte->iuser;
BKE_image_user_frame_calc(image, iuser, frame_number);
ImBuf *ibuf = BKE_image_acquire_ibuf(image, iuser, nullptr);
RenderResult *render_result = image->rr;
if (render_result) {
session = blender::bke::cryptomatte::CryptomatteSessionPtr(
BKE_cryptomatte_init_from_render_result(render_result));
}
BKE_image_release_ibuf(image, ibuf, nullptr);
break;
return cryptomatte_init_from_node_image(scene, node);
}
}
return session;
@ -111,7 +124,10 @@ static CryptomatteEntry *cryptomatte_find(const NodeCryptomatte &n, float encode
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. */
if (cryptomatte_find(node_cryptomatte, encoded_hash)) {
@ -121,9 +137,8 @@ static void cryptomatte_add(bNode &node, NodeCryptomatte &node_cryptomatte, floa
CryptomatteEntry *entry = static_cast<CryptomatteEntry *>(
MEM_callocN(sizeof(CryptomatteEntry), __func__));
entry->encoded_hash = encoded_hash;
/* TODO(jbakker): Get current frame from scene. */
blender::bke::cryptomatte::CryptomatteSessionPtr session = cryptomatte_init_from_node(
node, 0, true);
scene, node, true);
if (session) {
BKE_cryptomatte_find_name(session.get(), encoded_hash, entry->name, sizeof(entry->name));
}
@ -151,12 +166,12 @@ static bNodeSocketTemplate cmp_node_cryptomatte_out[] = {
{-1, ""},
};
void ntreeCompositCryptomatteSyncFromAdd(bNode *node)
void ntreeCompositCryptomatteSyncFromAdd(const Scene *scene, bNode *node)
{
BLI_assert(ELEM(node->type, CMP_NODE_CRYPTOMATTE, CMP_NODE_CRYPTOMATTE_LEGACY));
NodeCryptomatte *n = static_cast<NodeCryptomatte *>(node->storage);
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);
}
}
@ -170,14 +185,14 @@ void ntreeCompositCryptomatteSyncFromRemove(bNode *node)
zero_v3(n->runtime.remove);
}
}
void ntreeCompositCryptomatteUpdateLayerNames(bNode *node)
void ntreeCompositCryptomatteUpdateLayerNames(const Scene *scene, bNode *node)
{
BLI_assert(node->type == CMP_NODE_CRYPTOMATTE);
NodeCryptomatte *n = static_cast<NodeCryptomatte *>(node->storage);
BLI_freelistN(&n->runtime.layers);
blender::bke::cryptomatte::CryptomatteSessionPtr session = cryptomatte_init_from_node(
*node, 0, false);
*scene, *node, false);
if (session) {
for (blender::StringRef layer_name :
@ -190,12 +205,15 @@ void ntreeCompositCryptomatteUpdateLayerNames(bNode *node)
}
}
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);
NodeCryptomatte *node_cryptomatte = (NodeCryptomatte *)node->storage;
blender::bke::cryptomatte::CryptomatteSessionPtr session = cryptomatte_init_from_node(
*node, 0, false);
*scene, *node, false);
std::string first_layer_name;
if (session) {
@ -216,10 +234,10 @@ void ntreeCompositCryptomatteLayerPrefix(const bNode *node, char *r_prefix, size
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(
*node, 0, true);
*scene, *node, true);
return session_ptr.release();
}