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:
authorOmar Emara <mail@OmarEmara.dev>2022-08-10 11:21:18 +0300
committerOmar Emara <mail@OmarEmara.dev>2022-08-10 11:21:18 +0300
commitc014021802c323c3ed55c3c283717975a3d93edf (patch)
treea2537ce8187e6acff56b3936d994ab73447b3ad0 /source/blender/nodes
parentb5df7a02ac754de8e04fdeda4d1c3f0fcdf6a7a2 (diff)
Realtime Compositor: Add basic matte nodes
This patch implements the following nodes for the realtime compositor: - Box mask node. - Channel matte node. - Chroma matte node. - Color matte node. - Color spill node. - Difference matte node. - Distance matte node. - Ellipse matte node. - Luminance matte node. Differential Revision: https://developer.blender.org/D15230 Reviewed By: Clement Foucault
Diffstat (limited to 'source/blender/nodes')
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_boxmask.cc102
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_channel_matte.cc99
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_chroma_matte.cc66
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_color_matte.cc65
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_color_spill.cc115
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_diff_matte.cc57
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_distance_matte.cc75
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_ellipsemask.cc102
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_luma_matte.cc58
9 files changed, 724 insertions, 15 deletions
diff --git a/source/blender/nodes/composite/nodes/node_composite_boxmask.cc b/source/blender/nodes/composite/nodes/node_composite_boxmask.cc
index f39b69c63f2..9c7bb6432cb 100644
--- a/source/blender/nodes/composite/nodes/node_composite_boxmask.cc
+++ b/source/blender/nodes/composite/nodes/node_composite_boxmask.cc
@@ -5,9 +5,18 @@
* \ingroup cmpnodes
*/
+#include <cmath>
+
+#include "BLI_math_vec_types.hh"
+
#include "UI_interface.h"
#include "UI_resources.h"
+#include "GPU_shader.h"
+
+#include "COM_node_operation.hh"
+#include "COM_utilities.hh"
+
#include "node_composite_util.hh"
/* **************** SCALAR MATH ******************** */
@@ -48,6 +57,98 @@ static void node_composit_buts_boxmask(uiLayout *layout, bContext *UNUSED(C), Po
uiItemR(layout, ptr, "mask_type", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
}
+using namespace blender::realtime_compositor;
+
+class BoxMaskOperation : public NodeOperation {
+ public:
+ using NodeOperation::NodeOperation;
+
+ void execute() override
+ {
+ GPUShader *shader = shader_manager().get(get_shader_name());
+ GPU_shader_bind(shader);
+
+ const Domain domain = compute_domain();
+
+ GPU_shader_uniform_2iv(shader, "domain_size", domain.size);
+
+ GPU_shader_uniform_2fv(shader, "location", get_location());
+ GPU_shader_uniform_2fv(shader, "size", get_size() / 2.0f);
+ GPU_shader_uniform_1f(shader, "cos_angle", std::cos(get_angle()));
+ GPU_shader_uniform_1f(shader, "sin_angle", std::sin(get_angle()));
+
+ const Result &input_mask = get_input("Mask");
+ input_mask.bind_as_texture(shader, "base_mask_tx");
+
+ const Result &value = get_input("Value");
+ value.bind_as_texture(shader, "mask_value_tx");
+
+ Result &output_mask = get_result("Mask");
+ output_mask.allocate_texture(domain);
+ output_mask.bind_as_image(shader, "output_mask_img");
+
+ compute_dispatch_threads_at_least(shader, domain.size);
+
+ input_mask.unbind_as_texture();
+ value.unbind_as_texture();
+ output_mask.unbind_as_image();
+ GPU_shader_unbind();
+ }
+
+ Domain compute_domain() override
+ {
+ if (get_input("Mask").is_single_value()) {
+ return Domain(context().get_output_size());
+ }
+ return get_input("Mask").domain();
+ }
+
+ CMPNodeMaskType get_mask_type()
+ {
+ return (CMPNodeMaskType)bnode().custom1;
+ }
+
+ const char *get_shader_name()
+ {
+ switch (get_mask_type()) {
+ default:
+ case CMP_NODE_MASKTYPE_ADD:
+ return "compositor_box_mask_add";
+ case CMP_NODE_MASKTYPE_SUBTRACT:
+ return "compositor_box_mask_subtract";
+ case CMP_NODE_MASKTYPE_MULTIPLY:
+ return "compositor_box_mask_multiply";
+ case CMP_NODE_MASKTYPE_NOT:
+ return "compositor_box_mask_not";
+ }
+ }
+
+ NodeBoxMask &get_node_box_mask()
+ {
+ return *static_cast<NodeBoxMask *>(bnode().storage);
+ }
+
+ float2 get_location()
+ {
+ return float2(get_node_box_mask().x, get_node_box_mask().y);
+ }
+
+ float2 get_size()
+ {
+ return float2(get_node_box_mask().width, get_node_box_mask().height);
+ }
+
+ float get_angle()
+ {
+ return get_node_box_mask().rotation;
+ }
+};
+
+static NodeOperation *get_compositor_operation(Context &context, DNode node)
+{
+ return new BoxMaskOperation(context, node);
+}
+
} // namespace blender::nodes::node_composite_boxmask_cc
void register_node_type_cmp_boxmask()
@@ -61,6 +162,7 @@ void register_node_type_cmp_boxmask()
ntype.draw_buttons = file_ns::node_composit_buts_boxmask;
node_type_init(&ntype, file_ns::node_composit_init_boxmask);
node_type_storage(&ntype, "NodeBoxMask", node_free_standard_storage, node_copy_standard_storage);
+ ntype.get_compositor_operation = file_ns::get_compositor_operation;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_channel_matte.cc b/source/blender/nodes/composite/nodes/node_composite_channel_matte.cc
index 627f07fdfce..e899f7eb100 100644
--- a/source/blender/nodes/composite/nodes/node_composite_channel_matte.cc
+++ b/source/blender/nodes/composite/nodes/node_composite_channel_matte.cc
@@ -10,6 +10,10 @@
#include "UI_interface.h"
#include "UI_resources.h"
+#include "GPU_material.h"
+
+#include "COM_shader_node.hh"
+
#include "node_composite_util.hh"
/* ******************* Channel Matte Node ********************************* */
@@ -18,7 +22,9 @@ namespace blender::nodes::node_composite_channel_matte_cc {
static void cmp_node_channel_matte_declare(NodeDeclarationBuilder &b)
{
- b.add_input<decl::Color>(N_("Image")).default_value({1.0f, 1.0f, 1.0f, 1.0f});
+ b.add_input<decl::Color>(N_("Image"))
+ .default_value({1.0f, 1.0f, 1.0f, 1.0f})
+ .compositor_domain_priority(0);
b.add_output<decl::Color>(N_("Image"));
b.add_output<decl::Float>(N_("Matte"));
}
@@ -79,6 +85,96 @@ static void node_composit_buts_channel_matte(uiLayout *layout,
col, ptr, "limit_min", UI_ITEM_R_SPLIT_EMPTY_NAME | UI_ITEM_R_SLIDER, nullptr, ICON_NONE);
}
+using namespace blender::realtime_compositor;
+
+class ChannelMatteShaderNode : public ShaderNode {
+ public:
+ using ShaderNode::ShaderNode;
+
+ void compile(GPUMaterial *material) override
+ {
+ GPUNodeStack *inputs = get_inputs_array();
+ GPUNodeStack *outputs = get_outputs_array();
+
+ const float color_space = get_color_space();
+ const float matte_channel = get_matte_channel();
+ float limit_channels[2];
+ get_limit_channels(limit_channels);
+ const float max_limit = get_max_limit();
+ const float min_limit = get_min_limit();
+
+ GPU_stack_link(material,
+ &bnode(),
+ "node_composite_channel_matte",
+ inputs,
+ outputs,
+ GPU_constant(&color_space),
+ GPU_constant(&matte_channel),
+ GPU_constant(limit_channels),
+ GPU_uniform(&max_limit),
+ GPU_uniform(&min_limit));
+ }
+
+ /* 1 -> CMP_NODE_CHANNEL_MATTE_CS_RGB
+ * 2 -> CMP_NODE_CHANNEL_MATTE_CS_HSV
+ * 3 -> CMP_NODE_CHANNEL_MATTE_CS_YUV
+ * 4 -> CMP_NODE_CHANNEL_MATTE_CS_YCC */
+ int get_color_space()
+ {
+ return bnode().custom1;
+ }
+
+ /* Get the index of the channel used to generate the matte. */
+ int get_matte_channel()
+ {
+ return bnode().custom2 - 1;
+ }
+
+ NodeChroma *get_node_chroma()
+ {
+ return static_cast<NodeChroma *>(bnode().storage);
+ }
+
+ /* Get the index of the channel used to compute the limit value. */
+ int get_limit_channel()
+ {
+ return get_node_chroma()->channel - 1;
+ }
+
+ /* Get the indices of the channels used to compute the limit value. We always assume the limit
+ * algorithm is Max, if it is a single limit channel, store it in both limit channels, because
+ * the maximum of two identical values is is the same value. */
+ void get_limit_channels(float limit_channels[2])
+ {
+ if (get_node_chroma()->algorithm == CMP_NODE_CHANNEL_MATTE_LIMIT_ALGORITHM_MAX) {
+ /* If the algorithm is Max, store the indices of the other two channels other than the matte
+ * channel. */
+ limit_channels[0] = (get_matte_channel() + 1) % 3;
+ limit_channels[1] = (get_matte_channel() + 2) % 3;
+ }
+ else {
+ /* If the algorithm is Single, store the index of the limit channel in both channels. */
+ limit_channels[0] = get_limit_channel();
+ limit_channels[1] = get_limit_channel();
+ }
+ }
+
+ float get_max_limit()
+ {
+ return get_node_chroma()->t1;
+ }
+
+ float get_min_limit()
+ {
+ return get_node_chroma()->t2;
+ }
+};
+
+static ShaderNode *get_compositor_shader_node(DNode node)
+{
+ return new ChannelMatteShaderNode(node);
+}
+
} // namespace blender::nodes::node_composite_channel_matte_cc
void register_node_type_cmp_channel_matte()
@@ -93,6 +189,7 @@ void register_node_type_cmp_channel_matte()
ntype.flag |= NODE_PREVIEW;
node_type_init(&ntype, file_ns::node_composit_init_channel_matte);
node_type_storage(&ntype, "NodeChroma", node_free_standard_storage, node_copy_standard_storage);
+ ntype.get_compositor_shader_node = file_ns::get_compositor_shader_node;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_chroma_matte.cc b/source/blender/nodes/composite/nodes/node_composite_chroma_matte.cc
index 69319c6825d..9dcd4213949 100644
--- a/source/blender/nodes/composite/nodes/node_composite_chroma_matte.cc
+++ b/source/blender/nodes/composite/nodes/node_composite_chroma_matte.cc
@@ -5,11 +5,15 @@
* \ingroup cmpnodes
*/
-#include "BLI_math_rotation.h"
+#include <cmath>
#include "UI_interface.h"
#include "UI_resources.h"
+#include "GPU_material.h"
+
+#include "COM_shader_node.hh"
+
#include "node_composite_util.hh"
/* ******************* Chroma Key ********************************************************** */
@@ -18,8 +22,12 @@ namespace blender::nodes::node_composite_chroma_matte_cc {
static void cmp_node_chroma_matte_declare(NodeDeclarationBuilder &b)
{
- b.add_input<decl::Color>(N_("Image")).default_value({1.0f, 1.0f, 1.0f, 1.0f});
- b.add_input<decl::Color>(N_("Key Color")).default_value({1.0f, 1.0f, 1.0f, 1.0f});
+ b.add_input<decl::Color>(N_("Image"))
+ .default_value({1.0f, 1.0f, 1.0f, 1.0f})
+ .compositor_domain_priority(0);
+ b.add_input<decl::Color>(N_("Key Color"))
+ .default_value({1.0f, 1.0f, 1.0f, 1.0f})
+ .compositor_domain_priority(1);
b.add_output<decl::Color>(N_("Image"));
b.add_output<decl::Float>(N_("Matte"));
}
@@ -51,6 +59,57 @@ static void node_composit_buts_chroma_matte(uiLayout *layout, bContext *UNUSED(C
// uiItemR(col, ptr, "shadow_adjust", UI_ITEM_R_SLIDER, nullptr, ICON_NONE);
}
+using namespace blender::realtime_compositor;
+
+class ChromaMatteShaderNode : public ShaderNode {
+ public:
+ using ShaderNode::ShaderNode;
+
+ void compile(GPUMaterial *material) override
+ {
+ GPUNodeStack *inputs = get_inputs_array();
+ GPUNodeStack *outputs = get_outputs_array();
+
+ const float acceptance = get_acceptance();
+ const float cutoff = get_cutoff();
+ const float falloff = get_falloff();
+
+ GPU_stack_link(material,
+ &bnode(),
+ "node_composite_chroma_matte",
+ inputs,
+ outputs,
+ GPU_uniform(&acceptance),
+ GPU_uniform(&cutoff),
+ GPU_uniform(&falloff));
+ }
+
+ NodeChroma *get_node_chroma()
+ {
+ return static_cast<NodeChroma *>(bnode().storage);
+ }
+
+ float get_acceptance()
+ {
+ return std::tan(get_node_chroma()->t1) / 2.0f;
+ }
+
+ float get_cutoff()
+ {
+ return get_node_chroma()->t2;
+ }
+
+ float get_falloff()
+ {
+ return get_node_chroma()->fstrength;
+ }
+};
+
+static ShaderNode *get_compositor_shader_node(DNode node)
+{
+ return new ChromaMatteShaderNode(node);
+}
+
} // namespace blender::nodes::node_composite_chroma_matte_cc
void register_node_type_cmp_chroma_matte()
@@ -65,6 +124,7 @@ void register_node_type_cmp_chroma_matte()
ntype.flag |= NODE_PREVIEW;
node_type_init(&ntype, file_ns::node_composit_init_chroma_matte);
node_type_storage(&ntype, "NodeChroma", node_free_standard_storage, node_copy_standard_storage);
+ ntype.get_compositor_shader_node = file_ns::get_compositor_shader_node;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_color_matte.cc b/source/blender/nodes/composite/nodes/node_composite_color_matte.cc
index 474fb1b72f2..5e3aaf512e6 100644
--- a/source/blender/nodes/composite/nodes/node_composite_color_matte.cc
+++ b/source/blender/nodes/composite/nodes/node_composite_color_matte.cc
@@ -8,6 +8,10 @@
#include "UI_interface.h"
#include "UI_resources.h"
+#include "GPU_material.h"
+
+#include "COM_shader_node.hh"
+
#include "node_composite_util.hh"
/* ******************* Color Matte ********************************************************** */
@@ -16,8 +20,12 @@ namespace blender::nodes::node_composite_color_matte_cc {
static void cmp_node_color_matte_declare(NodeDeclarationBuilder &b)
{
- b.add_input<decl::Color>(N_("Image")).default_value({1.0f, 1.0f, 1.0f, 1.0f});
- b.add_input<decl::Color>(N_("Key Color")).default_value({1.0f, 1.0f, 1.0f, 1.0f});
+ b.add_input<decl::Color>(N_("Image"))
+ .default_value({1.0f, 1.0f, 1.0f, 1.0f})
+ .compositor_domain_priority(0);
+ b.add_input<decl::Color>(N_("Key Color"))
+ .default_value({1.0f, 1.0f, 1.0f, 1.0f})
+ .compositor_domain_priority(1);
b.add_output<decl::Color>(N_("Image"));
b.add_output<decl::Float>(N_("Matte"));
}
@@ -50,6 +58,58 @@ static void node_composit_buts_color_matte(uiLayout *layout, bContext *UNUSED(C)
col, ptr, "color_value", UI_ITEM_R_SPLIT_EMPTY_NAME | UI_ITEM_R_SLIDER, nullptr, ICON_NONE);
}
+using namespace blender::realtime_compositor;
+
+class ColorMatteShaderNode : public ShaderNode {
+ public:
+ using ShaderNode::ShaderNode;
+
+ void compile(GPUMaterial *material) override
+ {
+ GPUNodeStack *inputs = get_inputs_array();
+ GPUNodeStack *outputs = get_outputs_array();
+
+ const float hue_epsilon = get_hue_epsilon();
+ const float saturation_epsilon = get_saturation_epsilon();
+ const float value_epsilon = get_value_epsilon();
+
+ GPU_stack_link(material,
+ &bnode(),
+ "node_composite_color_matte",
+ inputs,
+ outputs,
+ GPU_uniform(&hue_epsilon),
+ GPU_uniform(&saturation_epsilon),
+ GPU_uniform(&value_epsilon));
+ }
+
+ NodeChroma *get_node_chroma()
+ {
+ return static_cast<NodeChroma *>(bnode().storage);
+ }
+
+ float get_hue_epsilon()
+ {
+ /* Divide by 2 because the hue wraps around. */
+ return get_node_chroma()->t1 / 2.0f;
+ }
+
+ float get_saturation_epsilon()
+ {
+ return get_node_chroma()->t2;
+ }
+
+ float get_value_epsilon()
+ {
+ return get_node_chroma()->t3;
+ }
+};
+
+static ShaderNode *get_compositor_shader_node(DNode node)
+{
+ return new ColorMatteShaderNode(node);
+}
+
} // namespace blender::nodes::node_composite_color_matte_cc
void register_node_type_cmp_color_matte()
@@ -64,6 +124,7 @@ void register_node_type_cmp_color_matte()
ntype.flag |= NODE_PREVIEW;
node_type_init(&ntype, file_ns::node_composit_init_color_matte);
node_type_storage(&ntype, "NodeChroma", node_free_standard_storage, node_copy_standard_storage);
+ ntype.get_compositor_shader_node = file_ns::get_compositor_shader_node;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_color_spill.cc b/source/blender/nodes/composite/nodes/node_composite_color_spill.cc
index 9ad5dfbaeb2..9744c01a256 100644
--- a/source/blender/nodes/composite/nodes/node_composite_color_spill.cc
+++ b/source/blender/nodes/composite/nodes/node_composite_color_spill.cc
@@ -10,6 +10,10 @@
#include "UI_interface.h"
#include "UI_resources.h"
+#include "GPU_material.h"
+
+#include "COM_shader_node.hh"
+
#include "node_composite_util.hh"
/* ******************* Color Spill Suppression ********************************* */
@@ -18,8 +22,15 @@ namespace blender::nodes::node_composite_color_spill_cc {
static void cmp_node_color_spill_declare(NodeDeclarationBuilder &b)
{
- b.add_input<decl::Color>(N_("Image")).default_value({1.0f, 1.0f, 1.0f, 1.0f});
- b.add_input<decl::Float>(N_("Fac")).default_value(1.0f).min(0.0f).max(1.0f).subtype(PROP_FACTOR);
+ b.add_input<decl::Color>(N_("Image"))
+ .default_value({1.0f, 1.0f, 1.0f, 1.0f})
+ .compositor_domain_priority(0);
+ b.add_input<decl::Float>(N_("Fac"))
+ .default_value(1.0f)
+ .min(0.0f)
+ .max(1.0f)
+ .subtype(PROP_FACTOR)
+ .compositor_domain_priority(1);
b.add_output<decl::Color>(N_("Image"));
}
@@ -27,8 +38,8 @@ static void node_composit_init_color_spill(bNodeTree *UNUSED(ntree), bNode *node
{
NodeColorspill *ncs = MEM_cnew<NodeColorspill>(__func__);
node->storage = ncs;
+ node->custom2 = CMP_NODE_COLOR_SPILL_LIMIT_ALGORITHM_SINGLE;
node->custom1 = 2; /* green channel */
- node->custom2 = 0; /* simple limit algorithm */
ncs->limchan = 0; /* limit by red */
ncs->limscale = 1.0f; /* limit scaling factor */
ncs->unspill = 0; /* do not use unspill */
@@ -80,6 +91,103 @@ static void node_composit_buts_color_spill(uiLayout *layout, bContext *UNUSED(C)
}
}
+using namespace blender::realtime_compositor;
+
+class ColorSpillShaderNode : public ShaderNode {
+ public:
+ using ShaderNode::ShaderNode;
+
+ void compile(GPUMaterial *material) override
+ {
+ GPUNodeStack *inputs = get_inputs_array();
+ GPUNodeStack *outputs = get_outputs_array();
+
+ const float spill_channel = get_spill_channel();
+ float spill_scale[3];
+ get_spill_scale(spill_scale);
+ float limit_channels[2];
+ get_limit_channels(limit_channels);
+ const float limit_scale = get_limit_scale();
+
+ GPU_stack_link(material,
+ &bnode(),
+ "node_composite_color_spill",
+ inputs,
+ outputs,
+ GPU_constant(&spill_channel),
+ GPU_uniform(spill_scale),
+ GPU_constant(limit_channels),
+ GPU_uniform(&limit_scale));
+ }
+
+ /* Get the index of the channel used for spilling. */
+ int get_spill_channel()
+ {
+ return bnode().custom1 - 1;
+ }
+
+ CMPNodeColorSpillLimitAlgorithm get_limit_algorithm()
+ {
+ return (CMPNodeColorSpillLimitAlgorithm)bnode().custom2;
+ }
+
+ NodeColorspill *get_node_color_spill()
+ {
+ return static_cast<NodeColorspill *>(bnode().storage);
+ }
+
+ void get_spill_scale(float spill_scale[3])
+ {
+ const NodeColorspill *node_color_spill = get_node_color_spill();
+ if (node_color_spill->unspill) {
+ spill_scale[0] = node_color_spill->uspillr;
+ spill_scale[1] = node_color_spill->uspillg;
+ spill_scale[2] = node_color_spill->uspillb;
+ spill_scale[get_spill_channel()] *= -1.0f;
+ }
+ else {
+ spill_scale[0] = 0.0f;
+ spill_scale[1] = 0.0f;
+ spill_scale[2] = 0.0f;
+ spill_scale[get_spill_channel()] = -1.0f;
+ }
+ }
+
+ /* Get the index of the channel used for limiting. */
+ int get_limit_channel()
+ {
+ return get_node_color_spill()->limchan;
+ }
+
+ /* Get the indices of the channels used to compute the limit value. We always assume the limit
+ * algorithm is Average, if it is a single limit channel, store it in both limit channels,
+ * because the average of two identical values is the same value. */
+ void get_limit_channels(float limit_channels[2])
+ {
+ if (get_limit_algorithm() == CMP_NODE_COLOR_SPILL_LIMIT_ALGORITHM_AVERAGE) {
+ /* If the algorithm is Average, store the indices of the other two channels other than the
+ * spill channel. */
+ limit_channels[0] = (get_spill_channel() + 1) % 3;
+ limit_channels[1] = (get_spill_channel() + 2) % 3;
+ }
+ else {
+ /* If the algorithm is Single, store the index of the limit channel in both channels. */
+ limit_channels[0] = get_limit_channel();
+ limit_channels[1] = get_limit_channel();
+ }
+ }
+
+ float get_limit_scale()
+ {
+ return get_node_color_spill()->limscale;
+ }
+};
+
+static ShaderNode *get_compositor_shader_node(DNode node)
+{
+ return new ColorSpillShaderNode(node);
+}
+
} // namespace blender::nodes::node_composite_color_spill_cc
void register_node_type_cmp_color_spill()
@@ -94,6 +202,7 @@ void register_node_type_cmp_color_spill()
node_type_init(&ntype, file_ns::node_composit_init_color_spill);
node_type_storage(
&ntype, "NodeColorspill", node_free_standard_storage, node_copy_standard_storage);
+ ntype.get_compositor_shader_node = file_ns::get_compositor_shader_node;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_diff_matte.cc b/source/blender/nodes/composite/nodes/node_composite_diff_matte.cc
index b87bbe439db..e129dcaa6ef 100644
--- a/source/blender/nodes/composite/nodes/node_composite_diff_matte.cc
+++ b/source/blender/nodes/composite/nodes/node_composite_diff_matte.cc
@@ -8,6 +8,10 @@
#include "UI_interface.h"
#include "UI_resources.h"
+#include "GPU_material.h"
+
+#include "COM_shader_node.hh"
+
#include "node_composite_util.hh"
/* ******************* channel Difference Matte ********************************* */
@@ -16,8 +20,12 @@ namespace blender::nodes::node_composite_diff_matte_cc {
static void cmp_node_diff_matte_declare(NodeDeclarationBuilder &b)
{
- b.add_input<decl::Color>(N_("Image 1")).default_value({1.0f, 1.0f, 1.0f, 1.0f});
- b.add_input<decl::Color>(N_("Image 2")).default_value({1.0f, 1.0f, 1.0f, 1.0f});
+ b.add_input<decl::Color>(N_("Image 1"))
+ .default_value({1.0f, 1.0f, 1.0f, 1.0f})
+ .compositor_domain_priority(0);
+ b.add_input<decl::Color>(N_("Image 2"))
+ .default_value({1.0f, 1.0f, 1.0f, 1.0f})
+ .compositor_domain_priority(1);
b.add_output<decl::Color>(N_("Image"));
b.add_output<decl::Float>(N_("Matte"));
}
@@ -40,6 +48,50 @@ static void node_composit_buts_diff_matte(uiLayout *layout, bContext *UNUSED(C),
uiItemR(col, ptr, "falloff", UI_ITEM_R_SPLIT_EMPTY_NAME | UI_ITEM_R_SLIDER, nullptr, ICON_NONE);
}
+using namespace blender::realtime_compositor;
+
+class DifferenceMatteShaderNode : public ShaderNode {
+ public:
+ using ShaderNode::ShaderNode;
+
+ void compile(GPUMaterial *material) override
+ {
+ GPUNodeStack *inputs = get_inputs_array();
+ GPUNodeStack *outputs = get_outputs_array();
+
+ const float tolerance = get_tolerance();
+ const float falloff = get_falloff();
+
+ GPU_stack_link(material,
+ &bnode(),
+ "node_composite_difference_matte",
+ inputs,
+ outputs,
+ GPU_uniform(&tolerance),
+ GPU_uniform(&falloff));
+ }
+
+ NodeChroma *get_node_chroma()
+ {
+ return static_cast<NodeChroma *>(bnode().storage);
+ }
+
+ float get_tolerance()
+ {
+ return get_node_chroma()->t1;
+ }
+
+ float get_falloff()
+ {
+ return get_node_chroma()->t2;
+ }
+};
+
+static ShaderNode *get_compositor_shader_node(DNode node)
+{
+ return new DifferenceMatteShaderNode(node);
+}
+
} // namespace blender::nodes::node_composite_diff_matte_cc
void register_node_type_cmp_diff_matte()
@@ -54,6 +106,7 @@ void register_node_type_cmp_diff_matte()
ntype.flag |= NODE_PREVIEW;
node_type_init(&ntype, file_ns::node_composit_init_diff_matte);
node_type_storage(&ntype, "NodeChroma", node_free_standard_storage, node_copy_standard_storage);
+ ntype.get_compositor_shader_node = file_ns::get_compositor_shader_node;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_distance_matte.cc b/source/blender/nodes/composite/nodes/node_composite_distance_matte.cc
index a8646d8498e..9d910b3f409 100644
--- a/source/blender/nodes/composite/nodes/node_composite_distance_matte.cc
+++ b/source/blender/nodes/composite/nodes/node_composite_distance_matte.cc
@@ -8,6 +8,10 @@
#include "UI_interface.h"
#include "UI_resources.h"
+#include "GPU_material.h"
+
+#include "COM_shader_node.hh"
+
#include "node_composite_util.hh"
/* ******************* channel Distance Matte ********************************* */
@@ -16,8 +20,12 @@ namespace blender::nodes::node_composite_distance_matte_cc {
static void cmp_node_distance_matte_declare(NodeDeclarationBuilder &b)
{
- b.add_input<decl::Color>(N_("Image")).default_value({1.0f, 1.0f, 1.0f, 1.0f});
- b.add_input<decl::Color>(N_("Key Color")).default_value({1.0f, 1.0f, 1.0f, 1.0f});
+ b.add_input<decl::Color>(N_("Image"))
+ .default_value({1.0f, 1.0f, 1.0f, 1.0f})
+ .compositor_domain_priority(0);
+ b.add_input<decl::Color>(N_("Key Color"))
+ .default_value({1.0f, 1.0f, 1.0f, 1.0f})
+ .compositor_domain_priority(1);
b.add_output<decl::Color>(N_("Image"));
b.add_output<decl::Float>(N_("Matte"));
}
@@ -26,7 +34,7 @@ static void node_composit_init_distance_matte(bNodeTree *UNUSED(ntree), bNode *n
{
NodeChroma *c = MEM_cnew<NodeChroma>(__func__);
node->storage = c;
- c->channel = 1;
+ c->channel = CMP_NODE_DISTANCE_MATTE_COLOR_SPACE_RGBA;
c->t1 = 0.1f;
c->t2 = 0.1f;
}
@@ -48,6 +56,66 @@ static void node_composit_buts_distance_matte(uiLayout *layout,
uiItemR(col, ptr, "falloff", UI_ITEM_R_SPLIT_EMPTY_NAME | UI_ITEM_R_SLIDER, nullptr, ICON_NONE);
}
+using namespace blender::realtime_compositor;
+
+class DistanceMatteShaderNode : public ShaderNode {
+ public:
+ using ShaderNode::ShaderNode;
+
+ void compile(GPUMaterial *material) override
+ {
+ GPUNodeStack *inputs = get_inputs_array();
+ GPUNodeStack *outputs = get_outputs_array();
+
+ const float tolerance = get_tolerance();
+ const float falloff = get_falloff();
+
+ if (get_color_space() == CMP_NODE_DISTANCE_MATTE_COLOR_SPACE_RGBA) {
+ GPU_stack_link(material,
+ &bnode(),
+ "node_composite_distance_matte_rgba",
+ inputs,
+ outputs,
+ GPU_uniform(&tolerance),
+ GPU_uniform(&falloff));
+ return;
+ }
+
+ GPU_stack_link(material,
+ &bnode(),
+ "node_composite_distance_matte_ycca",
+ inputs,
+ outputs,
+ GPU_uniform(&tolerance),
+ GPU_uniform(&falloff));
+ }
+
+ NodeChroma *get_node_chroma()
+ {
+ return static_cast<NodeChroma *>(bnode().storage);
+ }
+
+ CMPNodeDistanceMatteColorSpace get_color_space()
+ {
+ return (CMPNodeDistanceMatteColorSpace)get_node_chroma()->channel;
+ }
+
+ float get_tolerance()
+ {
+ return get_node_chroma()->t1;
+ }
+
+ float get_falloff()
+ {
+ return get_node_chroma()->t2;
+ }
+};
+
+static ShaderNode *get_compositor_shader_node(DNode node)
+{
+ return new DistanceMatteShaderNode(node);
+}
+
} // namespace blender::nodes::node_composite_distance_matte_cc
void register_node_type_cmp_distance_matte()
@@ -62,6 +130,7 @@ void register_node_type_cmp_distance_matte()
ntype.flag |= NODE_PREVIEW;
node_type_init(&ntype, file_ns::node_composit_init_distance_matte);
node_type_storage(&ntype, "NodeChroma", node_free_standard_storage, node_copy_standard_storage);
+ ntype.get_compositor_shader_node = file_ns::get_compositor_shader_node;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_ellipsemask.cc b/source/blender/nodes/composite/nodes/node_composite_ellipsemask.cc
index 4da6a0a442e..54dfa00eadd 100644
--- a/source/blender/nodes/composite/nodes/node_composite_ellipsemask.cc
+++ b/source/blender/nodes/composite/nodes/node_composite_ellipsemask.cc
@@ -5,9 +5,18 @@
* \ingroup cmpnodes
*/
+#include <cmath>
+
+#include "BLI_math_vec_types.hh"
+
#include "UI_interface.h"
#include "UI_resources.h"
+#include "GPU_shader.h"
+
+#include "COM_node_operation.hh"
+#include "COM_utilities.hh"
+
#include "node_composite_util.hh"
/* **************** SCALAR MATH ******************** */
@@ -46,6 +55,98 @@ static void node_composit_buts_ellipsemask(uiLayout *layout, bContext *UNUSED(C)
uiItemR(layout, ptr, "mask_type", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
}
+using namespace blender::realtime_compositor;
+
+class EllipseMaskOperation : public NodeOperation {
+ public:
+ using NodeOperation::NodeOperation;
+
+ void execute() override
+ {
+ GPUShader *shader = shader_manager().get(get_shader_name());
+ GPU_shader_bind(shader);
+
+ const Domain domain = compute_domain();
+
+ GPU_shader_uniform_2iv(shader, "domain_size", domain.size);
+
+ GPU_shader_uniform_2fv(shader, "location", get_location());
+ GPU_shader_uniform_2fv(shader, "radius", get_size() / 2.0f);
+ GPU_shader_uniform_1f(shader, "cos_angle", std::cos(get_angle()));
+ GPU_shader_uniform_1f(shader, "sin_angle", std::sin(get_angle()));
+
+ const Result &input_mask = get_input("Mask");
+ input_mask.bind_as_texture(shader, "base_mask_tx");
+
+ const Result &value = get_input("Value");
+ value.bind_as_texture(shader, "mask_value_tx");
+
+ Result &output_mask = get_result("Mask");
+ output_mask.allocate_texture(domain);
+ output_mask.bind_as_image(shader, "output_mask_img");
+
+ compute_dispatch_threads_at_least(shader, domain.size);
+
+ input_mask.unbind_as_texture();
+ value.unbind_as_texture();
+ output_mask.unbind_as_image();
+ GPU_shader_unbind();
+ }
+
+ Domain compute_domain() override
+ {
+ if (get_input("Mask").is_single_value()) {
+ return Domain(context().get_output_size());
+ }
+ return get_input("Mask").domain();
+ }
+
+ CMPNodeMaskType get_mask_type()
+ {
+ return (CMPNodeMaskType)bnode().custom1;
+ }
+
+ const char *get_shader_name()
+ {
+ switch (get_mask_type()) {
+ default:
+ case CMP_NODE_MASKTYPE_ADD:
+ return "compositor_ellipse_mask_add";
+ case CMP_NODE_MASKTYPE_SUBTRACT:
+ return "compositor_ellipse_mask_subtract";
+ case CMP_NODE_MASKTYPE_MULTIPLY:
+ return "compositor_ellipse_mask_multiply";
+ case CMP_NODE_MASKTYPE_NOT:
+ return "compositor_ellipse_mask_not";
+ }
+ }
+
+ NodeEllipseMask &get_node_ellipse_mask()
+ {
+ return *static_cast<NodeEllipseMask *>(bnode().storage);
+ }
+
+ float2 get_location()
+ {
+ return float2(get_node_ellipse_mask().x, get_node_ellipse_mask().y);
+ }
+
+ float2 get_size()
+ {
+ return float2(get_node_ellipse_mask().width, get_node_ellipse_mask().height);
+ }
+
+ float get_angle()
+ {
+ return get_node_ellipse_mask().rotation;
+ }
+};
+
+static NodeOperation *get_compositor_operation(Context &context, DNode node)
+{
+ return new EllipseMaskOperation(context, node);
+}
+
} // namespace blender::nodes::node_composite_ellipsemask_cc
void register_node_type_cmp_ellipsemask()
@@ -61,6 +162,7 @@ void register_node_type_cmp_ellipsemask()
node_type_init(&ntype, file_ns::node_composit_init_ellipsemask);
node_type_storage(
&ntype, "NodeEllipseMask", node_free_standard_storage, node_copy_standard_storage);
+ ntype.get_compositor_operation = file_ns::get_compositor_operation;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_luma_matte.cc b/source/blender/nodes/composite/nodes/node_composite_luma_matte.cc
index 94697a2aafd..092a12a7ea4 100644
--- a/source/blender/nodes/composite/nodes/node_composite_luma_matte.cc
+++ b/source/blender/nodes/composite/nodes/node_composite_luma_matte.cc
@@ -5,9 +5,15 @@
* \ingroup cmpnodes
*/
+#include "IMB_colormanagement.h"
+
#include "UI_interface.h"
#include "UI_resources.h"
+#include "GPU_material.h"
+
+#include "COM_shader_node.hh"
+
#include "node_composite_util.hh"
/* ******************* Luma Matte Node ********************************* */
@@ -16,7 +22,9 @@ namespace blender::nodes::node_composite_luma_matte_cc {
static void cmp_node_luma_matte_declare(NodeDeclarationBuilder &b)
{
- b.add_input<decl::Color>(N_("Image")).default_value({1.0f, 1.0f, 1.0f, 1.0f});
+ b.add_input<decl::Color>(N_("Image"))
+ .default_value({1.0f, 1.0f, 1.0f, 1.0f})
+ .compositor_domain_priority(0);
b.add_output<decl::Color>(N_("Image"));
b.add_output<decl::Float>(N_("Matte"));
}
@@ -40,6 +48,53 @@ static void node_composit_buts_luma_matte(uiLayout *layout, bContext *UNUSED(C),
col, ptr, "limit_min", UI_ITEM_R_SPLIT_EMPTY_NAME | UI_ITEM_R_SLIDER, nullptr, ICON_NONE);
}
+using namespace blender::realtime_compositor;
+
+class LuminanceMatteShaderNode : public ShaderNode {
+ public:
+ using ShaderNode::ShaderNode;
+
+ void compile(GPUMaterial *material) override
+ {
+ GPUNodeStack *inputs = get_inputs_array();
+ GPUNodeStack *outputs = get_outputs_array();
+
+ const float high = get_high();
+ const float low = get_low();
+ float luminance_coefficients[3];
+ IMB_colormanagement_get_luminance_coefficients(luminance_coefficients);
+
+ GPU_stack_link(material,
+ &bnode(),
+ "node_composite_luminance_matte",
+ inputs,
+ outputs,
+ GPU_uniform(&high),
+ GPU_uniform(&low),
+ GPU_constant(luminance_coefficients));
+ }
+
+ NodeChroma *get_node_chroma()
+ {
+ return static_cast<NodeChroma *>(bnode().storage);
+ }
+
+ float get_high()
+ {
+ return get_node_chroma()->t1;
+ }
+
+ float get_low()
+ {
+ return get_node_chroma()->t2;
+ }
+};
+
+static ShaderNode *get_compositor_shader_node(DNode node)
+{
+ return new LuminanceMatteShaderNode(node);
+}
+
} // namespace blender::nodes::node_composite_luma_matte_cc
void register_node_type_cmp_luma_matte()
@@ -54,6 +109,7 @@ void register_node_type_cmp_luma_matte()
ntype.flag |= NODE_PREVIEW;
node_type_init(&ntype, file_ns::node_composit_init_luma_matte);
node_type_storage(&ntype, "NodeChroma", node_free_standard_storage, node_copy_standard_storage);
+ ntype.get_compositor_shader_node = file_ns::get_compositor_shader_node;
nodeRegisterType(&ntype);
}