[Bf-blender-cvs] [c3cc8d2f6a7] master: Realtime Compositor: Implement Streaks Glare node

Omar Emara noreply at git.blender.org
Mon Dec 19 09:09:39 CET 2022


Commit: c3cc8d2f6a76dcbca560c6ba1c09427a310be49e
Author: Omar Emara
Date:   Mon Dec 19 10:08:59 2022 +0200
Branches: master
https://developer.blender.org/rBc3cc8d2f6a76dcbca560c6ba1c09427a310be49e

Realtime Compositor: Implement Streaks Glare node

This patch implements the Streaks Glare node. Which is an approximation
to the existing implementation in the CPU compositor. The difference due
to the approximation is bearily visible in artificial test cases, but is
less visible in actual use cases. Since the difference is rather similar
to that we discussed in the Simple Star mode, the decision to allow that
difference would probably hold here.

For the future, we can look into approximating this further using a
closed form IIR recursive filter with parallel interconnection and
block-based parallelism. That's because the streak filter is already
very similar to the causal pass of a fourth order recursive filter,
just with exponential steps.

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

Reviewed By: Clement Foucault

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

M	source/blender/compositor/realtime_compositor/CMakeLists.txt
A	source/blender/compositor/realtime_compositor/shaders/compositor_glare_streaks_accumulate.glsl
A	source/blender/compositor/realtime_compositor/shaders/compositor_glare_streaks_filter.glsl
M	source/blender/compositor/realtime_compositor/shaders/infos/compositor_glare_info.hh
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 27ffcee3b80..5826c70793c 100644
--- a/source/blender/compositor/realtime_compositor/CMakeLists.txt
+++ b/source/blender/compositor/realtime_compositor/CMakeLists.txt
@@ -106,6 +106,8 @@ set(GLSL_SRC
   shaders/compositor_glare_simple_star_diagonal_pass.glsl
   shaders/compositor_glare_simple_star_horizontal_pass.glsl
   shaders/compositor_glare_simple_star_vertical_pass.glsl
+  shaders/compositor_glare_streaks_accumulate.glsl
+  shaders/compositor_glare_streaks_filter.glsl
   shaders/compositor_image_crop.glsl
   shaders/compositor_morphological_distance.glsl
   shaders/compositor_morphological_distance_feather.glsl
diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_glare_streaks_accumulate.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_glare_streaks_accumulate.glsl
new file mode 100644
index 00000000000..0156edf088a
--- /dev/null
+++ b/source/blender/compositor/realtime_compositor/shaders/compositor_glare_streaks_accumulate.glsl
@@ -0,0 +1,9 @@
+#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl)
+
+void main()
+{
+  ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
+  vec4 attenuated_streak = texture_load(streak_tx, texel) * attenuation_factor;
+  vec4 current_accumulated_streaks = imageLoad(accumulated_streaks_img, texel);
+  imageStore(accumulated_streaks_img, texel, current_accumulated_streaks + attenuated_streak);
+}
diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_glare_streaks_filter.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_glare_streaks_filter.glsl
new file mode 100644
index 00000000000..7fe7d45e4fd
--- /dev/null
+++ b/source/blender/compositor/realtime_compositor/shaders/compositor_glare_streaks_filter.glsl
@@ -0,0 +1,41 @@
+#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl)
+
+void main()
+{
+  ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
+  ivec2 input_size = texture_size(input_streak_tx);
+
+  /* Add 0.5 to evaluate the input sampler at the center of the pixel and divide by the image size
+   * to get the coordinates into the sampler's expected [0, 1] range. Similarly, transform the
+   * vector into the sampler's space by dividing by the input size. */
+  vec2 coordinates = (vec2(texel) + vec2(0.5)) / input_size;
+  vec2 vector = streak_vector / input_size;
+
+  /* Load three equally spaced neighbours to the current pixel in the direction of the streak
+   * vector. */
+  vec4 neighbours[3];
+  neighbours[0] = texture(input_streak_tx, coordinates + vector);
+  neighbours[1] = texture(input_streak_tx, coordinates + vector * 2.0);
+  neighbours[2] = texture(input_streak_tx, coordinates + vector * 3.0);
+
+  /* Attenuate the value of two of the channels for each of the neighbours by multiplying by the
+   * color modulator. The particular channels for each neighbour were chosen to be visually similar
+   * to the modulation pattern of chromatic aberration. */
+  neighbours[0].gb *= color_modulator;
+  neighbours[1].rg *= color_modulator;
+  neighbours[2].rb *= color_modulator;
+
+  /* Compute the weighted sum of all neighbours using the given fade factors as weights. The
+   * weights are expected to be lower for neighbours that are further away. */
+  vec4 weighted_neighbours_sum = vec4(0.0);
+  for (int i = 0; i < 3; i++) {
+    weighted_neighbours_sum += fade_factors[i] * neighbours[i];
+  }
+
+  /* The output is the average between the center color and the weighted sum of the neighbours.
+   * Which intuitively mean that highlights will spread in the direction of the streak, which is
+   * the desired result. */
+  vec4 center_color = texture(input_streak_tx, coordinates);
+  vec4 output_color = (center_color + weighted_neighbours_sum) / 2.0;
+  imageStore(output_streak_img, texel, output_color);
+}
diff --git a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_glare_info.hh b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_glare_info.hh
index 0e078373dfe..029bb027d5b 100644
--- a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_glare_info.hh
+++ b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_glare_info.hh
@@ -82,3 +82,25 @@ GPU_SHADER_CREATE_INFO(compositor_glare_simple_star_anti_diagonal_pass)
     .image(0, GPU_RGBA16F, Qualifier::READ_WRITE, ImageType::FLOAT_2D, "anti_diagonal_img")
     .compute_source("compositor_glare_simple_star_anti_diagonal_pass.glsl")
     .do_static_compilation(true);
+
+/* -------
+ * Streaks
+ * ------- */
+
+GPU_SHADER_CREATE_INFO(compositor_glare_streaks_filter)
+    .local_group_size(16, 16)
+    .push_constant(Type::FLOAT, "color_modulator")
+    .push_constant(Type::VEC3, "fade_factors")
+    .push_constant(Type::VEC2, "streak_vector")
+    .sampler(0, ImageType::FLOAT_2D, "input_streak_tx")
+    .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_streak_img")
+    .compute_source("compositor_glare_streaks_filter.glsl")
+    .do_static_compilation(true);
+
+GPU_SHADER_CREATE_INFO(compositor_glare_streaks_accumulate)
+    .local_group_size(16, 16)
+    .push_constant(Type::FLOAT, "attenuation_factor")
+    .sampler(0, ImageType::FLOAT_2D, "streak_tx")
+    .image(0, GPU_RGBA16F, Qualifier::READ_WRITE, ImageType::FLOAT_2D, "accumulated_streaks_img")
+    .compute_source("compositor_glare_streaks_accumulate.glsl")
+    .do_static_compilation(true);
diff --git a/source/blender/nodes/composite/nodes/node_composite_glare.cc b/source/blender/nodes/composite/nodes/node_composite_glare.cc
index 86888cd039d..b02d9e6166b 100644
--- a/source/blender/nodes/composite/nodes/node_composite_glare.cc
+++ b/source/blender/nodes/composite/nodes/node_composite_glare.cc
@@ -9,6 +9,7 @@
 
 #include "BLI_assert.h"
 #include "BLI_index_range.hh"
+#include "BLI_math_base.h"
 #include "BLI_math_base.hh"
 #include "BLI_math_vec_types.hh"
 
@@ -31,6 +32,8 @@
 
 #include "node_composite_util.hh"
 
+#define MAX_GLARE_ITERATIONS 5
+
 namespace blender::nodes::node_composite_glare_cc {
 
 NODE_STORAGE_FUNCS(NodeGlare)
@@ -128,19 +131,9 @@ class GlareOperation : public NodeOperation {
       return true;
     }
 
-    /* Only the ghost and simple star operations are currently supported. */
-    switch (node_storage(bnode()).type) {
-      case CMP_NODE_GLARE_SIMPLE_STAR:
-        return false;
-      case CMP_NODE_GLARE_FOG_GLOW:
-        return true;
-      case CMP_NODE_GLARE_STREAKS:
-        return true;
-      case CMP_NODE_GLARE_GHOST:
-        return false;
-      default:
-        BLI_assert_unreachable();
-        return true;
+    /* The fog glow mode is currently unsupported. */
+    if (node_storage(bnode()).type == CMP_NODE_GLARE_FOG_GLOW) {
+      return true;
     }
 
     return false;
@@ -334,26 +327,174 @@ class GlareOperation : public NodeOperation {
     return size.x + size.y - 1;
   }
 
-  /* ---------------
-   * Fog Glow Glare.
-   * --------------- */
+  /* --------------
+   * Streaks Glare.
+   * -------------- */
 
-  /* Not yet implemented. Unreachable code due to the is_identity method. */
-  Result execute_fog_glow(Result & /*highlights_result*/)
+  Result execute_streaks(Result &highlights_result)
   {
-    BLI_assert_unreachable();
-    return Result(ResultType::Color, texture_pool());
+    /* Create an initially zero image where streaks will be accumulated. */
+    const float4 zero_color = float4(0.0f);
+    const int2 glare_size = get_glare_size();
+    Result accumulated_streaks_result = Result::Temporary(ResultType::Color, texture_pool());
+    accumulated_streaks_result.allocate_texture(glare_size);
+    GPU_texture_clear(accumulated_streaks_result.texture(), GPU_DATA_FLOAT, zero_color);
+
+    /* For each streak, compute its direction and apply a streak filter in that direction, then
+     * accumulate the result into the accumulated streaks result. */
+    for (const int streak_index : IndexRange(get_number_of_streaks())) {
+      const float2 streak_direction = compute_streak_direction(streak_index);
+      Result streak_result = apply_streak_filter(highlights_result, streak_direction);
+
+      GPUShader *shader = shader_manager().get("compositor_glare_streaks_accumulate");
+      GPU_shader_bind(shader);
+
+      const float attenuation_factor = compute_streak_attenuation_factor();
+      GPU_shader_uniform_1f(shader, "attenuation_factor", attenuation_factor);
+
+      streak_result.bind_as_texture(shader, "streak_tx");
+      accumulated_streaks_result.bind_as_image(shader, "accumulated_streaks_img", true);
+
+      compute_dispatch_threads_at_least(shader, glare_size);
+
+      streak_result.unbind_as_texture();
+      accumulated_streaks_result.unbind_as_image();
+
+      streak_result.release();
+      GPU_shader_unbind();
+    }
+
+    return accumulated_streaks_result;
   }
 
-  /* --------------
-   * Streaks Glare.
-   * -------------- */
+  Result apply_streak_filter(Result &highlights_result, const float2 &streak_direction)
+  {
+    GPUShader *shader = shader_manager().get("compositor_glare_streaks_filter");
+    GPU_shader_bind(shader);
 
-  /* Not yet implemented. Unreachable code due to the is_identity method. */
-  Result execute_streaks(Result & /*highlights_result*/)
+    /* Copy the highlights result into a new image because the output will be copied to the input
+     * after each iteration and the highlights result is still needed to compute other streaks. */
+    const int2 glare_size = get_glare_size();
+    Result input_streak_result = Result::Temporary(ResultType::Color, texture_pool());
+    input_streak_result.allocate_texture(glare_size);
+    GPU_memory_barrier(GPU_BARRIER_TEXTURE_UPDATE);
+    GPU_texture_copy(input_streak_result.texture(), highlights_result.texture());
+
+    Result output_streak_result = Result::Temporary(ResultType::Color, texture_pool());
+    output_streak_result.allocate_texture(glare_size);
+
+    /* For the given number of iterations, apply the streak filter in the given direction. The
+     * result of the previous iteration is used as t

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list