[Bf-blender-cvs] [36814ddc94b] master: Workbench: Improve AntiAliasing sampling

Jeroen Bakker noreply at git.blender.org
Tue Feb 16 09:05:50 CET 2021


Commit: 36814ddc94b56a66675b854bc0d7485828ddcd31
Author: Jeroen Bakker
Date:   Tue Feb 16 08:59:17 2021 +0100
Branches: master
https://developer.blender.org/rB36814ddc94b56a66675b854bc0d7485828ddcd31

Workbench: Improve AntiAliasing sampling

This improves stability and convergence speed of Workbench Temporal AntiAliasing.

This adds a filtering kernel (blackmann-haris, same as EEVEE/Cycles) to the
temporal antialiasing sampling. We also gather neighbor pixels since they might
end up in the pixel footprint.

We use a 1px radius for the filter window which is a bit less than the 1.5 default
of cycles and EEVEE since it does blur quite a bit more than what we have now.

Another improvement is that the filtering is now in log space which improves
AntiAliasing around highlights.

Theses improvement may not be very useful for every day case but it was an
experiment to try to make TAA usable for GPencil.

Test file used :
{F9798807}

|filtered+logspace|filtered|original|
|{F9798847}|{F9798848}|{F9798849}|

Reviewed By: jbakker

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

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

M	source/blender/draw/engines/workbench/shaders/workbench_effect_smaa_frag.glsl
M	source/blender/draw/engines/workbench/shaders/workbench_effect_taa_frag.glsl
M	source/blender/draw/engines/workbench/workbench_effect_antialiasing.c
M	source/blender/draw/engines/workbench/workbench_private.h

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

diff --git a/source/blender/draw/engines/workbench/shaders/workbench_effect_smaa_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_effect_smaa_frag.glsl
index 2dea2fc4883..9797a5e3301 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_effect_smaa_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_effect_smaa_frag.glsl
@@ -5,7 +5,7 @@ uniform sampler2D searchTex;
 uniform sampler2D blendTex;
 uniform sampler2D colorTex;
 uniform float mixFactor;
-uniform float taaSampleCountInv;
+uniform float taaAccumulatedWeight;
 
 in vec2 uvs;
 in vec2 pixcoord;
@@ -39,6 +39,12 @@ void main()
   if (mixFactor < 1.0) {
     fragColor += texture(colorTex, uvs) * (1.0 - mixFactor);
   }
-  fragColor *= taaSampleCountInv;
+  fragColor /= taaAccumulatedWeight;
+  fragColor = exp2(fragColor) - 0.5;
+
+  /* Avoid float precision issue. */
+  if (fragColor.a > 0.999) {
+    fragColor.a = 1.0;
+  }
 #endif
 }
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_effect_taa_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_effect_taa_frag.glsl
index b877c2c3f76..d021e4696f7 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_effect_taa_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_effect_taa_frag.glsl
@@ -1,11 +1,22 @@
 
 uniform sampler2D colorBuffer;
-
-in vec4 uvcoordsvar;
+uniform float samplesWeights[9];
 
 out vec4 fragColor;
 
 void main()
 {
-  fragColor = texture(colorBuffer, uvcoordsvar.st);
+  vec2 texel_size = 1.0 / vec2(textureSize(colorBuffer, 0));
+  vec2 uv = gl_FragCoord.xy * texel_size;
+
+  fragColor = vec4(0.0);
+  int i = 0;
+  for (int x = -1; x <= 1; x++) {
+    for (int y = -1; y <= 1; y++, i++) {
+      /* Use log2 space to avoid highlights creating too much aliasing. */
+      vec4 color = log2(texture(colorBuffer, uv + vec2(x, y) * texel_size) + 0.5);
+
+      fragColor += color * samplesWeights[i];
+    }
+  }
 }
diff --git a/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c b/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c
index feb48b2623d..83aa7f6e344 100644
--- a/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c
+++ b/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c
@@ -264,6 +264,37 @@ void workbench_antialiasing_engine_init(WORKBENCH_Data *vedata)
   }
 }
 
+static float filter_blackman_harris(float x, const float width)
+{
+  if (x > width * 0.5f) {
+    return 0.0f;
+  }
+  x = 2.0f * M_PI * clamp_f((x / width + 0.5f), 0.0f, 1.0f);
+  return 0.35875f - 0.48829f * cosf(x) + 0.14128f * cosf(2.0f * x) - 0.01168f * cosf(3.0f * x);
+}
+
+/* Compute weights for the 3x3 neighborhood using a 1.5px filter. */
+static void workbench_antialiasing_weights_get(const float offset[2],
+                                               float r_weights[9],
+                                               float *r_weight_sum)
+{
+  /* NOTE: If filter width is bigger than 2.0f, then we need to sample more neighborhood. */
+  const float filter_width = 2.0f;
+  *r_weight_sum = 0.0f;
+  int i = 0;
+  for (int x = -1; x <= 1; x++) {
+    for (int y = -1; y <= 1; y++, i++) {
+      float sample_co[2] = {x, y};
+      add_v2_v2(sample_co, offset);
+      float r = len_v2(sample_co);
+      /* fclem: is radial distance ok here? */
+      float weight = filter_blackman_harris(r, filter_width);
+      *r_weight_sum += weight;
+      r_weights[i] = weight;
+    }
+  }
+}
+
 void workbench_antialiasing_cache_init(WORKBENCH_Data *vedata)
 {
   WORKBENCH_TextureList *txl = vedata->txl;
@@ -278,10 +309,12 @@ void workbench_antialiasing_cache_init(WORKBENCH_Data *vedata)
 
   {
     DRW_PASS_CREATE(psl->aa_accum_ps, DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ADD_FULL);
+    DRW_PASS_INSTANCE_CREATE(psl->aa_accum_replace_ps, psl->aa_accum_ps, DRW_STATE_WRITE_COLOR);
 
     GPUShader *shader = workbench_shader_antialiasing_accumulation_get();
     grp = DRW_shgroup_create(shader, psl->aa_accum_ps);
-    DRW_shgroup_uniform_texture(grp, "colorBuffer", dtxl->color);
+    DRW_shgroup_uniform_texture_ex(grp, "colorBuffer", dtxl->color, GPU_SAMPLER_DEFAULT);
+    DRW_shgroup_uniform_float(grp, "samplesWeights", wpd->taa_weights, 9);
     DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
   }
 
@@ -325,7 +358,7 @@ void workbench_antialiasing_cache_init(WORKBENCH_Data *vedata)
     DRW_shgroup_uniform_texture(grp, "colorTex", txl->history_buffer_tx);
     DRW_shgroup_uniform_vec4_copy(grp, "viewportMetrics", metrics);
     DRW_shgroup_uniform_float(grp, "mixFactor", &wpd->smaa_mix_factor, 1);
-    DRW_shgroup_uniform_float(grp, "taaSampleCountInv", &wpd->taa_sample_inv, 1);
+    DRW_shgroup_uniform_float(grp, "taaAccumulatedWeight", &wpd->taa_weight_accum, 1);
 
     DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
   }
@@ -369,6 +402,8 @@ bool workbench_antialiasing_setup(WORKBENCH_Data *vedata)
       break;
   }
 
+  workbench_antialiasing_weights_get(transform_offset, wpd->taa_weights, &wpd->taa_weights_sum);
+
   /* construct new matrices from transform delta */
   float winmat[4][4], viewmat[4][4], persmat[4][4];
   DRW_view_winmat_get(default_view, winmat, false);
@@ -419,8 +454,11 @@ void workbench_antialiasing_draw_pass(WORKBENCH_Data *vedata)
   const bool last_sample = wpd->taa_sample + 1 == wpd->taa_sample_len;
   const bool taa_finished = wpd->taa_sample >= wpd->taa_sample_len;
   if (wpd->taa_sample == 0) {
+    wpd->taa_weight_accum = wpd->taa_weights_sum;
     wpd->valid_history = true;
-    GPU_texture_copy(txl->history_buffer_tx, dtxl->color);
+
+    GPU_framebuffer_bind(fbl->antialiasing_fb);
+    DRW_draw_pass(psl->aa_accum_replace_ps);
     /* In playback mode, we are sure the next redraw will not use the same viewmatrix.
      * In this case no need to save the depth buffer. */
     if (!wpd->is_playback) {
@@ -435,6 +473,7 @@ void workbench_antialiasing_draw_pass(WORKBENCH_Data *vedata)
       /* Accumulate result to the TAA buffer. */
       GPU_framebuffer_bind(fbl->antialiasing_fb);
       DRW_draw_pass(psl->aa_accum_ps);
+      wpd->taa_weight_accum += wpd->taa_weights_sum;
     }
     /* Copy back the saved depth buffer for correct overlays. */
     GPU_texture_copy(dtxl->depth, txl->depth_buffer_tx);
@@ -446,7 +485,6 @@ void workbench_antialiasing_draw_pass(WORKBENCH_Data *vedata)
   if (!DRW_state_is_image_render() || last_sample) {
     /* After a certain point SMAA is no longer necessary. */
     wpd->smaa_mix_factor = 1.0f - clamp_f(wpd->taa_sample / 4.0f, 0.0f, 1.0f);
-    wpd->taa_sample_inv = 1.0f / min_ii(wpd->taa_sample + 1, wpd->taa_sample_len);
 
     if (wpd->smaa_mix_factor > 0.0f) {
       GPU_framebuffer_bind(fbl->smaa_edge_fb);
diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h
index 522aae7f542..6247436feea 100644
--- a/source/blender/draw/engines/workbench/workbench_private.h
+++ b/source/blender/draw/engines/workbench/workbench_private.h
@@ -164,6 +164,7 @@ typedef struct WORKBENCH_PassList {
   struct DRWPass *volume_ps;
 
   struct DRWPass *aa_accum_ps;
+  struct DRWPass *aa_accum_replace_ps;
   struct DRWPass *aa_edge_ps;
   struct DRWPass *aa_weight_ps;
   struct DRWPass *aa_resolve_ps;
@@ -286,8 +287,12 @@ typedef struct WORKBENCH_PrivateData {
   int taa_sample_len_previous;
   /** Current TAA sample index in [0..taa_sample_len[ range. */
   int taa_sample;
-  /** Inverse of taa_sample to divide the accumulation buffer. */
-  float taa_sample_inv;
+  /** Weight accumulated. */
+  float taa_weight_accum;
+  /** Samples weight for this iteration. */
+  float taa_weights[9];
+  /** Sum of taa_weights. */
+  float taa_weights_sum;
   /** If the view has been updated and TAA needs to be reset. */
   bool view_updated;
   /** True if the history buffer contains relevant data and false if it could contain garbage. */



More information about the Bf-blender-cvs mailing list