[Bf-blender-cvs] [376f84e244e] temp-viewport-compositor-compiler: Viewport Compositor: Implement Filter node

Omar Emara noreply at git.blender.org
Thu Mar 31 16:22:13 CEST 2022


Commit: 376f84e244ee3f7cabfe9fa9faaa58063150d04b
Author: Omar Emara
Date:   Thu Mar 31 16:20:21 2022 +0200
Branches: temp-viewport-compositor-compiler
https://developer.blender.org/rB376f84e244ee3f7cabfe9fa9faaa58063150d04b

Viewport Compositor: Implement Filter node

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

M	source/blender/gpu/CMakeLists.txt
A	source/blender/gpu/shaders/compositor/compositor_filter.glsl
A	source/blender/gpu/shaders/compositor/infos/compositor_filter_info.hh
M	source/blender/nodes/composite/nodes/node_composite_filter.cc

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

diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 349c5e57f34..469ea3ea037 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -310,6 +310,7 @@ set(GLSL_SRC
   shaders/compositor/material/gpu_shader_compositor_type_conversion.glsl
 
   shaders/compositor/compositor_convert.glsl
+  shaders/compositor/compositor_filter.glsl
   shaders/compositor/compositor_realize_on_domain.glsl
   shaders/compositor/compositor_split_viewer.glsl
 
@@ -495,6 +496,7 @@ set(SHADER_CREATE_INFOS
   shaders/infos/gpu_srgb_to_framebuffer_space_info.hh
 
   shaders/compositor/infos/compositor_convert_info.hh
+  shaders/compositor/infos/compositor_filter_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_filter.glsl b/source/blender/gpu/shaders/compositor/compositor_filter.glsl
new file mode 100644
index 00000000000..b92a0644ff8
--- /dev/null
+++ b/source/blender/gpu/shaders/compositor/compositor_filter.glsl
@@ -0,0 +1,22 @@
+#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utils.glsl)
+
+void main()
+{
+  ivec2 xy = ivec2(gl_GlobalInvocationID.xy);
+
+  /* Compute the dot product between the kernel and the 3x3 window around the current pixel. */
+  vec4 color = vec4(0);
+  for (int j = 0; j < 3; j++) {
+    for (int i = 0; i < 3; i++) {
+      color += texture_load(input_image, xy + ivec2(i - 1, j - 1)) * kernel[j][i];
+    }
+  }
+
+  /* Mix with the original color at the center of the kernel using the input factor. */
+  color = mix(texture_load(input_image, xy), color, texture_load(factor, xy).x);
+
+  /* Make sure the output is never negative. */
+  color = max(color, 0.0);
+
+  imageStore(output_image, xy, color);
+}
diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_filter_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_filter_info.hh
new file mode 100644
index 00000000000..f55f8617b8a
--- /dev/null
+++ b/source/blender/gpu/shaders/compositor/infos/compositor_filter_info.hh
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2022 Blender Foundation.
+ * All rights reserved.
+ */
+
+#include "gpu_shader_create_info.hh"
+
+GPU_SHADER_CREATE_INFO(compositor_filter)
+    .local_group_size(16, 16)
+    .push_constant(Type::MAT3, "kernel")
+    .sampler(0, ImageType::FLOAT_2D, "input_image")
+    .sampler(1, ImageType::FLOAT_2D, "factor")
+    .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_image")
+    .compute_source("compositor_filter.glsl")
+    .do_static_compilation(true);
diff --git a/source/blender/nodes/composite/nodes/node_composite_filter.cc b/source/blender/nodes/composite/nodes/node_composite_filter.cc
index cd51e0d3c85..d5ba133d4aa 100644
--- a/source/blender/nodes/composite/nodes/node_composite_filter.cc
+++ b/source/blender/nodes/composite/nodes/node_composite_filter.cc
@@ -24,6 +24,12 @@
 #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"
 
 /* **************** FILTER  ******************** */
@@ -42,6 +48,146 @@ static void node_composit_buts_filter(uiLayout *layout, bContext *UNUSED(C), Poi
   uiItemR(layout, ptr, "filter_type", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
 }
 
+using namespace blender::viewport_compositor;
+
+class FilterOperation : public NodeOperation {
+ public:
+  using NodeOperation::NodeOperation;
+
+  void execute() override
+  {
+    GPUShader *shader = GPU_shader_create_from_info_name("compositor_filter");
+    GPU_shader_bind(shader);
+
+    float kernel[3][3];
+    get_filter_kernel(kernel);
+    GPU_shader_uniform_mat3(shader, "kernel", kernel);
+
+    const Result &input_image = get_input("Image");
+    input_image.bind_as_texture(shader, "input_image");
+
+    const Result &factor = get_input("Fac");
+    factor.bind_as_texture(shader, "factor");
+
+    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();
+    factor.unbind_as_texture();
+    output_image.unbind_as_image();
+    GPU_shader_unbind();
+    GPU_shader_free(shader);
+  }
+
+  int get_filter_method()
+  {
+    return node().custom1;
+  }
+
+  void get_filter_kernel(float kernel[3][3])
+  {
+    switch (get_filter_method()) {
+      case CMP_FILT_SOFT:
+        kernel[0][0] = 1.0f / 16.0f;
+        kernel[0][1] = 2.0f / 16.0f;
+        kernel[0][2] = 1.0f / 16.0f;
+        kernel[1][0] = 2.0f / 16.0f;
+        kernel[1][1] = 4.0f / 16.0f;
+        kernel[1][2] = 2.0f / 16.0f;
+        kernel[2][0] = 1.0f / 16.0f;
+        kernel[2][1] = 2.0f / 16.0f;
+        kernel[2][2] = 1.0f / 16.0f;
+        break;
+      case CMP_FILT_SHARP:
+        kernel[0][0] = -1.0f;
+        kernel[0][1] = -1.0f;
+        kernel[0][2] = -1.0f;
+        kernel[1][0] = -1.0f;
+        kernel[1][1] = 9.0f;
+        kernel[1][2] = -1.0f;
+        kernel[2][0] = -1.0f;
+        kernel[2][1] = -1.0f;
+        kernel[2][2] = -1.0f;
+        break;
+      case CMP_FILT_LAPLACE:
+        kernel[0][0] = -1.0f / 8.0f;
+        kernel[0][1] = -1.0f / 8.0f;
+        kernel[0][2] = -1.0f / 8.0f;
+        kernel[1][0] = -1.0f / 8.0f;
+        kernel[1][1] = 1.0f;
+        kernel[1][2] = -1.0f / 8.0f;
+        kernel[2][0] = -1.0f / 8.0f;
+        kernel[2][1] = -1.0f / 8.0f;
+        kernel[2][2] = -1.0f / 8.0f;
+        break;
+      case CMP_FILT_SOBEL:
+        kernel[0][0] = 1.0f;
+        kernel[0][1] = 0.0f;
+        kernel[0][2] = -1.0f;
+        kernel[1][0] = 2.0f;
+        kernel[1][1] = 0.0f;
+        kernel[1][2] = -2.0f;
+        kernel[2][0] = 1.0f;
+        kernel[2][1] = 0.0f;
+        kernel[2][2] = -1.0f;
+        break;
+      case CMP_FILT_PREWITT:
+        kernel[0][0] = 1.0f;
+        kernel[0][1] = 0.0f;
+        kernel[0][2] = -1.0f;
+        kernel[1][0] = 1.0f;
+        kernel[1][1] = 0.0f;
+        kernel[1][2] = -1.0f;
+        kernel[2][0] = 1.0f;
+        kernel[2][1] = 0.0f;
+        kernel[2][2] = -1.0f;
+        break;
+      case CMP_FILT_KIRSCH:
+        kernel[0][0] = 5.0f;
+        kernel[0][1] = -3.0f;
+        kernel[0][2] = -2.0f;
+        kernel[1][0] = 5.0f;
+        kernel[1][1] = -3.0f;
+        kernel[1][2] = -2.0f;
+        kernel[2][0] = 5.0f;
+        kernel[2][1] = -3.0f;
+        kernel[2][2] = -2.0f;
+        break;
+      case CMP_FILT_SHADOW:
+        kernel[0][0] = 1.0f;
+        kernel[0][1] = 0.0f;
+        kernel[0][2] = -1.0f;
+        kernel[1][0] = 2.0f;
+        kernel[1][1] = 1.0f;
+        kernel[1][2] = -2.0f;
+        kernel[2][0] = 1.0f;
+        kernel[2][1] = 0.0f;
+        kernel[2][2] = -1.0f;
+        break;
+      default:
+        kernel[0][0] = 0.0f;
+        kernel[0][1] = 0.0f;
+        kernel[0][2] = 0.0f;
+        kernel[1][0] = 0.0f;
+        kernel[1][1] = 1.0f;
+        kernel[1][2] = 0.0f;
+        kernel[2][0] = 0.0f;
+        kernel[2][1] = 0.0f;
+        kernel[2][2] = 0.0f;
+        break;
+    }
+  }
+};
+
+static NodeOperation *get_compositor_operation(Context &context, DNode node)
+{
+  return new FilterOperation(context, node);
+}
+
 }  // namespace blender::nodes::node_composite_filter_cc
 
 void register_node_type_cmp_filter()
@@ -54,6 +200,7 @@ void register_node_type_cmp_filter()
   ntype.declare = file_ns::cmp_node_filter_declare;
   ntype.draw_buttons = file_ns::node_composit_buts_filter;
   ntype.labelfunc = node_filter_label;
+  ntype.get_compositor_operation = file_ns::get_compositor_operation;
   ntype.flag |= NODE_PREVIEW;
 
   nodeRegisterType(&ntype);



More information about the Bf-blender-cvs mailing list