[Bf-blender-cvs] [d8c99ac34e6] greasepencil-refactor: GPencil: Refactor: Add per mask inversion capability

Clément Foucault noreply at git.blender.org
Tue Feb 11 17:12:45 CET 2020


Commit: d8c99ac34e62fd7606efdc1fafeba512a704ad0e
Author: Clément Foucault
Date:   Tue Feb 11 17:12:33 2020 +0100
Branches: greasepencil-refactor
https://developer.blender.org/rBd8c99ac34e62fd7606efdc1fafeba512a704ad0e

GPencil: Refactor: Add per mask inversion capability

With this commit, masks can be inverted per layer. Inversion means the
mask becomes subtractive instead of additive. The base visibility does not
change depending on the first type (i.e: if ther is nothing in the mask
layer, nothing will be masked regardless of the mask type).

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

M	source/blender/draw/CMakeLists.txt
M	source/blender/draw/engines/gpencil/gpencil_cache_utils.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
M	source/blender/draw/engines/gpencil/shaders/gpencil_layer_blend_frag.glsl
A	source/blender/draw/engines/gpencil/shaders/gpencil_mask_invert_frag.glsl

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

diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index b4ed5a953dd..e76d58bef90 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -285,6 +285,7 @@ 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)
+data_to_c_simple(engines/gpencil/shaders/gpencil_mask_invert_frag.glsl SRC)
 data_to_c_simple(engines/gpencil/shaders/gpencil_depth_merge_frag.glsl SRC)
 data_to_c_simple(engines/gpencil/shaders/gpencil_depth_merge_vert.glsl SRC)
 data_to_c_simple(engines/gpencil/shaders/gpencil_vfx_frag.glsl SRC)
diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
index 3caaea0516b..a5b3cdcec24 100644
--- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
@@ -116,7 +116,6 @@ GPENCIL_tLayer *gpencil_layer_cache_add(GPENCIL_PrivateData *pd, Object *ob, bGP
   const bool is_fade = ((pd->fade_layer_opacity > -1.0f) && (is_obact) &&
                         ((gpl->flag & GP_LAYER_ACTIVE) == 0));
   const bool use_mask = (gpl->flag & GP_LAYER_USE_MASK) != 0;
-  bool mask_invert = true; /* True because we invert the dummy texture red channel. */
 
   /* Defines layer opacity. For active object depends of layer opacity factor, and
    * for no active object, depends if the fade grease pencil objects option is enabled. */
@@ -134,27 +133,31 @@ GPENCIL_tLayer *gpencil_layer_cache_add(GPENCIL_PrivateData *pd, Object *ob, bGP
   GPENCIL_tLayer *tgp_layer = BLI_memblock_alloc(pd->gp_layer_pool);
   tgp_layer->layer_id = BLI_findindex(&gpd->layers, gpl);
   tgp_layer->mask_bits = NULL;
+  tgp_layer->mask_invert_bits = NULL;
 
   if (use_mask && !BLI_listbase_is_empty(&gpl->mask_layers)) {
     bool valid_mask = false;
     /* Warning: only GP_MAX_MASKBITS amount of bits.
      * TODO(fclem) Find a better system without any limitation. */
     tgp_layer->mask_bits = BLI_memblock_alloc(pd->gp_maskbit_pool);
+    tgp_layer->mask_invert_bits = BLI_memblock_alloc(pd->gp_maskbit_pool);
     BLI_bitmap_set_all(tgp_layer->mask_bits, false, GP_MAX_MASKBITS);
 
     LISTBASE_FOREACH (bGPDlayer_Mask *, mask, &gpl->mask_layers) {
       bGPDlayer *gpl_mask = BKE_gpencil_layer_named_get(gpd, mask->name);
-      if (gpl_mask && (gpl_mask != gpl) && ((gpl_mask->flag & GP_LAYER_HIDE) == 0)) {
+      if (gpl_mask && (gpl_mask != gpl) && ((gpl_mask->flag & GP_LAYER_HIDE) == 0) &&
+          ((mask->flag & GP_MASK_HIDE) == 0)) {
         int index = BLI_findindex(&gpd->layers, gpl_mask);
         if (index < GP_MAX_MASKBITS) {
+          const bool invert = (mask->flag & GP_MASK_INVERT) != 0;
           BLI_BITMAP_SET(tgp_layer->mask_bits, index, true);
+          BLI_BITMAP_SET(tgp_layer->mask_invert_bits, index, invert);
           valid_mask = true;
         }
       }
     }
 
     if (valid_mask) {
-      mask_invert = (gpl->flag & GP_LAYER_MASK_INVERT) != 0;
       pd->use_mask_fb = true;
     }
     else {
@@ -214,7 +217,6 @@ GPENCIL_tLayer *gpencil_layer_cache_add(GPENCIL_PrivateData *pd, Object *ob, bGP
     DRW_shgroup_uniform_texture_ref(grp, "colorBuf", &pd->color_layer_tx);
     DRW_shgroup_uniform_texture_ref(grp, "revealBuf", &pd->reveal_layer_tx);
     DRW_shgroup_uniform_texture_ref(grp, "maskBuf", (is_masked) ? &pd->mask_tx : &pd->dummy_tx);
-    DRW_shgroup_uniform_bool_copy(grp, "maskInvert", mask_invert);
     DRW_shgroup_stencil_mask(grp, 0xFF);
     DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
 
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index fe3e5def710..17a0ca25892 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -289,6 +289,14 @@ void GPENCIL_cache_init(void *ved)
     DRW_shgroup_uniform_vec4(grp, "gpModelMatrix[0]", pd->object_bound_mat[0], 4);
     DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
   }
+  {
+    DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_LOGIC_INVERT;
+    DRW_PASS_CREATE(psl->mask_invert_ps, state);
+
+    GPUShader *sh = GPENCIL_shader_mask_invert_get();
+    grp = DRW_shgroup_create(sh, psl->mask_invert_ps);
+    DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+  }
 
   Camera *cam = (pd->camera != NULL) ? pd->camera->data : NULL;
 
@@ -836,29 +844,46 @@ static void GPENCIL_draw_scene_depth_only(void *ved)
 
 static void gpencil_draw_mask(GPENCIL_Data *vedata, GPENCIL_tObject *ob, GPENCIL_tLayer *layer)
 {
+  GPENCIL_PassList *psl = vedata->psl;
   GPENCIL_FramebufferList *fbl = vedata->fbl;
   float clear_col[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+  float clear_depth = ob->is_drawmode3d ? 1.0f : 0.0f;
+  bool inverted = false;
+  /* OPTI(fclem) we could optimize by only clearing if the new mask_bits does not contain all
+   * the masks already rendered in the buffer, and drawing only the layers not already drawn. */
+  bool cleared = false;
 
   DRW_stats_group_start("GPencil Mask");
 
-  /* OPTI(fclem) we could optimize by only clearing if the new mask_bits contains all
-   * the masks already rendered in the buffer, and drawing only the layers not already drawn. */
-  if (true) {
-    GPU_framebuffer_bind(fbl->mask_fb);
-    GPU_framebuffer_clear_color_depth(fbl->mask_fb, clear_col, ob->is_drawmode3d ? 1.0f : 0.0f);
-  }
+  GPU_framebuffer_bind(fbl->mask_fb);
 
   for (int i = 0; i < GP_MAX_MASKBITS; i++) {
     if (!BLI_BITMAP_TEST(layer->mask_bits, i)) {
       continue;
     }
 
+    if (BLI_BITMAP_TEST_BOOL(layer->mask_invert_bits, i) != inverted) {
+      if (cleared) {
+        DRW_draw_pass(psl->mask_invert_ps);
+      }
+      inverted = !inverted;
+    }
+
+    if (!cleared) {
+      cleared = true;
+      GPU_framebuffer_clear_color_depth(fbl->mask_fb, clear_col, clear_depth);
+    }
+
     GPENCIL_tLayer *mask_layer = gpencil_layer_cache_get(ob, i);
     BLI_assert(mask_layer);
 
     DRW_draw_pass(mask_layer->geom_ps);
   }
 
+  if (inverted) {
+    DRW_draw_pass(psl->mask_invert_ps);
+  }
+
   DRW_stats_group_end();
 }
 
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h
index 1dec9feb61b..944494dd279 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.h
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.h
@@ -162,6 +162,7 @@ typedef struct GPENCIL_tLayer {
   DRWPass *blend_ps;
   /** Layer id of the mask. */
   BLI_bitmap *mask_bits;
+  BLI_bitmap *mask_invert_bits;
   /** Index in the layer list. Used as id for masking. */
   int layer_id;
 } GPENCIL_tLayer;
@@ -198,6 +199,8 @@ 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;
+  /* Invert mask buffer content. */
+  struct DRWPass *mask_invert_ps;
   /* Anti-Aliasing. */
   struct DRWPass *smaa_edge_ps;
   struct DRWPass *smaa_weight_ps;
@@ -377,6 +380,7 @@ struct GPUShader *GPENCIL_shader_geometry_get(void);
 struct GPUShader *GPENCIL_shader_composite_get(void);
 struct GPUShader *GPENCIL_shader_layer_blend_get(void);
 struct GPUShader *GPENCIL_shader_layer_mask_get(void);
+struct GPUShader *GPENCIL_shader_mask_invert_get(void);
 struct GPUShader *GPENCIL_shader_depth_merge_get(void);
 struct GPUShader *GPENCIL_shader_fx_blur_get(void);
 struct GPUShader *GPENCIL_shader_fx_colorize_get(void);
diff --git a/source/blender/draw/engines/gpencil/gpencil_shader.c b/source/blender/draw/engines/gpencil/gpencil_shader.c
index a2830fe5ec6..1cd1ffca333 100644
--- a/source/blender/draw/engines/gpencil/gpencil_shader.c
+++ b/source/blender/draw/engines/gpencil/gpencil_shader.c
@@ -30,6 +30,7 @@ extern char datatoc_gpencil_antialiasing_frag_glsl[];
 extern char datatoc_gpencil_antialiasing_vert_glsl[];
 extern char datatoc_gpencil_composite_frag_glsl[];
 extern char datatoc_gpencil_layer_blend_frag_glsl[];
+extern char datatoc_gpencil_mask_invert_frag_glsl[];
 extern char datatoc_gpencil_depth_merge_frag_glsl[];
 extern char datatoc_gpencil_depth_merge_vert_glsl[];
 extern char datatoc_gpencil_vfx_frag_glsl[];
@@ -50,6 +51,8 @@ static struct {
   GPUShader *layer_blend_sh;
   /* Merge the final object depth to the depth buffer. */
   GPUShader *depth_merge_sh;
+  /* Invert the content of the mask buffer. */
+  GPUShader *mask_invert_sh;
   /* Effects. */
   GPUShader *fx_composite_sh;
   GPUShader *fx_colorize_sh;
@@ -182,6 +185,15 @@ GPUShader *GPENCIL_shader_layer_blend_get(void)
   return g_shaders.layer_blend_sh;
 }
 
+GPUShader *GPENCIL_shader_mask_invert_get(void)
+{
+  if (!g_shaders.mask_invert_sh) {
+    g_shaders.mask_invert_sh = DRW_shader_create_fullscreen(datatoc_gpencil_mask_invert_frag_glsl,
+                                                            NULL);
+  }
+  return g_shaders.mask_invert_sh;
+}
+
 GPUShader *GPENCIL_shader_depth_merge_get(void)
 {
   if (!g_shaders.depth_merge_sh) {
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_layer_blend_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_layer_blend_frag.glsl
index 5dd9aa5253a..019e55ec0cd 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_layer_blend_frag.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_layer_blend_frag.glsl
@@ -22,8 +22,7 @@ void main()
   /* Stroke only render mono-chromatic revealage. We convert to alpha. */
   color.a = 1.0 - textureLod(revealBuf, uvcoordsvar.xy, 0).r;
 
-  float mask = textureLod(maskBuf, uvcoordsvar.xy, 0).r;
-  mask = (!maskInvert) ? (1.0 - mask) : mask;
+  float mask = 1.0 - textureLod(maskBuf, uvcoordsvar.xy, 0).r;
   mask *= blendOpacity;
 
   fragColor = vec4(1.0, 0.0, 1.0, 1.0);
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_mask_invert_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_mask_invert_frag.glsl
new file mode 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list