[Bf-blender-cvs] [2cbfeca07e3] temp-viewport-compositor-compiler: Viewport Compositor: Implement Crop node

Omar Emara noreply at git.blender.org
Fri Apr 1 13:24:53 CEST 2022


Commit: 2cbfeca07e30ec6ecc135cf41c4a71c51a2659fb
Author: Omar Emara
Date:   Fri Apr 1 13:14:08 2022 +0200
Branches: temp-viewport-compositor-compiler
https://developer.blender.org/rB2cbfeca07e30ec6ecc135cf41c4a71c51a2659fb

Viewport Compositor: Implement Crop node

===================================================================

M	source/blender/gpu/CMakeLists.txt
A	source/blender/gpu/shaders/compositor/compositor_alpha_crop.glsl
A	source/blender/gpu/shaders/compositor/compositor_image_crop.glsl
A	source/blender/gpu/shaders/compositor/infos/compositor_alpha_crop_info.hh
A	source/blender/gpu/shaders/compositor/infos/compositor_image_crop_info.hh
M	source/blender/nodes/composite/nodes/node_composite_crop.cc

===================================================================

diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 469ea3ea037..68a6b5d22c1 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -309,8 +309,10 @@ set(GLSL_SRC
   shaders/compositor/material/gpu_shader_compositor_texture_utils.glsl
   shaders/compositor/material/gpu_shader_compositor_type_conversion.glsl
 
+  shaders/compositor/compositor_alpha_crop.glsl
   shaders/compositor/compositor_convert.glsl
   shaders/compositor/compositor_filter.glsl
+  shaders/compositor/compositor_image_crop.glsl
   shaders/compositor/compositor_realize_on_domain.glsl
   shaders/compositor/compositor_split_viewer.glsl
 
@@ -495,8 +497,10 @@ set(SHADER_CREATE_INFOS
   shaders/infos/gpu_shader_text_info.hh
   shaders/infos/gpu_srgb_to_framebuffer_space_info.hh
 
+  shaders/compositor/infos/compositor_alpha_crop_info.hh
   shaders/compositor/infos/compositor_convert_info.hh
   shaders/compositor/infos/compositor_filter_info.hh
+  shaders/compositor/infos/compositor_image_crop_info.hh
   shaders/compositor/infos/compositor_realize_on_domain_info.hh
   shaders/compositor/infos/compositor_split_viewer_info.hh
 )
diff --git a/source/blender/gpu/shaders/compositor/compositor_alpha_crop.glsl b/source/blender/gpu/shaders/compositor/compositor_alpha_crop.glsl
new file mode 100644
index 00000000000..344d34b30d4
--- /dev/null
+++ b/source/blender/gpu/shaders/compositor/compositor_alpha_crop.glsl
@@ -0,0 +1,10 @@
+#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utils.glsl)
+
+void main()
+{
+  ivec2 xy = ivec2(gl_GlobalInvocationID.xy);
+  /* Write the pixel color if it is inside the cropping region, otherwise, write zero. */
+  bool is_inside = all(greaterThan(xy, lower_bound)) && all(lessThan(xy, higher_bound));
+  vec4 color = is_inside ? texture_load(input_image, xy) : vec4(0.0);
+  imageStore(output_image, xy, color);
+}
diff --git a/source/blender/gpu/shaders/compositor/compositor_image_crop.glsl b/source/blender/gpu/shaders/compositor/compositor_image_crop.glsl
new file mode 100644
index 00000000000..fe2c2818ba3
--- /dev/null
+++ b/source/blender/gpu/shaders/compositor/compositor_image_crop.glsl
@@ -0,0 +1,7 @@
+#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utils.glsl)
+
+void main()
+{
+  ivec2 xy = ivec2(gl_GlobalInvocationID.xy);
+  imageStore(output_image, xy, texture_load(input_image, xy + lower_bound));
+}
diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_alpha_crop_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_alpha_crop_info.hh
new file mode 100644
index 00000000000..0f0be5f95bb
--- /dev/null
+++ b/source/blender/gpu/shaders/compositor/infos/compositor_alpha_crop_info.hh
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+#include "gpu_shader_create_info.hh"
+
+GPU_SHADER_CREATE_INFO(compositor_alpha_crop)
+    .local_group_size(16, 16)
+    .push_constant(Type::IVEC2, "lower_bound")
+    .push_constant(Type::IVEC2, "higher_bound")
+    .sampler(0, ImageType::FLOAT_2D, "input_image")
+    .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_image")
+    .compute_source("compositor_alpha_crop.glsl")
+    .do_static_compilation(true);
diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_image_crop_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_image_crop_info.hh
new file mode 100644
index 00000000000..381075a8944
--- /dev/null
+++ b/source/blender/gpu/shaders/compositor/infos/compositor_image_crop_info.hh
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+#include "gpu_shader_create_info.hh"
+
+GPU_SHADER_CREATE_INFO(compositor_image_crop)
+    .local_group_size(16, 16)
+    .push_constant(Type::IVEC2, "lower_bound")
+    .sampler(0, ImageType::FLOAT_2D, "input_image")
+    .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_image")
+    .compute_source("compositor_image_crop.glsl")
+    .do_static_compilation(true);
diff --git a/source/blender/nodes/composite/nodes/node_composite_crop.cc b/source/blender/nodes/composite/nodes/node_composite_crop.cc
index e14b7d04ea6..6d978389cfb 100644
--- a/source/blender/nodes/composite/nodes/node_composite_crop.cc
+++ b/source/blender/nodes/composite/nodes/node_composite_crop.cc
@@ -21,11 +21,22 @@
  * \ingroup cmpnodes
  */
 
+#include "BLI_math_base.h"
+#include "BLI_math_vec_types.hh"
+
+#include "DNA_node_types.h"
+
 #include "RNA_access.h"
 
 #include "UI_interface.h"
 #include "UI_resources.h"
 
+#include "GPU_compute.h"
+#include "GPU_shader.h"
+#include "GPU_texture.h"
+
+#include "NOD_compositor_execute.hh"
+
 #include "node_composite_util.hh"
 
 /* **************** Crop  ******************** */
@@ -34,7 +45,9 @@ namespace blender::nodes::node_composite_crop_cc {
 
 static void cmp_node_crop_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"));
 }
 
@@ -70,6 +83,162 @@ static void node_composit_buts_crop(uiLayout *layout, bContext *UNUSED(C), Point
   }
 }
 
+using namespace blender::viewport_compositor;
+
+class CropOperation : public NodeOperation {
+ public:
+  using NodeOperation::NodeOperation;
+
+  void execute() override
+  {
+    /* The operation does nothing, so just pass the input through. */
+    if (is_identity()) {
+      get_input("Image").pass_through(get_result("Image"));
+    }
+
+    if (get_is_image_crop()) {
+      execute_image_crop();
+    }
+    else {
+      execute_alpha_crop();
+    }
+  }
+
+  /* Crop by replacing areas outside of the cropping bounds with zero alpha. The output have the
+   * same domain as the input image. */
+  void execute_alpha_crop()
+  {
+    GPUShader *shader = GPU_shader_create_from_info_name("compositor_alpha_crop");
+    GPU_shader_bind(shader);
+
+    int2 lower_bound, higher_bound;
+    compute_cropping_bounds(lower_bound, higher_bound);
+    GPU_shader_uniform_2iv(shader, "lower_bound", lower_bound);
+    GPU_shader_uniform_2iv(shader, "higher_bound", higher_bound);
+
+    const Result &input_image = get_input("Image");
+    input_image.bind_as_texture(shader, "input_image");
+
+    Result &output_image = get_result("Image");
+    output_image.allocate_texture(compute_domain());
+    output_image.bind_as_image(shader, "output_image");
+
+    const int2 size = compute_domain().size;
+    GPU_compute_dispatch(shader, size.x / 16 + 1, size.y / 16 + 1, 1);
+
+    input_image.unbind_as_texture();
+    output_image.unbind_as_image();
+    GPU_shader_unbind();
+    GPU_shader_free(shader);
+  }
+
+  /* Crop the image into a new size that matches the cropping bounds. */
+  void execute_image_crop()
+  {
+    int2 lower_bound, higher_bound;
+    compute_cropping_bounds(lower_bound, higher_bound);
+
+    /* The image is cropped into nothing, so just return a single zero value. */
+    if (lower_bound.x == higher_bound.x || lower_bound.y == higher_bound.y) {
+      Result &result = get_result("Image");
+      result.allocate_single_value();
+      result.set_color_value(float4(0.0f));
+      return;
+    }
+
+    GPUShader *shader = GPU_shader_create_from_info_name("compositor_image_crop");
+    GPU_shader_bind(shader);
+
+    GPU_shader_uniform_2iv(shader, "lower_bound", lower_bound);
+
+    const Result &input_image = get_input("Image");
+    input_image.bind_as_texture(shader, "input_image");
+
+    const int2 size = higher_bound - lower_bound;
+
+    Result &output_image = get_result("Image");
+    output_image.allocate_texture(Domain(size, compute_domain().transformation));
+    output_image.bind_as_image(shader, "output_image");
+
+    GPU_compute_dispatch(shader, size.x / 16 + 1, size.y / 16 + 1, 1);
+
+    input_image.unbind_as_texture();
+    output_image.unbind_as_image();
+    GPU_shader_unbind();
+    GPU_shader_free(shader);
+  }
+
+  /* If true, the image should actually be cropped into a new size. Otherwise, if false, the region
+   * outside of the cropping bounds will be set to a zero alpha value. */
+  bool get_is_image_crop()
+  {
+    return node().custom1;
+  }
+
+  bool get_is_relative()
+  {
+    return node().custom2;
+  }
+
+  NodeTwoXYs &get_node_two_xys()
+  {
+    return *static_cast<NodeTwoXYs *>(node().storage);
+  }
+
+  /* Returns true if the operation does nothing and the input can be passed through. */
+  bool is_identity()
+  {
+    const Result &input = get_input("Image");
+    /* Single value inputs can't be cropped and are returned as is. */
+    if (input.is_single_value()) {
+      return true;
+    }
+
+    int2 lower_bound, higher_bound;
+    compute_cropping_bounds(lower_bound, higher_bound);
+    const int2 input_size = input.domain().size;
+    /* The cropping bounds cover the whole image, so no cropping happens. */
+    if (lower_bound == int2(0) && higher_bound == input_size) {
+      return true;
+    }
+
+    return false;
+  }
+
+  void compute_cropping_bounds(int2 &lower_bound, int2 &higher_bound)
+  {
+    const NodeTwoXYs &node_two_xys = get_node_two_xys();
+    const int2 input_size = get_input("Image").domain().size;
+
+    if (get_is_relative()) {
+      /* The cropping bounds are relative to the image size. The factors are in the [0, 1] range,
+       * so it is guaranteed that they won't go over the input image size. */
+      lower_bound.x = input_size.x * node_two_xys.fac_x1;
+      lower_bound.y = input_size.y * node_two_xys.fac_y2;
+      higher_bound.x = input_size.x * node_two_xys.fac_x2;
+      higher_bound.y = input_size.y * node_two_xys.fac_y1;
+    }
+    else {
+      /* Make sure the bounds don't go over the input image size. */
+      lower_bound.x = min_ii(node_two_xys.x1, input_size.x);
+      lower_bound.y = min_ii(node_two_xys.y2, input_size.y);
+      higher_bound.x = min_ii(node_two_xys.x2, input_size.x);
+      higher_bound.y = min_ii(node_two_xys.y1, input_size.y);
+    }
+
+    /* Make sure higher bound is actually higher 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list