[Bf-blender-cvs] [10f2e39f480] greasepencil-refactor: GPencil: Refactor: New linked mask system

Clément Foucault noreply at git.blender.org
Fri Feb 7 23:44:03 CET 2020


Commit: 10f2e39f4803ca4f1110f3866e7aae1ac29acc95
Author: Clément Foucault
Date:   Fri Feb 7 23:43:36 2020 +0100
Branches: greasepencil-refactor
https://developer.blender.org/rB10f2e39f4803ca4f1110f3866e7aae1ac29acc95

GPencil: Refactor: New linked mask system

The new system is more flexible and a bit simpler from the code side.

Each layer has a mask layer slot. If filled with a correct layer name,
the mask layer will be rendered again in a separate buffer. This buffer
will then be used in the blend pass to modulate the opacity of the layer.

This approach is not 100% equivalent to the standard layering in most 2D
applications if using varying alpha on a mask applied to multiple layers.
However this technique does support any ordering arrangement of the masks.

The layers used as mask can now still render normaly.

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

M	source/blender/blenkernel/BKE_gpencil.h
M	source/blender/blenkernel/intern/gpencil.c
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
D	source/blender/draw/engines/gpencil/shaders/gpencil_layer_mask_frag.glsl

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

diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h
index 495fe4eb7f6..f19af3cb1b7 100644
--- a/source/blender/blenkernel/BKE_gpencil.h
+++ b/source/blender/blenkernel/BKE_gpencil.h
@@ -179,6 +179,7 @@ struct bGPDframe *BKE_gpencil_layer_frame_get(struct bGPDlayer *gpl,
 struct bGPDframe *BKE_gpencil_layer_frame_find(struct bGPDlayer *gpl, int cframe);
 bool BKE_gpencil_layer_frame_delete(struct bGPDlayer *gpl, struct bGPDframe *gpf);
 
+struct bGPDlayer *BKE_gpencil_layer_named_get(struct bGPdata *gpd, const char *name);
 struct bGPDlayer *BKE_gpencil_layer_active_get(struct bGPdata *gpd);
 void BKE_gpencil_layer_active_set(struct bGPdata *gpd, struct bGPDlayer *active);
 void BKE_gpencil_layer_delete(struct bGPdata *gpd, struct bGPDlayer *gpl);
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index 2b58525396b..02cbbcc4060 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -1002,6 +1002,14 @@ bool BKE_gpencil_layer_frame_delete(bGPDlayer *gpl, bGPDframe *gpf)
   return changed;
 }
 
+bGPDlayer *BKE_gpencil_layer_named_get(bGPdata *gpd, const char *name)
+{
+  if (name[0] == '\0') {
+    return NULL;
+  }
+  return BLI_findstring(&gpd->layers, name, offsetof(bGPDlayer, info));
+}
+
 /* get the active gp-layer for editing */
 bGPDlayer *BKE_gpencil_layer_active_get(bGPdata *gpd)
 {
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 5d11578fe19..46fce6341f0 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -283,7 +283,6 @@ 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_layer_mask_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 ae8ac611570..6b4e017c96b 100644
--- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
@@ -115,6 +115,7 @@ GPENCIL_tLayer *gpencil_layer_cache_add(GPENCIL_PrivateData *pd, Object *ob, bGP
   const bool is_obact = ((pd->obact) && (pd->obact == ob));
   const bool is_fade = ((pd->fade_layer_opacity > -1.0f) && (is_obact) &&
                         ((gpl->flag & GP_LAYER_ACTIVE) == 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. */
@@ -127,28 +128,21 @@ GPENCIL_tLayer *gpencil_layer_cache_add(GPENCIL_PrivateData *pd, Object *ob, bGP
       fade_layer_opacity = pd->fade_gp_object_opacity;
     }
   }
+
   bGPdata *gpd = (bGPdata *)ob->data;
   GPENCIL_tLayer *tgp_layer = BLI_memblock_alloc(pd->gp_layer_pool);
+  tgp_layer->layer_id = BLI_findindex(&gpd->layers, gpl);
+  tgp_layer->mask_id = -1;
 
-  const bool is_mask = (gpl->flag & GP_LAYER_USE_MASK) != 0;
-  tgp_layer->is_mask = is_mask;
-  tgp_layer->do_masked_clear = false;
-
-  if (!is_mask) {
-    tgp_layer->is_masked = false;
-    for (bGPDlayer *gpl_m = gpl->next; gpl_m; gpl_m = gpl_m->next) {
-      if (gpl_m->flag & GP_LAYER_USE_MASK) {
-        if (gpl_m->flag & GP_LAYER_HIDE) {
-          /* We don't mask but we dont try to mask with further layers. */
-        }
-        else {
-          tgp_layer->is_masked = true;
-        }
-        break;
-      }
-    }
+  bGPDlayer *gpl_mask = BKE_gpencil_layer_named_get(gpd, gpl->mask_layer);
+  if (gpl_mask && (gpl_mask != gpl) && ((gpl_mask->flag & GP_LAYER_HIDE) == 0)) {
+    mask_invert = (gpl->flag & GP_LAYER_MASK_INVERT) != 0;
+    tgp_layer->mask_id = BLI_findindex(&gpd->layers, gpl_mask);
+    pd->use_mask_fb = true;
   }
 
+  const bool is_masked = tgp_layer->mask_id != -1;
+
   {
     DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA_PREMUL;
     if (GPENCIL_3D_DRAWMODE(ob, gpd) || pd->draw_depth_only) {
@@ -160,42 +154,13 @@ GPENCIL_tLayer *gpencil_layer_cache_add(GPENCIL_PrivateData *pd, Object *ob, bGP
       state |= DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_GREATER;
     }
 
-    if (gpl->flag & GP_LAYER_USE_MASK) {
-      state |= DRW_STATE_STENCIL_EQUAL;
-    }
-    else {
-      state |= DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_ALWAYS;
-    }
+    /* Always write stencil. Only used as optimization for blending. */
+    state |= DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_ALWAYS;
 
     tgp_layer->geom_ps = DRW_pass_create("GPencil Layer", state);
   }
 
-  if (is_mask) {
-    DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_EQUAL | DRW_STATE_BLEND_MUL;
-    tgp_layer->blend_ps = DRW_pass_create("GPencil Mask Layer", state);
-
-    GPUShader *sh = GPENCIL_shader_layer_mask_get();
-    DRWShadingGroup *grp = DRW_shgroup_create(sh, tgp_layer->blend_ps);
-    DRW_shgroup_uniform_int_copy(grp, "isFirstPass", true);
-    DRW_shgroup_uniform_float_copy(grp, "maskOpacity", fade_layer_opacity);
-    DRW_shgroup_uniform_bool_copy(grp, "maskInvert", gpl->flag & GP_LAYER_MASK_INVERT);
-    DRW_shgroup_uniform_texture_ref(grp, "colorBuf", &pd->color_masked_tx);
-    DRW_shgroup_uniform_texture_ref(grp, "revealBuf", &pd->reveal_masked_tx);
-    DRW_shgroup_uniform_texture_ref(grp, "maskBuf", &pd->reveal_layer_tx);
-    DRW_shgroup_stencil_mask(grp, 0xFF);
-    DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
-
-    /* We cannot do custom blending on MultiTarget framebuffers.
-     * Workaround by doing 2 passes. */
-    grp = DRW_shgroup_create_sub(grp);
-    DRW_shgroup_state_disable(grp, DRW_STATE_BLEND_MUL);
-    DRW_shgroup_state_enable(grp, DRW_STATE_BLEND_ADD_FULL);
-    DRW_shgroup_uniform_int_copy(grp, "isFirstPass", false);
-    DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
-
-    pd->use_mask_fb = true;
-  }
-  else if ((gpl->blend_mode != eGplBlendMode_Regular) || (fade_layer_opacity < 1.0f)) {
+  if (is_masked || (gpl->blend_mode != eGplBlendMode_Regular) || (fade_layer_opacity < 1.0f)) {
     DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_EQUAL;
     switch (gpl->blend_mode) {
       case eGplBlendMode_Regular:
@@ -227,6 +192,8 @@ GPENCIL_tLayer *gpencil_layer_cache_add(GPENCIL_PrivateData *pd, Object *ob, bGP
     DRW_shgroup_uniform_float_copy(grp, "blendOpacity", fade_layer_opacity);
     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);
 
@@ -248,3 +215,17 @@ GPENCIL_tLayer *gpencil_layer_cache_add(GPENCIL_PrivateData *pd, Object *ob, bGP
 
   return tgp_layer;
 }
+
+GPENCIL_tLayer *gpencil_layer_cache_get(GPENCIL_tObject *tgp_ob, int number)
+{
+  if (number >= 0) {
+    GPENCIL_tLayer *layer = tgp_ob->layers.first;
+    while (layer != NULL) {
+      if (layer->layer_id == number) {
+        return layer;
+      }
+      layer = layer->next;
+    }
+  }
+  return NULL;
+}
\ No newline at end of file
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index 8736857c45c..437988c66c1 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -438,14 +438,9 @@ static void gp_layer_cache_populate(bGPDlayer *gpl,
                             (gpl == iter->pd->sbuffer_layer);
   }
 
-  GPENCIL_tLayer *tgp_layer_prev = iter->tgp_ob->layers.last;
   GPENCIL_tLayer *tgp_layer = gpencil_layer_cache_add(iter->pd, iter->ob, gpl);
   BLI_LINKS_APPEND(&iter->tgp_ob->layers, tgp_layer);
 
-  if (tgp_layer->is_masked && (tgp_layer_prev == NULL || !tgp_layer_prev->is_masked)) {
-    tgp_layer->do_masked_clear = true;
-  }
-
   gpencil_material_resources_get(iter->matpool, 0, NULL, NULL, &iter->ubo_mat);
 
   const bool is_stroke_order_3d = (gpd->draw_mode == GP_DRAWMODE_3D) || iter->pd->draw_depth_only;
@@ -784,17 +779,22 @@ void GPENCIL_cache_finish(void *ved)
     }
 
     if (pd->use_mask_fb) {
-      /* We need to separate all the masked layer together in order to correctly mix them. */
-      pd->color_masked_tx = DRW_texture_pool_query_2d(
-          size[0], size[1], format, &draw_engine_gpencil_type);
-      pd->reveal_masked_tx = DRW_texture_pool_query_2d(
-          size[0], size[1], format, &draw_engine_gpencil_type);
-
-      GPU_framebuffer_ensure_config(&fbl->masked_fb,
+      /* We need an extra depth to not disturb the normal drawing.
+       * The color_tx is needed for framebuffer cmpleteness. */
+      GPUTexture *color_tx, *depth_tx;
+      depth_tx = DRW_texture_pool_query_2d(
+          size[0], size[1], GPU_DEPTH24_STENCIL8, &draw_engine_gpencil_type);
+      color_tx = DRW_texture_pool_query_2d(size[0], size[1], GPU_R8, &draw_engine_gpencil_type);
+      /* Use high quality format for render. */
+      eGPUTextureFormat mask_format = pd->is_render ? GPU_R16 : GPU_R8;
+      pd->mask_tx = DRW_texture_pool_query_2d(
+          size[0], size[1], mask_format, &draw_engine_gpencil_type);
+
+      GPU_framebuffer_ensure_config(&fbl->mask_fb,
                                     {
-                                        GPU_ATTACHMENT_TEXTURE(pd->depth_tx),
-                                        GPU_ATTACHMENT_TEXTURE(pd->color_masked_tx),
-                                        GPU_ATTACHMENT_TEXTURE(pd->reveal_masked_tx)

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list