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/nodes/COM_CryptomatteNode.cc')
-rw-r--r--source/blender/compositor/nodes/COM_CryptomatteNode.cc255
1 files changed, 219 insertions, 36 deletions
diff --git a/source/blender/compositor/nodes/COM_CryptomatteNode.cc b/source/blender/compositor/nodes/COM_CryptomatteNode.cc
index 27ef98af8f3..4c698b5609f 100644
--- a/source/blender/compositor/nodes/COM_CryptomatteNode.cc
+++ b/source/blender/compositor/nodes/COM_CryptomatteNode.cc
@@ -17,64 +17,247 @@
*/
#include "COM_CryptomatteNode.h"
-#include "COM_ConvertOperation.h"
-#include "COM_CryptomatteOperation.h"
-
+#include "BKE_node.h"
#include "BLI_assert.h"
#include "BLI_hash_mm3.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
-
+#include "COM_ConvertOperation.h"
+#include "COM_CryptomatteOperation.h"
+#include "COM_MultilayerImageOperation.h"
+#include "COM_RenderLayersProg.h"
#include "COM_SetAlphaMultiplyOperation.h"
+#include "COM_SetColorOperation.h"
#include <iterator>
+#include <string>
+
+/** \name Cryptomatte base
+ * \{ */
-CryptomatteNode::CryptomatteNode(bNode *editorNode) : Node(editorNode)
+void CryptomatteBaseNode::convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const
{
- /* pass */
+ NodeOutput *output_image_socket = this->getOutputSocket(0);
+
+ bNode *node = this->getbNode();
+ NodeCryptomatte *cryptomatte_settings = static_cast<NodeCryptomatte *>(node->storage);
+
+ CryptomatteOperation *cryptomatte_operation = create_cryptomatte_operation(
+ converter, context, *node, cryptomatte_settings);
+ converter.addOperation(cryptomatte_operation);
+
+ NodeOutput *output_matte_socket = this->getOutputSocket(1);
+ SeparateChannelOperation *extract_mask_operation = new SeparateChannelOperation;
+ extract_mask_operation->setChannel(3);
+ converter.addOperation(extract_mask_operation);
+ converter.addLink(cryptomatte_operation->getOutputSocket(0),
+ extract_mask_operation->getInputSocket(0));
+ converter.mapOutputSocket(output_matte_socket, extract_mask_operation->getOutputSocket(0));
+
+ NodeInput *input_image_socket = this->getInputSocket(0);
+ SetAlphaMultiplyOperation *apply_mask_operation = new SetAlphaMultiplyOperation();
+ converter.mapInputSocket(input_image_socket, apply_mask_operation->getInputSocket(0));
+ converter.addOperation(apply_mask_operation);
+ converter.addLink(extract_mask_operation->getOutputSocket(0),
+ apply_mask_operation->getInputSocket(1));
+ converter.mapOutputSocket(output_image_socket, apply_mask_operation->getOutputSocket(0));
+
+ NodeOutput *output_pick_socket = this->getOutputSocket(2);
+ SetAlphaMultiplyOperation *extract_pick_operation = new SetAlphaMultiplyOperation();
+ converter.addOperation(extract_pick_operation);
+ converter.addInputValue(extract_pick_operation->getInputSocket(1), 1.0f);
+ converter.addLink(cryptomatte_operation->getOutputSocket(0),
+ extract_pick_operation->getInputSocket(0));
+ converter.mapOutputSocket(output_pick_socket, extract_pick_operation->getOutputSocket(0));
}
-void CryptomatteNode::convertToOperations(NodeConverter &converter,
- const CompositorContext & /*context*/) const
+/* \} */
+
+/** \name Cryptomatte V2
+ * \{ */
+static std::string prefix_from_node(const bNode &node)
{
- NodeInput *inputSocketImage = this->getInputSocket(0);
- NodeOutput *outputSocketImage = this->getOutputSocket(0);
- NodeOutput *outputSocketMatte = this->getOutputSocket(1);
- NodeOutput *outputSocketPick = this->getOutputSocket(2);
+ char prefix[MAX_NAME];
+ ntreeCompositCryptomatteLayerPrefix(&node, prefix, sizeof(prefix));
+ return std::string(prefix, BLI_strnlen(prefix, sizeof(prefix)));
+}
- bNode *node = this->getbNode();
- NodeCryptomatte *cryptoMatteSettings = (NodeCryptomatte *)node->storage;
+static std::string combined_layer_pass_name(RenderLayer *render_layer, RenderPass *render_pass)
+{
+ if (render_layer->name[0] == '\0') {
+ return std::string(render_pass->name,
+ BLI_strnlen(render_pass->name, sizeof(render_pass->name)));
+ }
- CryptomatteOperation *operation = new CryptomatteOperation(getNumberOfInputSockets() - 1);
- if (cryptoMatteSettings) {
- LISTBASE_FOREACH (CryptomatteEntry *, cryptomatte_entry, &cryptoMatteSettings->entries) {
- operation->addObjectIndex(cryptomatte_entry->encoded_hash);
+ std::string combined_name =
+ blender::StringRef(render_layer->name,
+ BLI_strnlen(render_layer->name, sizeof(render_layer->name))) +
+ "." +
+ blender::StringRef(render_pass->name,
+ BLI_strnlen(render_pass->name, sizeof(render_pass->name)));
+ return combined_name;
+}
+
+void CryptomatteNode::input_operations_from_render_source(
+ const CompositorContext &context,
+ const bNode &node,
+ blender::Vector<NodeOperation *> &r_input_operations)
+{
+ Scene *scene = (Scene *)node.id;
+ if (!scene) {
+ return;
+ }
+
+ BLI_assert(GS(scene->id.name) == ID_SCE);
+ Render *render = RE_GetSceneRender(scene);
+ RenderResult *render_result = render ? RE_AcquireResultRead(render) : nullptr;
+
+ if (!render_result) {
+ return;
+ }
+
+ const short cryptomatte_layer_id = 0;
+ const std::string prefix = prefix_from_node(node);
+ LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
+ RenderLayer *render_layer = RE_GetRenderLayer(render_result, view_layer->name);
+ if (render_layer) {
+ LISTBASE_FOREACH (RenderPass *, render_pass, &render_layer->passes) {
+ const std::string combined_name = combined_layer_pass_name(render_layer, render_pass);
+ if (blender::StringRef(combined_name).startswith(prefix)) {
+ RenderLayersProg *op = new RenderLayersProg(
+ render_pass->name, COM_DT_COLOR, render_pass->channels);
+ op->setScene(scene);
+ op->setLayerId(cryptomatte_layer_id);
+ op->setRenderData(context.getRenderData());
+ op->setViewName(context.getViewName());
+ r_input_operations.append(op);
+ }
+ }
}
}
+ RE_ReleaseResult(render);
+}
- converter.addOperation(operation);
+void CryptomatteNode::input_operations_from_image_source(
+ const CompositorContext &context,
+ const bNode &node,
+ blender::Vector<NodeOperation *> &r_input_operations)
+{
+ NodeCryptomatte *cryptomatte_settings = (NodeCryptomatte *)node.storage;
+ Image *image = (Image *)node.id;
+ if (!image) {
+ return;
+ }
- for (int i = 0; i < getNumberOfInputSockets() - 1; i++) {
- converter.mapInputSocket(this->getInputSocket(i + 1), operation->getInputSocket(i));
+ BLI_assert(GS(image->id.name) == ID_IM);
+ if (image->type != IMA_TYPE_MULTILAYER) {
+ return;
}
- SeparateChannelOperation *separateOperation = new SeparateChannelOperation;
- separateOperation->setChannel(3);
- converter.addOperation(separateOperation);
+ ImageUser *iuser = &cryptomatte_settings->iuser;
+ BKE_image_user_frame_calc(image, iuser, context.getFramenumber());
+ ImBuf *ibuf = BKE_image_acquire_ibuf(image, iuser, nullptr);
- SetAlphaMultiplyOperation *operationAlpha = new SetAlphaMultiplyOperation();
- converter.addOperation(operationAlpha);
+ if (image->rr) {
+ int view = 0;
+ if (BLI_listbase_count_at_most(&image->rr->views, 2) > 1) {
+ if (iuser->view == 0) {
+ /* Heuristic to match image name with scene names, check if the view name exists in the
+ * image. */
+ view = BLI_findstringindex(
+ &image->rr->views, context.getViewName(), offsetof(RenderView, name));
+ if (view == -1) {
+ view = 0;
+ }
+ }
+ else {
+ view = iuser->view - 1;
+ }
+ }
- converter.addLink(operation->getOutputSocket(0), separateOperation->getInputSocket(0));
- converter.addLink(separateOperation->getOutputSocket(0), operationAlpha->getInputSocket(1));
+ const std::string prefix = prefix_from_node(node);
+ LISTBASE_FOREACH (RenderLayer *, render_layer, &image->rr->layers) {
+ LISTBASE_FOREACH (RenderPass *, render_pass, &render_layer->passes) {
+ const std::string combined_name = combined_layer_pass_name(render_layer, render_pass);
+ if (blender::StringRef(combined_name).startswith(prefix)) {
+ MultilayerColorOperation *op = new MultilayerColorOperation(
+ render_layer, render_pass, view);
+ op->setImage(image);
+ op->setImageUser(iuser);
+ op->setFramenumber(context.getFramenumber());
+ r_input_operations.append(op);
+ }
+ }
+ }
+ }
+ BKE_image_release_ibuf(image, ibuf, nullptr);
+}
- SetAlphaMultiplyOperation *clearAlphaOperation = new SetAlphaMultiplyOperation();
- converter.addOperation(clearAlphaOperation);
- converter.addInputValue(clearAlphaOperation->getInputSocket(1), 1.0f);
+blender::Vector<NodeOperation *> CryptomatteNode::create_input_operations(
+ const CompositorContext &context, const bNode &node)
+{
+ blender::Vector<NodeOperation *> input_operations;
+ switch (node.custom1) {
+ case CMP_CRYPTOMATTE_SRC_RENDER:
+ input_operations_from_render_source(context, node, input_operations);
+ break;
+ case CMP_CRYPTOMATTE_SRC_IMAGE:
+ input_operations_from_image_source(context, node, input_operations);
+ break;
+ }
- converter.addLink(operation->getOutputSocket(0), clearAlphaOperation->getInputSocket(0));
+ if (input_operations.is_empty()) {
+ SetColorOperation *op = new SetColorOperation();
+ op->setChannel1(0.0f);
+ op->setChannel2(1.0f);
+ op->setChannel3(0.0f);
+ op->setChannel4(0.0f);
+ input_operations.append(op);
+ }
+ return input_operations;
+}
+CryptomatteOperation *CryptomatteNode::create_cryptomatte_operation(
+ NodeConverter &converter,
+ const CompositorContext &context,
+ const bNode &node,
+ const NodeCryptomatte *cryptomatte_settings) const
+{
+ blender::Vector<NodeOperation *> input_operations = create_input_operations(context, node);
+ CryptomatteOperation *operation = new CryptomatteOperation(input_operations.size());
+ LISTBASE_FOREACH (CryptomatteEntry *, cryptomatte_entry, &cryptomatte_settings->entries) {
+ operation->addObjectIndex(cryptomatte_entry->encoded_hash);
+ }
+ for (int i = 0; i < input_operations.size(); ++i) {
+ converter.addOperation(input_operations[i]);
+ converter.addLink(input_operations[i]->getOutputSocket(), operation->getInputSocket(i));
+ }
+ return operation;
+}
+
+/* \} */
+
+/** \name Cryptomatte legacy
+ * \{ */
- converter.mapInputSocket(inputSocketImage, operationAlpha->getInputSocket(0));
- converter.mapOutputSocket(outputSocketMatte, separateOperation->getOutputSocket(0));
- converter.mapOutputSocket(outputSocketImage, operationAlpha->getOutputSocket(0));
- converter.mapOutputSocket(outputSocketPick, clearAlphaOperation->getOutputSocket(0));
+CryptomatteOperation *CryptomatteLegacyNode::create_cryptomatte_operation(
+ NodeConverter &converter,
+ const CompositorContext &UNUSED(context),
+ const bNode &UNUSED(node),
+ const NodeCryptomatte *cryptomatte_settings) const
+{
+ const int num_inputs = getNumberOfInputSockets() - 1;
+ CryptomatteOperation *operation = new CryptomatteOperation(num_inputs);
+ if (cryptomatte_settings) {
+ LISTBASE_FOREACH (CryptomatteEntry *, cryptomatte_entry, &cryptomatte_settings->entries) {
+ operation->addObjectIndex(cryptomatte_entry->encoded_hash);
+ }
+ }
+
+ for (int i = 0; i < num_inputs; i++) {
+ converter.mapInputSocket(this->getInputSocket(i + 1), operation->getInputSocket(i));
+ }
+
+ return operation;
}
+
+/* \} */ \ No newline at end of file