[Bf-blender-cvs] [0f7bde8f6f5] greasepencil-refactor: GPencil: Refactor: Add SMAA as Antialiasing solution

Clément Foucault noreply at git.blender.org
Sat Jan 4 17:42:13 CET 2020


Commit: 0f7bde8f6f5883d8ee54e9f58cb9d8134310b5a9
Author: Clément Foucault
Date:   Sat Jan 4 17:39:27 2020 +0100
Branches: greasepencil-refactor
https://developer.blender.org/rB0f7bde8f6f5883d8ee54e9f58cb9d8134310b5a9

GPencil: Refactor: Add SMAA as Antialiasing solution

This removes the need of MSAA and the cost associated with it.
We run edge detection on both revealage and color buffer.

However the implemntation is not perfect: The source buffers are in linear
color space and the edge detection implies gamma corrected (display) space.
This mean the algorithm fails to capture some color changes. To workaround
this, we increase SMAA_LUMA_WEIGHT which has the same effect as decreasing
SMAA_THRESHOLD. This works ok in most scenes since GPencil objects have
clean and sharply defined shapes.

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

M	source/blender/draw/CMakeLists.txt
A	source/blender/draw/engines/gpencil/gpencil_antialiasing.c
M	source/blender/draw/engines/gpencil/gpencil_engine.c
M	source/blender/draw/engines/gpencil/gpencil_engine.h
M	source/blender/draw/engines/gpencil/gpencil_shader.c
A	source/blender/draw/engines/gpencil/shaders/gpencil_antialiasing_frag.glsl
A	source/blender/draw/engines/gpencil/shaders/gpencil_antialiasing_vert.glsl
M	source/blender/draw/intern/shaders/common_smaa_lib.glsl

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

diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 8aa5949a052..2a86aa48647 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -110,6 +110,7 @@ set(SRC
   engines/workbench/workbench_studiolight.c
   engines/workbench/workbench_volume.c
   engines/external/external_engine.c
+  engines/gpencil/gpencil_antialiasing.c
   engines/gpencil/gpencil_cache_utils.c
   engines/gpencil/gpencil_draw_cache_impl.c
   engines/gpencil/gpencil_draw_data.c
@@ -277,6 +278,8 @@ data_to_c_simple(intern/shaders/common_fullscreen_vert.glsl SRC)
 
 data_to_c_simple(engines/gpencil/shaders/gpencil_frag.glsl SRC)
 data_to_c_simple(engines/gpencil/shaders/gpencil_vert.glsl SRC)
+data_to_c_simple(engines/gpencil/shaders/gpencil_antialiasing_frag.glsl SRC)
+data_to_c_simple(engines/gpencil/shaders/gpencil_antialiasing_vert.glsl SRC)
 data_to_c_simple(engines/gpencil/shaders/gpencil_common_lib.glsl SRC)
 data_to_c_simple(engines/gpencil/shaders/gpencil_composite_frag.glsl SRC)
 data_to_c_simple(engines/gpencil/shaders/gpencil_layer_blend_frag.glsl SRC)
diff --git a/source/blender/draw/engines/gpencil/gpencil_antialiasing.c b/source/blender/draw/engines/gpencil/gpencil_antialiasing.c
new file mode 100644
index 00000000000..8e0ef370ab0
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/gpencil_antialiasing.c
@@ -0,0 +1,155 @@
+/*
+ * 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.
+ *
+ * Copyright 2019, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw
+ */
+
+#include "DRW_render.h"
+
+#include "gpencil_engine.h"
+
+#include "smaa_textures.h"
+
+void GPENCIL_antialiasing_init(struct GPENCIL_Data *vedata)
+{
+  GPENCIL_PrivateData *pd = vedata->stl->pd;
+  GPENCIL_FramebufferList *fbl = vedata->fbl;
+  GPENCIL_TextureList *txl = vedata->txl;
+  GPENCIL_PassList *psl = vedata->psl;
+  DRWShadingGroup *grp;
+
+  /* We need a temporary buffer to output result. */
+  BLI_assert(pd->color_layer_tx && pd->reveal_layer_tx);
+
+  if (txl->smaa_search_tx == NULL) {
+    txl->smaa_search_tx = GPU_texture_create_nD(SEARCHTEX_WIDTH,
+                                                SEARCHTEX_HEIGHT,
+                                                0,
+                                                2,
+                                                searchTexBytes,
+                                                GPU_R8,
+                                                GPU_DATA_UNSIGNED_BYTE,
+                                                0,
+                                                false,
+                                                NULL);
+
+    txl->smaa_area_tx = GPU_texture_create_nD(AREATEX_WIDTH,
+                                              AREATEX_HEIGHT,
+                                              0,
+                                              2,
+                                              areaTexBytes,
+                                              GPU_RG8,
+                                              GPU_DATA_UNSIGNED_BYTE,
+                                              0,
+                                              false,
+                                              NULL);
+
+    GPU_texture_bind(txl->smaa_search_tx, 0);
+    GPU_texture_filter_mode(txl->smaa_search_tx, true);
+    GPU_texture_unbind(txl->smaa_search_tx);
+
+    GPU_texture_bind(txl->smaa_area_tx, 0);
+    GPU_texture_filter_mode(txl->smaa_area_tx, true);
+    GPU_texture_unbind(txl->smaa_area_tx);
+  }
+
+  const float *size = DRW_viewport_size_get();
+  float metrics[4] = {1.0f / size[0], 1.0f / size[1], size[0], size[1]};
+
+  {
+    pd->smaa_edge_tx = DRW_texture_pool_query_2d(
+        size[0], size[1], GPU_RG8, &draw_engine_gpencil_type);
+    pd->smaa_weight_tx = DRW_texture_pool_query_2d(
+        size[0], size[1], GPU_RGBA8, &draw_engine_gpencil_type);
+
+    GPU_framebuffer_ensure_config(&fbl->smaa_edge_fb,
+                                  {
+                                      GPU_ATTACHMENT_NONE,
+                                      GPU_ATTACHMENT_TEXTURE(pd->smaa_edge_tx),
+                                  });
+
+    GPU_framebuffer_ensure_config(&fbl->smaa_weight_fb,
+                                  {
+                                      GPU_ATTACHMENT_NONE,
+                                      GPU_ATTACHMENT_TEXTURE(pd->smaa_weight_tx),
+                                  });
+  }
+
+  {
+    /* Stage 1: Edge detection. */
+    DRW_PASS_CREATE(psl->smaa_edge_ps, DRW_STATE_WRITE_COLOR);
+
+    GPUShader *sh = GPENCIL_shader_antialiasing(&en_data, 0);
+    grp = DRW_shgroup_create(sh, psl->smaa_edge_ps);
+    DRW_shgroup_uniform_texture(grp, "colorTex", pd->color_tx);
+    DRW_shgroup_uniform_texture(grp, "revealTex", pd->reveal_tx);
+    DRW_shgroup_uniform_vec4_copy(grp, "viewportMetrics", metrics);
+
+    DRW_shgroup_clear_framebuffer(grp, GPU_COLOR_BIT, 0, 0, 0, 0, 0.0f, 0x0);
+    DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+  }
+  {
+    /* Stage 2: Blend Weight/Coord. */
+    DRW_PASS_CREATE(psl->smaa_weight_ps, DRW_STATE_WRITE_COLOR);
+
+    GPUShader *sh = GPENCIL_shader_antialiasing(&en_data, 1);
+    grp = DRW_shgroup_create(sh, psl->smaa_weight_ps);
+    DRW_shgroup_uniform_texture(grp, "edgesTex", pd->smaa_edge_tx);
+    DRW_shgroup_uniform_texture(grp, "areaTex", txl->smaa_area_tx);
+    DRW_shgroup_uniform_texture(grp, "searchTex", txl->smaa_search_tx);
+    DRW_shgroup_uniform_vec4_copy(grp, "viewportMetrics", metrics);
+
+    DRW_shgroup_clear_framebuffer(grp, GPU_COLOR_BIT, 0, 0, 0, 0, 0.0f, 0x0);
+    DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+  }
+  {
+    /* Stage 3: Resolve. */
+    /* TODO merge it with the main composite pass. */
+    DRW_PASS_CREATE(psl->smaa_resolve_ps, DRW_STATE_WRITE_COLOR);
+
+    GPUShader *sh = GPENCIL_shader_antialiasing(&en_data, 2);
+    grp = DRW_shgroup_create(sh, psl->smaa_resolve_ps);
+    DRW_shgroup_uniform_texture(grp, "blendTex", pd->smaa_weight_tx);
+    DRW_shgroup_uniform_texture(grp, "colorTex", pd->color_tx);
+    DRW_shgroup_uniform_texture(grp, "revealTex", pd->reveal_tx);
+    DRW_shgroup_uniform_vec4_copy(grp, "viewportMetrics", metrics);
+
+    DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+  }
+}
+
+void GPENCIL_antialiasing_draw(struct GPENCIL_Data *vedata)
+{
+  GPENCIL_FramebufferList *fbl = vedata->fbl;
+  GPENCIL_PrivateData *pd = vedata->stl->pd;
+  GPENCIL_PassList *psl = vedata->psl;
+
+  GPU_framebuffer_bind(fbl->smaa_edge_fb);
+  DRW_draw_pass(psl->smaa_edge_ps);
+
+  GPU_framebuffer_bind(fbl->smaa_weight_fb);
+  DRW_draw_pass(psl->smaa_weight_ps);
+
+  GPU_framebuffer_bind(fbl->layer_fb);
+  DRW_draw_pass(psl->smaa_resolve_ps);
+
+  /* Swap buffers */
+  SWAP(GPUTexture *, pd->color_tx, pd->color_layer_tx);
+  SWAP(GPUTexture *, pd->reveal_tx, pd->reveal_layer_tx);
+}
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index ad06810a878..6a40eb23efc 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -385,6 +385,9 @@ static void GPENCIL_engine_free(void)
   DRW_SHADER_FREE_SAFE(e_data.gpencil_background_sh);
   DRW_SHADER_FREE_SAFE(e_data.gpencil_paper_sh);
 
+  for (int i = 0; i < 3; i++) {
+    DRW_SHADER_FREE_SAFE(e_data.antialiasing_sh[i]);
+  }
   DRW_SHADER_FREE_SAFE(e_data.gpencil_sh);
   DRW_SHADER_FREE_SAFE(e_data.composite_sh);
   DRW_SHADER_FREE_SAFE(e_data.layer_blend_sh);
@@ -1354,6 +1357,8 @@ static void GPENCIL_cache_finish_new(void *ved)
                                         GPU_ATTACHMENT_TEXTURE(pd->reveal_masked_tx),
                                     });
     }
+
+    GPENCIL_antialiasing_init(vedata);
   }
 }
 
@@ -1703,6 +1708,8 @@ static void GPENCIL_draw_scene_new(void *ved)
     GPENCIL_fast_draw_end(vedata);
   }
 
+  GPENCIL_antialiasing_draw(vedata);
+
   if (dfbl->default_fb) {
     GPU_framebuffer_bind(dfbl->default_fb);
     DRW_draw_pass(psl->composite_ps);
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h
index 62b58e45566..8eed67457ec 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.h
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.h
@@ -359,6 +359,10 @@ typedef struct GPENCIL_PassList {
   struct DRWPass *composite_ps;
   /* Composite the object depth to the default depth buffer to occlude overlays. */
   struct DRWPass *merge_depth_ps;
+  /* Anti-Aliasing. */
+  struct DRWPass *smaa_edge_ps;
+  struct DRWPass *smaa_weight_ps;
+  struct DRWPass *smaa_resolve_ps;
 } GPENCIL_PassList;
 
 typedef struct GPENCIL_FramebufferList {
@@ -376,6 +380,8 @@ typedef struct GPENCIL_FramebufferList {
   struct GPUFrameBuffer *layer_fb;
   struct GPUFrameBuffer *object_fb;
   struct GPUFrameBuffer *masked_fb;
+  struct GPUFrameBuffer *smaa_edge_fb;
+  struct GPUFrameBuffer *smaa_weight_fb;
 } GPENCIL_FramebufferList;
 
 typedef struct GPENCIL_TextureList {
@@ -385,6 +391,9 @@ typedef struct GPENCIL_TextureList {
   struct GPUTexture *snapshot_depth_tx;
   struct GPUTexture *snapshot_color_tx;
   struct GPUTexture *snapshot_reveal_tx;
+  /* Textures used by Antialiasing. */
+  struct GPUTexture *smaa_area_tx;
+  struct GPUTexture *smaa_search_tx;
 
   /* multisample textures */
   struct GPUTexture *multisample_color;
@@ -479,6 +488,9 @@ typedef struct GPENCIL_PrivateData {
   GPUTexture *reveal_layer_tx;
   GPUTexture *reveal_object_t

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list