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/nodes/composite/nodes/node_composite_composite.cc')
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_composite.cc129
1 files changed, 129 insertions, 0 deletions
diff --git a/source/blender/nodes/composite/nodes/node_composite_composite.cc b/source/blender/nodes/composite/nodes/node_composite_composite.cc
index d35ce7dc11a..68061bb434d 100644
--- a/source/blender/nodes/composite/nodes/node_composite_composite.cc
+++ b/source/blender/nodes/composite/nodes/node_composite_composite.cc
@@ -5,9 +5,18 @@
* \ingroup cmpnodes
*/
+#include "BLI_math_vec_types.hh"
+
#include "UI_interface.h"
#include "UI_resources.h"
+#include "GPU_shader.h"
+#include "GPU_state.h"
+#include "GPU_texture.h"
+
+#include "COM_node_operation.hh"
+#include "COM_utilities.hh"
+
#include "node_composite_util.hh"
/* **************** COMPOSITE ******************** */
@@ -26,6 +35,125 @@ static void node_composit_buts_composite(uiLayout *layout, bContext *UNUSED(C),
uiItemR(layout, ptr, "use_alpha", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
}
+using namespace blender::realtime_compositor;
+
+class CompositeOperation : public NodeOperation {
+ public:
+ using NodeOperation::NodeOperation;
+
+ void execute() override
+ {
+ const Result &image = get_input("Image");
+ const Result &alpha = get_input("Alpha");
+
+ if (image.is_single_value() && alpha.is_single_value()) {
+ execute_clear();
+ }
+ else if (ignore_alpha()) {
+ execute_ignore_alpha();
+ }
+ else if (!node().input_by_identifier("Alpha")->is_logically_linked()) {
+ execute_copy();
+ }
+ else {
+ execute_set_alpha();
+ }
+ }
+
+ /* Executes when all inputs are single values, in which case, the output texture can just be
+ * cleared to the appropriate color. */
+ void execute_clear()
+ {
+ const Result &image = get_input("Image");
+ const Result &alpha = get_input("Alpha");
+
+ float4 color = image.get_color_value();
+ if (ignore_alpha()) {
+ color.w = 1.0f;
+ }
+ else if (node().input_by_identifier("Alpha")->is_logically_linked()) {
+ color.w = alpha.get_float_value();
+ }
+
+ GPU_texture_clear(context().get_output_texture(), GPU_DATA_FLOAT, color);
+ }
+
+ /* Executes when the alpha channel of the image is ignored. */
+ void execute_ignore_alpha()
+ {
+ GPUShader *shader = shader_manager().get("compositor_convert_color_to_opaque");
+ GPU_shader_bind(shader);
+
+ const Result &image = get_input("Image");
+ image.bind_as_texture(shader, "input_tx");
+
+ GPUTexture *output_texture = context().get_output_texture();
+ const int image_unit = GPU_shader_get_texture_binding(shader, "output_img");
+ GPU_texture_image_bind(output_texture, image_unit);
+
+ compute_dispatch_threads_at_least(shader, compute_domain().size);
+
+ image.unbind_as_texture();
+ GPU_texture_image_unbind(output_texture);
+ GPU_shader_unbind();
+ }
+
+ /* Executes when the image texture is written with no adjustments and can thus be copied directly
+ * to the output texture. */
+ void execute_copy()
+ {
+ const Result &image = get_input("Image");
+
+ /* Make sure any prior writes to the texture are reflected before copying it. */
+ GPU_memory_barrier(GPU_BARRIER_TEXTURE_UPDATE);
+
+ GPU_texture_copy(context().get_output_texture(), image.texture());
+ }
+
+ /* Executes when the alpha channel of the image is set as the value of the input alpha. */
+ void execute_set_alpha()
+ {
+ GPUShader *shader = shader_manager().get("compositor_set_alpha");
+ GPU_shader_bind(shader);
+
+ const Result &image = get_input("Image");
+ image.bind_as_texture(shader, "image_tx");
+
+ const Result &alpha = get_input("Alpha");
+ alpha.bind_as_texture(shader, "alpha_tx");
+
+ GPUTexture *output_texture = context().get_output_texture();
+ const int image_unit = GPU_shader_get_texture_binding(shader, "output_img");
+ GPU_texture_image_bind(output_texture, image_unit);
+
+ compute_dispatch_threads_at_least(shader, compute_domain().size);
+
+ image.unbind_as_texture();
+ alpha.unbind_as_texture();
+ GPU_texture_image_unbind(output_texture);
+ GPU_shader_unbind();
+ }
+
+ /* If true, the alpha channel of the image is set to 1, that is, it becomes opaque. If false, the
+ * alpha channel of the image is retained, but only if the alpha input is not linked. If the
+ * alpha input is linked, it the value of that input will be used as the alpha of the image. */
+ bool ignore_alpha()
+ {
+ return bnode().custom2 & CMP_NODE_OUTPUT_IGNORE_ALPHA;
+ }
+
+ /* The operation domain have the same dimensions of the output without any transformations. */
+ Domain compute_domain() override
+ {
+ return Domain(context().get_output_size());
+ }
+};
+
+static NodeOperation *get_compositor_operation(Context &context, DNode node)
+{
+ return new CompositeOperation(context, node);
+}
+
} // namespace blender::nodes::node_composite_composite_cc
void register_node_type_cmp_composite()
@@ -37,6 +165,7 @@ void register_node_type_cmp_composite()
cmp_node_type_base(&ntype, CMP_NODE_COMPOSITE, "Composite", NODE_CLASS_OUTPUT);
ntype.declare = file_ns::cmp_node_composite_declare;
ntype.draw_buttons = file_ns::node_composit_buts_composite;
+ ntype.get_compositor_operation = file_ns::get_compositor_operation;
ntype.flag |= NODE_PREVIEW;
ntype.no_muting = true;