[Bf-blender-cvs] [3adcfeac960] greasepencil-refactor: GPencil: Refactor: Implement Stroke self overlap option

Clément Foucault noreply at git.blender.org
Thu Dec 12 22:33:41 CET 2019


Commit: 3adcfeac9601622fd5de8cf9e32739a1c383cb41
Author: Clément Foucault
Date:   Thu Dec 12 21:28:03 2019 +0100
Branches: greasepencil-refactor
https://developer.blender.org/rB3adcfeac9601622fd5de8cf9e32739a1c383cb41

GPencil: Refactor: Implement Stroke self overlap option

This is a novel approach were we use the depth buffer instead of the
stencil buffer. This allows up to ~1e24 different indices to draw to.
We use a DRW_STATE_DEPTH_GREATER to discard the fragment comming from the
same stroke.

Since we can have strokes that don't have this option, we use the point
indices instead of the stroke index to avoid changing the state during
drawing.

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

M	source/blender/draw/engines/gpencil/gpencil_cache_utils.c
M	source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
M	source/blender/draw/engines/gpencil/gpencil_draw_data.c
M	source/blender/draw/engines/gpencil/gpencil_engine.c
M	source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl
M	source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl

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

diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
index ea244feae8d..729ae0dcfa1 100644
--- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
@@ -65,6 +65,9 @@ GPENCIL_tLayer *gpencil_layer_cache_add_new(GPENCIL_PrivateData *pd,
   if (GPENCIL_3D_DRAWMODE(ob, gpd)) {
     state |= DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
   }
+  else {
+    state |= DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_GREATER;
+  }
   tgp_layer->geom_ps = DRW_pass_create("GPencil Layer", state);
 
   return tgp_layer;
diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
index 630cd55135c..695a959c6f6 100644
--- a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
+++ b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
@@ -68,7 +68,7 @@ static GPUVertBuf *gpencil_dummy_buffer_get(void)
 /* MUST match the format below. */
 typedef struct gpStrokeVert {
   /** Mat is float because we need to pack other float attribs with it. */
-  float mat, strength;
+  float mat, strength, stroke_id, point_id;
   /** Position and thickness packed in the same attribute. */
   float pos[3], thickness;
   float col[4];
@@ -80,7 +80,7 @@ static GPUVertFormat *gpencil_stroke_format(void)
 {
   static GPUVertFormat format = {0};
   if (format.attr_len == 0) {
-    GPU_vertformat_attr_add(&format, "ma", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+    GPU_vertformat_attr_add(&format, "ma", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
     GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
     GPU_vertformat_attr_add(&format, "col", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
     GPU_vertformat_attr_add(&format, "uv", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
@@ -109,16 +109,16 @@ static int gpencil_stroke_is_cyclic(const bGPDstroke *gps)
   return ((gps->flag & GP_STROKE_CYCLIC) != 0) && (gps->totpoints > 2);
 }
 
-static void gpencil_buffer_add_point(gpStrokeVert *verts,
-                                     const bGPDstroke *gps,
-                                     const bGPDspoint *pt,
-                                     bool is_endpoint)
+static void gpencil_buffer_add_point(
+    gpStrokeVert *verts, const bGPDstroke *gps, const bGPDspoint *pt, int v, bool is_endpoint)
 {
   copy_v3_v3(verts->pos, &pt->x);
   copy_v2_v2(verts->uv, pt->uv_fill);
   copy_v4_v4(verts->col, pt->mix_color);
   verts->strength = pt->strength;
   verts->u_stroke = pt->uv_fac;
+  verts->stroke_id = gps->runtime.stroke_start;
+  verts->point_id = v;
   /* Rotation are in [-90°..90°] range, so we can encode the sign of the angle + the cosine
    * because the cosine will always be positive. */
   verts->v_rot = cosf(pt->uv_rot) * signf(pt->uv_rot);
@@ -136,18 +136,18 @@ static void gpencil_buffer_add_stroke(gpStrokeVert *verts, const bGPDstroke *gps
 
   /* First point for adjacency (not drawn). */
   int adj_idx = (is_cyclic) ? (pts_len - 1) : 1;
-  gpencil_buffer_add_point(&verts[v++], gps, &pts[adj_idx], true);
+  gpencil_buffer_add_point(&verts[v++], gps, &pts[adj_idx], v, true);
 
   for (int i = 0; i < pts_len; i++) {
-    gpencil_buffer_add_point(&verts[v++], gps, &pts[i], false);
+    gpencil_buffer_add_point(&verts[v++], gps, &pts[i], v, false);
   }
   /* Draw line to first point to complete the loop for cyclic strokes. */
   if (is_cyclic) {
-    gpencil_buffer_add_point(&verts[v++], gps, &pts[0], false);
+    gpencil_buffer_add_point(&verts[v++], gps, &pts[0], v, false);
   }
   /* Last adjacency point (not drawn). */
   adj_idx = (is_cyclic) ? 1 : (pts_len - 2);
-  gpencil_buffer_add_point(&verts[v++], gps, &pts[adj_idx], true);
+  gpencil_buffer_add_point(&verts[v++], gps, &pts[adj_idx], v, true);
 }
 
 static void gpencil_buffer_add_fill(GPUIndexBufBuilder *ibo, const bGPDstroke *gps)
diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_data.c b/source/blender/draw/engines/gpencil/gpencil_draw_data.c
index 7784a092f3d..eec037041f5 100644
--- a/source/blender/draw/engines/gpencil/gpencil_draw_data.c
+++ b/source/blender/draw/engines/gpencil/gpencil_draw_data.c
@@ -130,6 +130,10 @@ GPENCIL_MaterialPool *gpencil_material_pool_create(GPENCIL_PrivateData *pd, Obje
       }
     }
 
+    if ((gp_style->mode != GP_STYLE_MODE_LINE) || (gp_style->flag & GP_STYLE_DISABLE_STENCIL)) {
+      mat_data->flag |= GP_STROKE_OVERLAP;
+    }
+
     /* Stroke Style */
     if ((gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) && (gp_style->sima)) {
       /* TODO finish. */
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index 93831e02360..f5f157f8e55 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -768,6 +768,7 @@ static void gp_layer_cache_populate(bGPDlayer *gpl,
   GPUUniformBuffer *ubo_mat;
   gpencil_material_resources_get(iter->matpool, 0, NULL, NULL, &ubo_mat);
 
+  const bool is_stroke_order_3D = (gpd->draw_mode == GP_DRAWMODE_3D);
   const bool is_screenspace = (gpd->flag & GP_DATA_STROKE_KEEPTHICKNESS) != 0;
 
   float object_scale = mat4_to_scale(iter->ob->obmat);
@@ -780,6 +781,7 @@ static void gp_layer_cache_populate(bGPDlayer *gpl,
   DRW_shgroup_uniform_block(iter->grp, "gpMaterialBlock", ubo_mat);
   DRW_shgroup_uniform_texture(iter->grp, "gpFillTexture", iter->tex_fill);
   DRW_shgroup_uniform_texture(iter->grp, "gpStrokeTexture", iter->tex_stroke);
+  DRW_shgroup_uniform_bool_copy(iter->grp, "strokeOrder3D", is_stroke_order_3D);
   DRW_shgroup_uniform_vec4_copy(iter->grp, "gpModelMatrix[0]", iter->ob->obmat[0]);
   DRW_shgroup_uniform_vec4_copy(iter->grp, "gpModelMatrix[1]", iter->ob->obmat[1]);
   DRW_shgroup_uniform_vec4_copy(iter->grp, "gpModelMatrix[2]", iter->ob->obmat[2]);
@@ -791,6 +793,9 @@ static void gp_layer_cache_populate(bGPDlayer *gpl,
   DRW_shgroup_uniform_float_copy(iter->grp, "thicknessWorldScale", thickness_scale);
   DRW_shgroup_uniform_float_copy(iter->grp, "vertexColorOpacity", gpl->vertex_paint_opacity);
   DRW_shgroup_uniform_vec4_copy(iter->grp, "layerTint", gpl->tintcolor);
+  /* Should do this clear for the whole object. */
+  float clear_depth = is_stroke_order_3D ? 1.0f : 0.0f;
+  DRW_shgroup_clear_framebuffer(iter->grp, GPU_DEPTH_BIT, 0, 0, 0, 0, clear_depth, 0);
 }
 
 static void gp_stroke_cache_populate(bGPDlayer *UNUSED(gpl),
@@ -801,11 +806,6 @@ static void gp_stroke_cache_populate(bGPDlayer *UNUSED(gpl),
   gpIterPopulateData *iter = (gpIterPopulateData *)thunk;
 
   MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(iter->ob, gps->mat_nr + 1);
-  /* if the user switch used material from data to object,
-   * the material could not be available */
-  if (gp_style == NULL) {
-    return;
-  }
 
   bool hide_material = (gp_style->flag & GP_STYLE_COLOR_HIDE) != 0;
   bool show_stroke = (gp_style->flag & GP_STYLE_STROKE_SHOW) != 0;
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl
index 554d9389a9f..27c5622302b 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl
@@ -6,6 +6,7 @@ in vec4 finalColorMul;
 in vec4 finalColorAdd;
 in vec2 finalUvs;
 flat in int matFlag;
+flat in float depth;
 
 out vec4 fragColor;
 
@@ -44,4 +45,15 @@ void main()
   if (fragColor.a < 0.001) {
     discard;
   }
+
+  /* We override the fragment depth using the fragment shader to ensure a constant value.
+   * This has a cost as the depth test cannot happen early.
+   * We could do this in the vertex shader but then perspective interpolation of uvs and
+   * fragment clipping gets really complicated. */
+  if (depth >= 0.0) {
+    gl_FragDepth = depth;
+  }
+  else {
+    gl_FragDepth = gl_FragCoord.z;
+  }
 }
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl
index d9369f2c3f7..45d17f090a1 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl
@@ -5,6 +5,7 @@ uniform vec2 sizeViewportInv;
 
 /* Per Object */
 uniform vec4 gpModelMatrix[4];
+uniform bool strokeOrder3D;
 uniform float thicknessScale;
 uniform float thicknessWorldScale;
 #define thicknessIsScreenSpace (thicknessWorldScale < 0.0)
@@ -14,10 +15,12 @@ uniform float thicknessOffset;
 uniform float vertexColorOpacity;
 uniform vec4 layerTint;
 
-in vec2 ma1;
-in vec2 ma2;
+in vec4 ma1;
+in vec4 ma2;
 #define strength1 ma1.y
 #define strength2 ma2.y
+#define stroke_id1 ma1.z
+#define point_id1 ma1.w
 /* Position contains thickness in 4th component. */
 in vec4 pos;  /* Prev adj vert */
 in vec4 pos1; /* Current edge */
@@ -36,6 +39,7 @@ out vec4 finalColorMul;
 out vec4 finalColorAdd;
 out vec2 finalUvs;
 flat out int matFlag;
+flat out float depth;
 
 void discard_vert()
 {
@@ -213,6 +217,24 @@ void stroke_vertex()
   if (!is_dot) {
     finalUvs.x = (use_curr) ? uv1.z : uv2.z;
   }
+
+  if (strokeOrder3D) {
+    /* Use the fragment depth (see fragment shader). */
+    depth = -1.0;
+  }
+  else if (GP_FLAG_TEST(materials[m].flag, GP_STROKE_OVERLAP)) {
+    /* Use the index of the point as depth.
+     * This means the stroke can overlap itself. */
+    depth = (point_id1 + 1.0) * 0.0000002;
+  }
+  else {
+    /* Use the index of first point of the stroke as depth.
+     * We render using a greater depth test this means the stroke
+     * cannot overlap itself.
+     * We offset by one so that the fill can be overlapped by its stroke.
+     * The offset is ok since we pad the strokes data because of adjacency infos. */
+    depth = (stroke_id1 + 1.0) * 0.0000002;
+  }
 }
 
 void fill_vertex()
@@ -235,6 +257,15 @@ void fill_vertex()
   vec2 loc = materials[m].fill_uv_offset.xy;
   mat2x2 rot_scale = mat2x2(materials[m].fill_uv_rot_scale.xy, materials[m].fill_uv_rot_scale.zw);
   finalUvs = rot_scale * uv1.xy + loc;
+
+  if (strokeOrder3D) {
+

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list