Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/compositor')
-rw-r--r--source/blender/compositor/CMakeLists.txt2
-rw-r--r--source/blender/compositor/intern/COM_MetaData.cpp71
-rw-r--r--source/blender/compositor/intern/COM_MetaData.h56
-rw-r--r--source/blender/compositor/intern/COM_SocketReader.h13
-rw-r--r--source/blender/compositor/nodes/COM_OutputFileNode.cpp6
-rw-r--r--source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cpp9
-rw-r--r--source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h3
-rw-r--r--source/blender/compositor/operations/COM_OutputFileOperation.cpp33
-rw-r--r--source/blender/compositor/operations/COM_OutputFileOperation.h6
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersProg.cpp84
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersProg.h2
-rw-r--r--source/blender/compositor/operations/COM_SocketProxyOperation.cpp5
-rw-r--r--source/blender/compositor/operations/COM_SocketProxyOperation.h1
13 files changed, 283 insertions, 8 deletions
diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt
index 19eeb90c822..a226b009ec9 100644
--- a/source/blender/compositor/CMakeLists.txt
+++ b/source/blender/compositor/CMakeLists.txt
@@ -71,6 +71,8 @@ set(SRC
intern/COM_MemoryBuffer.h
intern/COM_MemoryProxy.cpp
intern/COM_MemoryProxy.h
+ intern/COM_MetaData.cpp
+ intern/COM_MetaData.h
intern/COM_Node.cpp
intern/COM_Node.h
intern/COM_NodeConverter.cpp
diff --git a/source/blender/compositor/intern/COM_MetaData.cpp b/source/blender/compositor/intern/COM_MetaData.cpp
new file mode 100644
index 00000000000..2b75947ff89
--- /dev/null
+++ b/source/blender/compositor/intern/COM_MetaData.cpp
@@ -0,0 +1,71 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2021, Blender Foundation.
+ */
+
+#include "COM_MetaData.h"
+
+#include "BKE_cryptomatte.hh"
+#include "BKE_image.h"
+
+#include "RE_pipeline.h"
+
+#include <string_view>
+
+void MetaData::add(const blender::StringRef key, const blender::StringRef value)
+{
+ entries_.add(key, value);
+}
+
+void MetaData::addCryptomatteEntry(const blender::StringRef layer_name,
+ const blender::StringRefNull key,
+ const blender::StringRef value)
+{
+ add(blender::BKE_cryptomatte_meta_data_key(layer_name, key), value);
+}
+
+/* Replace the hash neutral cryptomatte keys with hashed versions.
+ *
+ * When a conversion happens it will also add the cryptomatte name key with the given
+ * `layer_name`.*/
+void MetaData::replaceHashNeutralCryptomatteKeys(const blender::StringRef layer_name)
+{
+ std::string cryptomatte_hash = entries_.pop_default(META_DATA_KEY_CRYPTOMATTE_HASH, "");
+ std::string cryptomatte_conversion = entries_.pop_default(META_DATA_KEY_CRYPTOMATTE_CONVERSION,
+ "");
+ std::string cryptomatte_manifest = entries_.pop_default(META_DATA_KEY_CRYPTOMATTE_MANIFEST, "");
+
+ if (cryptomatte_hash.length() || cryptomatte_conversion.length() ||
+ cryptomatte_manifest.length()) {
+ addCryptomatteEntry(layer_name, "name", layer_name);
+ }
+ if (cryptomatte_hash.length()) {
+ addCryptomatteEntry(layer_name, "hash", cryptomatte_hash);
+ }
+ if (cryptomatte_conversion.length()) {
+ addCryptomatteEntry(layer_name, "conversion", cryptomatte_conversion);
+ }
+ if (cryptomatte_manifest.length()) {
+ addCryptomatteEntry(layer_name, "manifest", cryptomatte_manifest);
+ }
+}
+
+void MetaData::addToRenderResult(RenderResult *render_result) const
+{
+ for (blender::Map<std::string, std::string>::Item entry : entries_.items()) {
+ BKE_render_result_stamp_data(render_result, entry.key.c_str(), entry.value.c_str());
+ }
+}
diff --git a/source/blender/compositor/intern/COM_MetaData.h b/source/blender/compositor/intern/COM_MetaData.h
new file mode 100644
index 00000000000..22988b0b7ee
--- /dev/null
+++ b/source/blender/compositor/intern/COM_MetaData.h
@@ -0,0 +1,56 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2021, Blender Foundation.
+ */
+
+#pragma once
+
+#include <string>
+
+#include "BLI_map.hh"
+
+#include "MEM_guardedalloc.h"
+
+/* Forward declarations. */
+struct StampData;
+struct RenderResult;
+
+/* Cryptomatte includes hash in its meta data keys. The hash is generated from the render
+ * layer/pass name. Compositing happens without the knowledge of the original layer and pass. The
+ * next keys are used to transfer the cryptomatte meta data in a neutral way. The file output node
+ * will generate a hash based on the layer name configured by the user.
+ *
+ * The `{hash}` has no special meaning except to make sure that the meta data stays unique. */
+constexpr blender::StringRef META_DATA_KEY_CRYPTOMATTE_HASH("cryptomatte/{hash}/hash");
+constexpr blender::StringRef META_DATA_KEY_CRYPTOMATTE_CONVERSION("cryptomatte/{hash}/conversion");
+constexpr blender::StringRef META_DATA_KEY_CRYPTOMATTE_MANIFEST("cryptomatte/{hash}/manifest");
+constexpr blender::StringRef META_DATA_KEY_CRYPTOMATTE_NAME("cryptomatte/{hash}/name");
+
+class MetaData {
+ private:
+ blender::Map<std::string, std::string> entries_;
+ void addCryptomatteEntry(const blender::StringRef layer_name,
+ const blender::StringRefNull key,
+ const blender::StringRef value);
+
+ public:
+ void add(const blender::StringRef key, const blender::StringRef value);
+ void replaceHashNeutralCryptomatteKeys(const blender::StringRef layer_name);
+ void addToRenderResult(RenderResult *render_result) const;
+#ifdef WITH_CXX_GUARDEDALLOC
+ MEM_CXX_CLASS_ALLOC_FUNCS("COM:MetaData")
+#endif
+};
diff --git a/source/blender/compositor/intern/COM_SocketReader.h b/source/blender/compositor/intern/COM_SocketReader.h
index ee2a6e0e1bf..7c4132efe60 100644
--- a/source/blender/compositor/intern/COM_SocketReader.h
+++ b/source/blender/compositor/intern/COM_SocketReader.h
@@ -19,8 +19,12 @@
#pragma once
#include "BLI_rect.h"
+#include "COM_MetaData.h"
#include "COM_defines.h"
+#include <memory>
+#include <optional>
+
#ifdef WITH_CXX_GUARDEDALLOC
# include "MEM_guardedalloc.h"
#endif
@@ -32,6 +36,7 @@ typedef enum PixelSampler {
} PixelSampler;
class MemoryBuffer;
+
/**
* \brief Helper class for reading socket data.
* Only use this class for dispatching (un-ary and n-ary) executions.
@@ -134,6 +139,14 @@ class SocketReader {
return this->m_height;
}
+ /* Return the meta data associated with this branch.
+ *
+ * The return parameter holds an instance or is an nullptr. */
+ virtual std::unique_ptr<MetaData> getMetaData() const
+ {
+ return std::unique_ptr<MetaData>();
+ }
+
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("COM:SocketReader")
#endif
diff --git a/source/blender/compositor/nodes/COM_OutputFileNode.cpp b/source/blender/compositor/nodes/COM_OutputFileNode.cpp
index 09528e09f1f..e0cff1de276 100644
--- a/source/blender/compositor/nodes/COM_OutputFileNode.cpp
+++ b/source/blender/compositor/nodes/COM_OutputFileNode.cpp
@@ -50,7 +50,8 @@ void OutputFileNode::convertToOperations(NodeConverter &converter,
OutputOpenExrMultiLayerOperation *outputOperation;
if (is_multiview && storage->format.views_format == R_IMF_VIEWS_MULTIVIEW) {
- outputOperation = new OutputOpenExrMultiLayerMultiViewOperation(context.getRenderData(),
+ outputOperation = new OutputOpenExrMultiLayerMultiViewOperation(context.getScene(),
+ context.getRenderData(),
context.getbNodeTree(),
storage->base_path,
storage->format.exr_codec,
@@ -58,7 +59,8 @@ void OutputFileNode::convertToOperations(NodeConverter &converter,
context.getViewName());
}
else {
- outputOperation = new OutputOpenExrMultiLayerOperation(context.getRenderData(),
+ outputOperation = new OutputOpenExrMultiLayerOperation(context.getScene(),
+ context.getRenderData(),
context.getbNodeTree(),
storage->base_path,
storage->format.exr_codec,
diff --git a/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cpp b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cpp
index 21d9177ddd5..0b732357c92 100644
--- a/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cpp
+++ b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cpp
@@ -143,13 +143,14 @@ void OutputOpenExrSingleLayerMultiViewOperation::deinitExecution()
/************************************ OpenEXR Multilayer Multiview *******************************/
OutputOpenExrMultiLayerMultiViewOperation::OutputOpenExrMultiLayerMultiViewOperation(
+ const Scene *scene,
const RenderData *rd,
const bNodeTree *tree,
const char *path,
char exr_codec,
bool exr_half_float,
const char *viewName)
- : OutputOpenExrMultiLayerOperation(rd, tree, path, exr_codec, exr_half_float, viewName)
+ : OutputOpenExrMultiLayerOperation(scene, rd, tree, path, exr_codec, exr_half_float, viewName)
{
}
@@ -195,12 +196,16 @@ void *OutputOpenExrMultiLayerMultiViewOperation::get_handle(const char *filename
BLI_make_existing_file(filename);
/* prepare the file with all the channels for the header */
- if (IMB_exr_begin_write(exrhandle, filename, width, height, this->m_exr_codec, nullptr) == 0) {
+ StampData *stamp_data = createStampData();
+ if (IMB_exr_begin_write(exrhandle, filename, width, height, this->m_exr_codec, stamp_data) ==
+ 0) {
printf("Error Writing Multilayer Multiview Openexr\n");
IMB_exr_close(exrhandle);
+ BKE_stamp_data_free(stamp_data);
}
else {
IMB_exr_clear_channels(exrhandle);
+ BKE_stamp_data_free(stamp_data);
return exrhandle;
}
}
diff --git a/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h
index 1deaf121173..bc057355cef 100644
--- a/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h
+++ b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h
@@ -48,7 +48,8 @@ class OutputOpenExrSingleLayerMultiViewOperation : public OutputSingleLayerOpera
class OutputOpenExrMultiLayerMultiViewOperation : public OutputOpenExrMultiLayerOperation {
private:
public:
- OutputOpenExrMultiLayerMultiViewOperation(const RenderData *rd,
+ OutputOpenExrMultiLayerMultiViewOperation(const Scene *scene,
+ const RenderData *rd,
const bNodeTree *tree,
const char *path,
char exr_codec,
diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.cpp b/source/blender/compositor/operations/COM_OutputFileOperation.cpp
index 2676ab1b9ca..216b754f676 100644
--- a/source/blender/compositor/operations/COM_OutputFileOperation.cpp
+++ b/source/blender/compositor/operations/COM_OutputFileOperation.cpp
@@ -18,12 +18,15 @@
#include "COM_OutputFileOperation.h"
+#include "COM_MetaData.h"
+
#include <cstring>
#include "BLI_listbase.h"
#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"
@@ -36,6 +39,8 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+#include "RE_pipeline.h"
+
void add_exr_channels(void *exrhandle,
const char *layerName,
const DataType datatype,
@@ -299,13 +304,15 @@ OutputOpenExrLayer::OutputOpenExrLayer(const char *name_, DataType datatype_, bo
this->imageInput = nullptr;
}
-OutputOpenExrMultiLayerOperation::OutputOpenExrMultiLayerOperation(const RenderData *rd,
+OutputOpenExrMultiLayerOperation::OutputOpenExrMultiLayerOperation(const Scene *scene,
+ const RenderData *rd,
const bNodeTree *tree,
const char *path,
char exr_codec,
bool exr_half_float,
const char *viewName)
{
+ this->m_scene = scene;
this->m_rd = rd;
this->m_tree = tree;
@@ -323,6 +330,26 @@ void OutputOpenExrMultiLayerOperation::add_layer(const char *name,
this->m_layers.push_back(OutputOpenExrLayer(name, datatype, use_layer));
}
+StampData *OutputOpenExrMultiLayerOperation::createStampData() const
+{
+ /* StampData API doesn't provide functions to modify an instance without having a RenderResult.
+ */
+ RenderResult render_result;
+ StampData *stamp_data = BKE_stamp_info_from_scene_static(m_scene);
+ render_result.stamp_data = stamp_data;
+ for (int i = 0; i < this->m_layers.size(); i++) {
+ const OutputOpenExrLayer *layer = &this->m_layers[i];
+ std::unique_ptr<MetaData> meta_data = layer->imageInput->getMetaData();
+ if (meta_data) {
+ blender::StringRef layer_name = blender::BKE_cryptomatte_extract_layer_name(
+ blender::StringRef(layer->name, BLI_strnlen(layer->name, sizeof(layer->name))));
+ meta_data->replaceHashNeutralCryptomatteKeys(layer_name);
+ meta_data->addToRenderResult(&render_result);
+ }
+ }
+ return stamp_data;
+}
+
void OutputOpenExrMultiLayerOperation::initExecution()
{
for (unsigned int i = 0; i < this->m_layers.size(); i++) {
@@ -386,7 +413,8 @@ void OutputOpenExrMultiLayerOperation::deinitExecution()
}
/* when the filename has no permissions, this can fail */
- if (IMB_exr_begin_write(exrhandle, filename, width, height, this->m_exr_codec, nullptr)) {
+ StampData *stamp_data = createStampData();
+ if (IMB_exr_begin_write(exrhandle, filename, width, height, this->m_exr_codec, stamp_data)) {
IMB_exr_write_channels(exrhandle);
}
else {
@@ -404,5 +432,6 @@ void OutputOpenExrMultiLayerOperation::deinitExecution()
this->m_layers[i].imageInput = nullptr;
}
+ BKE_stamp_data_free(stamp_data);
}
}
diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.h b/source/blender/compositor/operations/COM_OutputFileOperation.h
index b2454e17e3f..915d59599e2 100644
--- a/source/blender/compositor/operations/COM_OutputFileOperation.h
+++ b/source/blender/compositor/operations/COM_OutputFileOperation.h
@@ -91,6 +91,7 @@ class OutputOpenExrMultiLayerOperation : public NodeOperation {
protected:
typedef std::vector<OutputOpenExrLayer> LayerList;
+ const Scene *m_scene;
const RenderData *m_rd;
const bNodeTree *m_tree;
@@ -100,8 +101,11 @@ class OutputOpenExrMultiLayerOperation : public NodeOperation {
LayerList m_layers;
const char *m_viewName;
+ StampData *createStampData() const;
+
public:
- OutputOpenExrMultiLayerOperation(const RenderData *rd,
+ OutputOpenExrMultiLayerOperation(const Scene *scene,
+ const RenderData *rd,
const bNodeTree *tree,
const char *path,
char exr_codec,
diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.cpp b/source/blender/compositor/operations/COM_RenderLayersProg.cpp
index 11f64aa4d6a..2a0a6e33b6a 100644
--- a/source/blender/compositor/operations/COM_RenderLayersProg.cpp
+++ b/source/blender/compositor/operations/COM_RenderLayersProg.cpp
@@ -18,8 +18,16 @@
#include "COM_RenderLayersProg.h"
+#include "COM_MetaData.h"
+
+#include "BKE_cryptomatte.hh"
+#include "BKE_image.h"
#include "BKE_scene.h"
+
#include "BLI_listbase.h"
+#include "BLI_string.h"
+#include "BLI_string_ref.hh"
+
#include "DNA_scene_types.h"
#include "RE_pipeline.h"
@@ -209,6 +217,82 @@ 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_meta_data_key(cryptomatte_layer_name, "manifest");
+ hash_key = blender::BKE_cryptomatte_meta_data_key(cryptomatte_layer_name, "hash");
+ conversion_key = blender::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};
+
+ if (re) {
+ rr = RE_AcquireResultRead(re);
+ }
+
+ if (rr && rr->stamp_data) {
+ ViewLayer *view_layer = (ViewLayer *)BLI_findlink(&scene->view_layers, getLayerId());
+ if (view_layer) {
+ std::string full_layer_name = std::string(
+ view_layer->name,
+ BLI_strnlen(view_layer->name, sizeof(view_layer->name))) +
+ "." + m_passName;
+ blender::StringRef cryptomatte_layer_name = blender::BKE_cryptomatte_extract_layer_name(
+ full_layer_name);
+ callback_data.setCryptomatteKeys(cryptomatte_layer_name);
+
+ BKE_stamp_info_callback(
+ &callback_data, rr->stamp_data, extract_cryptomatte_meta_data, false);
+ }
+ }
+
+ if (re) {
+ RE_ReleaseResult(re);
+ re = nullptr;
+ }
+
+ return std::move(callback_data.meta_data);
+}
+
/* ******** Render Layers AO Operation ******** */
void RenderLayersAOOperation::executePixelSampled(float output[4],
float x,
diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.h b/source/blender/compositor/operations/COM_RenderLayersProg.h
index abfcac1f80d..ec98969b223 100644
--- a/source/blender/compositor/operations/COM_RenderLayersProg.h
+++ b/source/blender/compositor/operations/COM_RenderLayersProg.h
@@ -121,6 +121,8 @@ class RenderLayersProg : public NodeOperation {
void initExecution();
void deinitExecution();
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+
+ std::unique_ptr<MetaData> getMetaData() const override;
};
class RenderLayersAOOperation : public RenderLayersProg {
diff --git a/source/blender/compositor/operations/COM_SocketProxyOperation.cpp b/source/blender/compositor/operations/COM_SocketProxyOperation.cpp
index baeb2f44303..53f5fea8795 100644
--- a/source/blender/compositor/operations/COM_SocketProxyOperation.cpp
+++ b/source/blender/compositor/operations/COM_SocketProxyOperation.cpp
@@ -24,3 +24,8 @@ SocketProxyOperation::SocketProxyOperation(DataType type, bool use_conversion)
this->addInputSocket(type);
this->addOutputSocket(type);
}
+
+std::unique_ptr<MetaData> SocketProxyOperation::getMetaData() const
+{
+ return this->getInputSocket(0)->getReader()->getMetaData();
+}
diff --git a/source/blender/compositor/operations/COM_SocketProxyOperation.h b/source/blender/compositor/operations/COM_SocketProxyOperation.h
index 22c144598f6..435083f5008 100644
--- a/source/blender/compositor/operations/COM_SocketProxyOperation.h
+++ b/source/blender/compositor/operations/COM_SocketProxyOperation.h
@@ -41,6 +41,7 @@ class SocketProxyOperation : public NodeOperation {
{
m_use_conversion = use_conversion;
}
+ std::unique_ptr<MetaData> getMetaData() const override;
private:
bool m_use_conversion;