Commit: fa27a5d066a1d6b04e77bfa4088dca83644bceaf
Author: Omar Emara
Date:   Fri Dec 9 16:50:52 2022 +0200
Branches: master
https://developer.blender.org/rBfa27a5d066a1d6b04e77bfa4088dca83644bceaf

Realtime Compositor: Implement Ghost Glare node

This patch implements the Ghost Glare node. It is implemented using
direct convolution as opposed to a recursive one, which produces
slightly different results---more accurate ones, however, since the
ghosts are attenuated where it matters, the difference is barely
visible and is acceptable as far as I can tell.

A possible performance improvement is to implement all passes in a
single shader dispatch, where an array of all scales and color
modulators is computed recursively on the host then used in the shader
to add all ghosts, avoiding usage of global memory and unnecessary
copies. This optimization will be implemented separately.

Differential Revision: https://developer.blender.org/D16641

Reviewed By: Clement Foucault

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

M       source/blender/compositor/realtime_compositor/CMakeLists.txt
M       source/blender/compositor/realtime_compositor/COM_result.hh
A       
source/blender/compositor/realtime_compositor/algorithms/COM_algorithm_symmetric_separable_blur.hh
A       
source/blender/compositor/realtime_compositor/algorithms/intern/symmetric_separable_blur.cc
M       source/blender/compositor/realtime_compositor/intern/result.cc
A       
source/blender/compositor/realtime_compositor/shaders/compositor_glare_ghost_accumulate.glsl
A       
source/blender/compositor/realtime_compositor/shaders/compositor_glare_ghost_base.glsl
A       
source/blender/compositor/realtime_compositor/shaders/compositor_glare_highlights.glsl
A       
source/blender/compositor/realtime_compositor/shaders/compositor_glare_mix.glsl
A       
source/blender/compositor/realtime_compositor/shaders/infos/compositor_glare_info.hh
M       source/blender/makesdna/DNA_node_types.h
M       source/blender/nodes/composite/nodes/node_composite_blur.cc
M       source/blender/nodes/composite/nodes/node_composite_glare.cc

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

diff --git a/source/blender/compositor/realtime_compositor/CMakeLists.txt 
b/source/blender/compositor/realtime_compositor/CMakeLists.txt
index b4352248b5b..7d7448a448f 100644
--- a/source/blender/compositor/realtime_compositor/CMakeLists.txt
+++ b/source/blender/compositor/realtime_compositor/CMakeLists.txt
@@ -60,8 +60,10 @@ set(SRC
   COM_utilities.hh
 
   algorithms/intern/algorithm_parallel_reduction.cc
+  algorithms/intern/symmetric_separable_blur.cc
 
   algorithms/COM_algorithm_parallel_reduction.hh
+  algorithms/COM_algorithm_symmetric_separable_blur.hh
 
   cached_resources/intern/morphological_distance_feather_weights.cc
   cached_resources/intern/symmetric_blur_weights.cc
@@ -96,6 +98,10 @@ set(GLSL_SRC
   shaders/compositor_ellipse_mask.glsl
   shaders/compositor_filter.glsl
   shaders/compositor_flip.glsl
+  shaders/compositor_glare_ghost_accumulate.glsl
+  shaders/compositor_glare_ghost_base.glsl
+  shaders/compositor_glare_highlights.glsl
+  shaders/compositor_glare_mix.glsl
   shaders/compositor_image_crop.glsl
   shaders/compositor_morphological_distance.glsl
   shaders/compositor_morphological_distance_feather.glsl
@@ -181,6 +187,7 @@ set(SRC_SHADER_CREATE_INFOS
   shaders/infos/compositor_ellipse_mask_info.hh
   shaders/infos/compositor_filter_info.hh
   shaders/infos/compositor_flip_info.hh
+  shaders/infos/compositor_glare_info.hh
   shaders/infos/compositor_image_crop_info.hh
   shaders/infos/compositor_morphological_distance_feather_info.hh
   shaders/infos/compositor_morphological_distance_info.hh
diff --git a/source/blender/compositor/realtime_compositor/COM_result.hh 
b/source/blender/compositor/realtime_compositor/COM_result.hh
index f5ecc4c2112..3f8378bc4c2 100644
--- a/source/blender/compositor/realtime_compositor/COM_result.hh
+++ b/source/blender/compositor/realtime_compositor/COM_result.hh
@@ -105,6 +105,11 @@ class Result {
    * and release the result's texture. */
   Result(ResultType type, TexturePool &texture_pool);
 
+  /* Identical to the standard constructor but initializes the reference count 
to 1. This is useful
+   * to construct temporary results that are created and released by the 
developer manually, which
+   * are typically used in operations that need temporary intermediate 
results. */
+  static Result Temporary(ResultType type, TexturePool &texture_pool);
+
   /* Declare the result to be a texture result, allocate a texture of an 
appropriate type with
    * the size of the given domain from the result's texture pool, and set the 
domain of the result
    * to the given domain. */
@@ -125,8 +130,9 @@ class Result {
   void bind_as_texture(GPUShader *shader, const char *texture_name) const;
 
   /* Bind the texture of the result to the image unit with the given name in 
the currently bound
-   * given shader. */
-  void bind_as_image(GPUShader *shader, const char *image_name) const;
+   * given shader. If read is true, a memory barrier will be inserted for 
image reads to ensure any
+   * prior writes to the images are reflected before reading from it. */
+  void bind_as_image(GPUShader *shader, const char *image_name, bool read = 
false) const;
 
   /* Unbind the texture which was previously bound using bind_as_texture. */
   void unbind_as_texture() const;
diff --git 
a/source/blender/compositor/realtime_compositor/algorithms/COM_algorithm_symmetric_separable_blur.hh
 
b/source/blender/compositor/realtime_compositor/algorithms/COM_algorithm_symmetric_separable_blur.hh
new file mode 100644
index 00000000000..317ce2ab522
--- /dev/null
+++ 
b/source/blender/compositor/realtime_compositor/algorithms/COM_algorithm_symmetric_separable_blur.hh
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#pragma once
+
+#include "BLI_math_vec_types.hh"
+
+#include "COM_context.hh"
+#include "COM_result.hh"
+
+namespace blender::realtime_compositor {
+
+/* Blur the input using a horizontal and a vertical separable blur passes 
given a certain radius
+ * and filter type using SymmetricSeparableBlurWeights. The output is written 
to the given output
+ * result, which will be allocated internally and is thus expected not to be 
previously allocated.
+ * If extend_bounds is true, the output will have an extra radius amount of 
pixels on the boundary
+ * of the image, where blurring can take place assuming a fully transparent 
out of bound values. If
+ * gamma_correct is true, the input will be gamma corrected before blurring 
and then uncorrected
+ * after blurring, using a gamma coefficient of 2. */
+void symmetric_separable_blur(Context &context,
+                              Result &input,
+                              Result &output,
+                              float2 radius,
+                              int filter_type,
+                              bool extend_bounds,
+                              bool gamma_correct);
+
+}  // namespace blender::realtime_compositor
diff --git 
a/source/blender/compositor/realtime_compositor/algorithms/intern/symmetric_separable_blur.cc
 
b/source/blender/compositor/realtime_compositor/algorithms/intern/symmetric_separable_blur.cc
new file mode 100644
index 00000000000..e450abdc203
--- /dev/null
+++ 
b/source/blender/compositor/realtime_compositor/algorithms/intern/symmetric_separable_blur.cc
@@ -0,0 +1,132 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "BLI_math_base.hh"
+#include "BLI_math_vec_types.hh"
+#include "BLI_math_vector.hh"
+
+#include "GPU_shader.h"
+#include "GPU_texture.h"
+
+#include "COM_context.hh"
+#include "COM_utilities.hh"
+
+#include "COM_algorithm_symmetric_separable_blur.hh"
+
+#include "COM_symmetric_separable_blur_weights.hh"
+
+namespace blender::realtime_compositor {
+
+static Result horizontal_pass(Context &context,
+                              Result &input,
+                              float radius,
+                              int filter_type,
+                              bool extend_bounds,
+                              bool gamma_correct)
+{
+  GPUShader *shader = 
context.shader_manager().get("compositor_symmetric_separable_blur");
+  GPU_shader_bind(shader);
+
+  GPU_shader_uniform_1b(shader, "extend_bounds", extend_bounds);
+  GPU_shader_uniform_1b(shader, "gamma_correct_input", gamma_correct);
+  GPU_shader_uniform_1b(shader, "gamma_uncorrect_output", false);
+
+  input.bind_as_texture(shader, "input_tx");
+
+  const SymmetricSeparableBlurWeights &weights =
+      
context.cache_manager().get_symmetric_separable_blur_weights(filter_type, 
radius);
+  weights.bind_as_texture(shader, "weights_tx");
+
+  Domain domain = input.domain();
+  if (extend_bounds) {
+    domain.size.x += int(math::ceil(radius)) * 2;
+  }
+
+  /* We allocate an output image of a transposed size, that is, with a height 
equivalent to the
+   * width of the input and vice versa. This is done as a performance 
optimization. The shader
+   * will blur the image horizontally and write it to the intermediate output 
transposed. Then
+   * the vertical pass will execute the same horizontal blur shader, but since 
its input is
+   * transposed, it will effectively do a vertical blur and write to the 
output transposed,
+   * effectively undoing the transposition in the horizontal pass. This is 
done to improve
+   * spatial cache locality in the shader and to avoid having two separate 
shaders for each blur
+   * pass. */
+  const int2 transposed_domain = int2(domain.size.y, domain.size.x);
+
+  Result output = Result::Temporary(ResultType::Color, context.texture_pool());
+  output.allocate_texture(transposed_domain);
+  output.bind_as_image(shader, "output_img");
+
+  compute_dispatch_threads_at_least(shader, domain.size);
+
+  GPU_shader_unbind();
+  input.unbind_as_texture();
+  weights.unbind_as_texture();
+  output.unbind_as_image();
+
+  return output;
+}
+
+static void vertical_pass(Context &context,
+                          Result &original_input,
+                          Result &horizontal_pass_result,
+                          Result &output,
+                          float2 radius,
+                          int filter_type,
+                          bool extend_bounds,
+                          bool gamma_correct)
+{
+  GPUShader *shader = 
context.shader_manager().get("compositor_symmetric_separable_blur");
+  GPU_shader_bind(shader);
+
+  GPU_shader_uniform_1b(shader, "extend_bounds", extend_bounds);
+  GPU_shader_uniform_1b(shader, "gamma_correct_input", false);
+  GPU_shader_uniform_1b(shader, "gamma_uncorrect_output", gamma_correct);
+
+  horizontal_pass_result.bind_as_texture(shader, "input_tx");
+
+  const SymmetricSeparableBlurWeights &weights =
+      
context.cache_manager().get_symmetric_separable_blur_weights(filter_type, 
radius.y);
+  weights.bind_as_texture(shader, "weights_tx");
+
+  Domain domain = original_input.domain();
+  if (extend_bounds) {
+    /* Add a radius amount of pixels in both sides of the image, hence the 
multiply by 2. */
+    domain.size += int2(math::ceil(radius)) * 2;
+  }
+
+  output.allocate_texture(domain);
+  output.bind_as_image(shader, "output_img");
+
+  /* Notice that the domain is transposed, see the note on the horizontal pass 
method for more
+   * information on the reasoning behind this. */
+  compute_dispatch_threads_at_least(shader, int2(domain.size.y, 
domain.size.x));
+
+  GPU_shader_unbind();
+  horizontal_pass_result.unbind_as_texture();
+  output.unbind_as_image();
+  weights.unbind_as_texture();
+}
+
+void symmetric_separable_blur(Context &context,
+                              Result &input,
+                              Result &output,
+                              float2 radius,
+                              int filter_type,
+                              bool extend_bounds,
+                              bool gamma_correct)
+{
+  Result horizontal_pass_result = horizontal_pass(
+      context, input, radius.x, filter_type, extend_bounds, gamma_correct);
+
+  vertical_pass(context,
+                input,
+                horizontal_pass_result,
+                output,
+                radius,
+                filter_type,
+                extend_bounds,
+                gamma_correct);
+
+  horizontal_pass_result.release();
+}
+
+}  // namespace blender::realtime_composito

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
List details, subscription details or unsubscribe:
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to