Cryptomatte: Read metadata from multilayer OpenEXR.
Currently the compositor reads cryptomatte meta-data from the render result. When loading a multilayer open exr file the meta-data was ignored. This patch will also load the cryptomatte meta-data from multilayer open exr files. This enabled workflows where the rendering and compositing are done in separate scenes or for future changes where the cryptomatte node will use the meta-data for name matching and color picking. Reviewed By: Sergey Sharybin Differential Revision: https://developer.blender.org/D10384
This commit is contained in:
parent
8dec6452f2
commit
2d4b638a67
|
@ -18,7 +18,6 @@
|
|||
|
||||
#include "COM_MetaData.h"
|
||||
|
||||
#include "BKE_cryptomatte.hh"
|
||||
#include "BKE_image.h"
|
||||
|
||||
#include "RE_pipeline.h"
|
||||
|
@ -69,3 +68,39 @@ void MetaData::addToRenderResult(RenderResult *render_result) const
|
|||
BKE_render_result_stamp_data(render_result, entry.key.c_str(), entry.value.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void MetaDataExtractCallbackData::addMetaData(blender::StringRef key, blender::StringRefNull value)
|
||||
{
|
||||
if (!meta_data) {
|
||||
meta_data = std::make_unique<MetaData>();
|
||||
}
|
||||
meta_data->add(key, value);
|
||||
}
|
||||
|
||||
void MetaDataExtractCallbackData::setCryptomatteKeys(blender::StringRef cryptomatte_layer_name)
|
||||
{
|
||||
manifest_key = blender::bke::cryptomatte::BKE_cryptomatte_meta_data_key(cryptomatte_layer_name,
|
||||
"manifest");
|
||||
hash_key = blender::bke::cryptomatte::BKE_cryptomatte_meta_data_key(cryptomatte_layer_name,
|
||||
"hash");
|
||||
conversion_key = blender::bke::cryptomatte::BKE_cryptomatte_meta_data_key(cryptomatte_layer_name,
|
||||
"conversion");
|
||||
}
|
||||
|
||||
void MetaDataExtractCallbackData::extract_cryptomatte_meta_data(void *_data,
|
||||
const char *propname,
|
||||
char *propvalue,
|
||||
int UNUSED(len))
|
||||
{
|
||||
MetaDataExtractCallbackData *data = static_cast<MetaDataExtractCallbackData *>(_data);
|
||||
blender::StringRefNull key(propname);
|
||||
if (key == data->hash_key) {
|
||||
data->addMetaData(META_DATA_KEY_CRYPTOMATTE_HASH, propvalue);
|
||||
}
|
||||
else if (key == data->conversion_key) {
|
||||
data->addMetaData(META_DATA_KEY_CRYPTOMATTE_CONVERSION, propvalue);
|
||||
}
|
||||
else if (key == data->manifest_key) {
|
||||
data->addMetaData(META_DATA_KEY_CRYPTOMATTE_MANIFEST, propvalue);
|
||||
}
|
||||
}
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#include "BKE_cryptomatte.hh"
|
||||
#include "BLI_map.hh"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
@ -54,3 +55,18 @@ class MetaData {
|
|||
MEM_CXX_CLASS_ALLOC_FUNCS("COM:MetaData")
|
||||
#endif
|
||||
};
|
||||
|
||||
struct MetaDataExtractCallbackData {
|
||||
std::unique_ptr<MetaData> meta_data;
|
||||
std::string hash_key;
|
||||
std::string conversion_key;
|
||||
std::string manifest_key;
|
||||
|
||||
void addMetaData(blender::StringRef key, blender::StringRefNull value);
|
||||
void setCryptomatteKeys(blender::StringRef cryptomatte_layer_name);
|
||||
/* C type callback function (StampCallback). */
|
||||
static void extract_cryptomatte_meta_data(void *_data,
|
||||
const char *propname,
|
||||
char *propvalue,
|
||||
int UNUSED(len));
|
||||
};
|
||||
|
|
|
@ -34,12 +34,12 @@ ImageNode::ImageNode(bNode *editorNode) : Node(editorNode)
|
|||
/* pass */
|
||||
}
|
||||
NodeOperation *ImageNode::doMultilayerCheck(NodeConverter &converter,
|
||||
RenderLayer *rl,
|
||||
RenderLayer *render_layer,
|
||||
RenderPass *render_pass,
|
||||
Image *image,
|
||||
ImageUser *user,
|
||||
int framenumber,
|
||||
int outputsocketIndex,
|
||||
int passindex,
|
||||
int view,
|
||||
DataType datatype) const
|
||||
{
|
||||
|
@ -47,19 +47,18 @@ NodeOperation *ImageNode::doMultilayerCheck(NodeConverter &converter,
|
|||
MultilayerBaseOperation *operation = nullptr;
|
||||
switch (datatype) {
|
||||
case COM_DT_VALUE:
|
||||
operation = new MultilayerValueOperation(passindex, view);
|
||||
operation = new MultilayerValueOperation(render_layer, render_pass, view);
|
||||
break;
|
||||
case COM_DT_VECTOR:
|
||||
operation = new MultilayerVectorOperation(passindex, view);
|
||||
operation = new MultilayerVectorOperation(render_layer, render_pass, view);
|
||||
break;
|
||||
case COM_DT_COLOR:
|
||||
operation = new MultilayerColorOperation(passindex, view);
|
||||
operation = new MultilayerColorOperation(render_layer, render_pass, view);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
operation->setImage(image);
|
||||
operation->setRenderLayer(rl);
|
||||
operation->setImageUser(user);
|
||||
operation->setFramenumber(framenumber);
|
||||
|
||||
|
@ -128,16 +127,15 @@ void ImageNode::convertToOperations(NodeConverter &converter,
|
|||
}
|
||||
|
||||
if (rpass) {
|
||||
int passindex = BLI_findindex(&rl->passes, rpass);
|
||||
switch (rpass->channels) {
|
||||
case 1:
|
||||
operation = doMultilayerCheck(converter,
|
||||
rl,
|
||||
rpass,
|
||||
image,
|
||||
imageuser,
|
||||
framenumber,
|
||||
index,
|
||||
passindex,
|
||||
view,
|
||||
COM_DT_VALUE);
|
||||
break;
|
||||
|
@ -146,22 +144,22 @@ void ImageNode::convertToOperations(NodeConverter &converter,
|
|||
case 3:
|
||||
operation = doMultilayerCheck(converter,
|
||||
rl,
|
||||
rpass,
|
||||
image,
|
||||
imageuser,
|
||||
framenumber,
|
||||
index,
|
||||
passindex,
|
||||
view,
|
||||
COM_DT_VECTOR);
|
||||
break;
|
||||
case 4:
|
||||
operation = doMultilayerCheck(converter,
|
||||
rl,
|
||||
rpass,
|
||||
image,
|
||||
imageuser,
|
||||
framenumber,
|
||||
index,
|
||||
passindex,
|
||||
view,
|
||||
COM_DT_COLOR);
|
||||
break;
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "DNA_node_types.h"
|
||||
|
||||
#include "RE_engine.h"
|
||||
#include "RE_pipeline.h"
|
||||
|
||||
/**
|
||||
* \brief ImageNode
|
||||
|
@ -33,11 +34,11 @@ class ImageNode : public Node {
|
|||
private:
|
||||
NodeOperation *doMultilayerCheck(NodeConverter &converter,
|
||||
RenderLayer *rl,
|
||||
RenderPass *render_pass,
|
||||
Image *image,
|
||||
ImageUser *user,
|
||||
int framenumber,
|
||||
int outputsocketIndex,
|
||||
int passindex,
|
||||
int view,
|
||||
DataType datatype) const;
|
||||
|
||||
|
|
|
@ -21,10 +21,14 @@
|
|||
#include "IMB_imbuf.h"
|
||||
#include "IMB_imbuf_types.h"
|
||||
|
||||
MultilayerBaseOperation::MultilayerBaseOperation(int passindex, int view)
|
||||
MultilayerBaseOperation::MultilayerBaseOperation(RenderLayer *render_layer,
|
||||
RenderPass *render_pass,
|
||||
int view)
|
||||
{
|
||||
this->m_passId = passindex;
|
||||
this->m_passId = BLI_findindex(&render_layer->passes, render_pass);
|
||||
this->m_view = view;
|
||||
this->m_renderLayer = render_layer;
|
||||
this->m_renderPass = render_pass;
|
||||
}
|
||||
|
||||
ImBuf *MultilayerBaseOperation::getImBuf()
|
||||
|
@ -45,6 +49,32 @@ ImBuf *MultilayerBaseOperation::getImBuf()
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<MetaData> MultilayerColorOperation::getMetaData() const
|
||||
{
|
||||
BLI_assert(this->m_buffer);
|
||||
MetaDataExtractCallbackData callback_data = {nullptr};
|
||||
RenderResult *render_result = this->m_image->rr;
|
||||
if (render_result && render_result->stamp_data) {
|
||||
RenderLayer *render_layer = this->m_renderLayer;
|
||||
RenderPass *render_pass = this->m_renderPass;
|
||||
std::string full_layer_name =
|
||||
std::string(render_layer->name,
|
||||
BLI_strnlen(render_layer->name, sizeof(render_layer->name))) +
|
||||
"." +
|
||||
std::string(render_pass->name, BLI_strnlen(render_pass->name, sizeof(render_pass->name)));
|
||||
blender::StringRef cryptomatte_layer_name =
|
||||
blender::bke::cryptomatte::BKE_cryptomatte_extract_layer_name(full_layer_name);
|
||||
callback_data.setCryptomatteKeys(cryptomatte_layer_name);
|
||||
|
||||
BKE_stamp_info_callback(&callback_data,
|
||||
render_result->stamp_data,
|
||||
MetaDataExtractCallbackData::extract_cryptomatte_meta_data,
|
||||
false);
|
||||
}
|
||||
|
||||
return std::move(callback_data.meta_data);
|
||||
}
|
||||
|
||||
void MultilayerColorOperation::executePixelSampled(float output[4],
|
||||
float x,
|
||||
float y,
|
||||
|
|
|
@ -24,34 +24,34 @@ class MultilayerBaseOperation : public BaseImageOperation {
|
|||
private:
|
||||
int m_passId;
|
||||
int m_view;
|
||||
RenderLayer *m_renderlayer;
|
||||
|
||||
protected:
|
||||
RenderLayer *m_renderLayer;
|
||||
RenderPass *m_renderPass;
|
||||
ImBuf *getImBuf();
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
MultilayerBaseOperation(int passindex, int view);
|
||||
void setRenderLayer(RenderLayer *renderlayer)
|
||||
{
|
||||
this->m_renderlayer = renderlayer;
|
||||
}
|
||||
MultilayerBaseOperation(RenderLayer *render_layer, RenderPass *render_pass, int view);
|
||||
};
|
||||
|
||||
class MultilayerColorOperation : public MultilayerBaseOperation {
|
||||
public:
|
||||
MultilayerColorOperation(int passindex, int view) : MultilayerBaseOperation(passindex, view)
|
||||
MultilayerColorOperation(RenderLayer *render_layer, RenderPass *render_pass, int view)
|
||||
: MultilayerBaseOperation(render_layer, render_pass, view)
|
||||
{
|
||||
this->addOutputSocket(COM_DT_COLOR);
|
||||
}
|
||||
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
|
||||
std::unique_ptr<MetaData> getMetaData() const override;
|
||||
};
|
||||
|
||||
class MultilayerValueOperation : public MultilayerBaseOperation {
|
||||
public:
|
||||
MultilayerValueOperation(int passindex, int view) : MultilayerBaseOperation(passindex, view)
|
||||
MultilayerValueOperation(RenderLayer *render_layer, RenderPass *render_pass, int view)
|
||||
: MultilayerBaseOperation(render_layer, render_pass, view)
|
||||
{
|
||||
this->addOutputSocket(COM_DT_VALUE);
|
||||
}
|
||||
|
@ -60,7 +60,8 @@ class MultilayerValueOperation : public MultilayerBaseOperation {
|
|||
|
||||
class MultilayerVectorOperation : public MultilayerBaseOperation {
|
||||
public:
|
||||
MultilayerVectorOperation(int passindex, int view) : MultilayerBaseOperation(passindex, view)
|
||||
MultilayerVectorOperation(RenderLayer *render_layer, RenderPass *render_pass, int view)
|
||||
: MultilayerBaseOperation(render_layer, render_pass, view)
|
||||
{
|
||||
this->addOutputSocket(COM_DT_VECTOR);
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "BLI_path_util.h"
|
||||
#include "BLI_string.h"
|
||||
|
||||
#include "BKE_cryptomatte.hh"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_image.h"
|
||||
#include "BKE_main.h"
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
#include "COM_MetaData.h"
|
||||
|
||||
#include "BKE_cryptomatte.hh"
|
||||
#include "BKE_image.h"
|
||||
#include "BKE_scene.h"
|
||||
|
||||
|
@ -217,62 +216,18 @@ void RenderLayersProg::determineResolution(unsigned int resolution[2],
|
|||
}
|
||||
}
|
||||
|
||||
struct CallbackData {
|
||||
std::unique_ptr<MetaData> meta_data;
|
||||
std::string hash_key;
|
||||
std::string conversion_key;
|
||||
std::string manifest_key;
|
||||
|
||||
void addMetaData(blender::StringRef key, blender::StringRefNull value)
|
||||
{
|
||||
if (!meta_data) {
|
||||
meta_data = std::make_unique<MetaData>();
|
||||
}
|
||||
meta_data->add(key, value);
|
||||
}
|
||||
|
||||
void setCryptomatteKeys(blender::StringRef cryptomatte_layer_name)
|
||||
{
|
||||
manifest_key = blender::bke::cryptomatte::BKE_cryptomatte_meta_data_key(cryptomatte_layer_name,
|
||||
"manifest");
|
||||
hash_key = blender::bke::cryptomatte::BKE_cryptomatte_meta_data_key(cryptomatte_layer_name,
|
||||
"hash");
|
||||
conversion_key = blender::bke::cryptomatte::BKE_cryptomatte_meta_data_key(
|
||||
cryptomatte_layer_name, "conversion");
|
||||
}
|
||||
};
|
||||
|
||||
/* C type callback function (StampCallback). */
|
||||
static void extract_cryptomatte_meta_data(void *_data,
|
||||
const char *propname,
|
||||
char *propvalue,
|
||||
int UNUSED(len))
|
||||
{
|
||||
CallbackData *data = static_cast<CallbackData *>(_data);
|
||||
blender::StringRefNull key(propname);
|
||||
if (key == data->hash_key) {
|
||||
data->addMetaData(META_DATA_KEY_CRYPTOMATTE_HASH, propvalue);
|
||||
}
|
||||
else if (key == data->conversion_key) {
|
||||
data->addMetaData(META_DATA_KEY_CRYPTOMATTE_CONVERSION, propvalue);
|
||||
}
|
||||
else if (key == data->manifest_key) {
|
||||
data->addMetaData(META_DATA_KEY_CRYPTOMATTE_MANIFEST, propvalue);
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<MetaData> RenderLayersProg::getMetaData() const
|
||||
{
|
||||
Scene *scene = this->getScene();
|
||||
Render *re = (scene) ? RE_GetSceneRender(scene) : nullptr;
|
||||
RenderResult *rr = nullptr;
|
||||
CallbackData callback_data = {nullptr};
|
||||
RenderResult *render_result = nullptr;
|
||||
MetaDataExtractCallbackData callback_data = {nullptr};
|
||||
|
||||
if (re) {
|
||||
rr = RE_AcquireResultRead(re);
|
||||
render_result = RE_AcquireResultRead(re);
|
||||
}
|
||||
|
||||
if (rr && rr->stamp_data) {
|
||||
if (render_result && render_result->stamp_data) {
|
||||
ViewLayer *view_layer = (ViewLayer *)BLI_findlink(&scene->view_layers, getLayerId());
|
||||
if (view_layer) {
|
||||
std::string full_layer_name = std::string(
|
||||
|
@ -283,8 +238,10 @@ std::unique_ptr<MetaData> RenderLayersProg::getMetaData() const
|
|||
full_layer_name);
|
||||
callback_data.setCryptomatteKeys(cryptomatte_layer_name);
|
||||
|
||||
BKE_stamp_info_callback(
|
||||
&callback_data, rr->stamp_data, extract_cryptomatte_meta_data, false);
|
||||
BKE_stamp_info_callback(&callback_data,
|
||||
render_result->stamp_data,
|
||||
MetaDataExtractCallbackData::extract_cryptomatte_meta_data,
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue