[Bf-blender-cvs] [32b8eab5cfa] greasepencil-refactor: GPencil: Refactor: Add thickness support

Clément Foucault noreply at git.blender.org
Mon Dec 9 02:30:43 CET 2019


Commit: 32b8eab5cfa692fdb8ee56acc895cfe2e55aba51
Author: Clément Foucault
Date:   Sun Dec 8 22:52:51 2019 +0100
Branches: greasepencil-refactor
https://developer.blender.org/rB32b8eab5cfa692fdb8ee56acc895cfe2e55aba51

GPencil: Refactor: Add thickness support

This add CORRECT support for worldspace thickness to GPencil stroke.

However it does not perfectly match old implementation which was buggy.

Mitigation could be done via doversion but it is not the goal of this
commit.

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

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

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

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 171c3ff4e5f..b3364d113dd 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,8 @@ static GPUVertBuf *gpencil_dummy_buffer_get(void)
 /* MUST match the format below. */
 typedef struct gpStrokeVert {
   int mat;
-  float pos[3];
+  /** Position and thickness packed in the same attribute. */
+  float pos[3], thickness;
   // float col[4];
   // float rad;
   // float uv[2];
@@ -80,9 +81,8 @@ static GPUVertFormat *gpencil_stroke_format(void)
   if (format.attr_len == 0) {
     /* TODO Try reducing format size. */
     GPU_vertformat_attr_add(&format, "ma", GPU_COMP_I32, 1, GPU_FETCH_INT);
-    GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, 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, "rad", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
     // GPU_vertformat_attr_add(&format, "uv", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
     /* IMPORTANT: This means having only 4 attributes to fit into opengl limit of 16 attrib. */
     GPU_vertformat_multiload_enable(&format, 4);
@@ -109,10 +109,16 @@ static int gpencil_stroke_is_cyclic(const bGPDstroke *stroke)
   return ((stroke->flag & GP_STROKE_CYCLIC) != 0) && (stroke->totpoints > 2);
 }
 
-static void gpencil_buffer_add_point(gpStrokeVert *verts, const bGPDspoint *pt, bool is_endpoint)
+static void gpencil_buffer_add_point(gpStrokeVert *verts,
+                                     const bGPDstroke *stroke,
+                                     const bGPDspoint *pt,
+                                     bool is_endpoint)
 {
+  // float obscale = mat4_to_scale(ob->obmat);
+  // short lthick = brush->size * obscale;
   /* TODO other attribs */
   copy_v3_v3(verts->pos, &pt->x);
+  verts->thickness = stroke->thickness * pt->pressure;
   /* Tag endpoint material to -1 so they get discarded by vertex shader. */
   verts->mat = (is_endpoint) ? -1 : 0;
 }
@@ -126,18 +132,18 @@ static void gpencil_buffer_add_stroke(gpStrokeVert *verts, const bGPDstroke *str
 
   /* First point for adjacency (not drawn). */
   int adj_idx = (is_cyclic) ? (pts_len - 1) : 1;
-  gpencil_buffer_add_point(&verts[v++], &pts[adj_idx], true);
+  gpencil_buffer_add_point(&verts[v++], stroke, &pts[adj_idx], true);
 
   for (int i = 0; i < pts_len; i++) {
-    gpencil_buffer_add_point(&verts[v++], &pts[i], false);
+    gpencil_buffer_add_point(&verts[v++], stroke, &pts[i], false);
   }
   /* Draw line to first point to complete the loop for cyclic strokes. */
   if (is_cyclic) {
-    gpencil_buffer_add_point(&verts[v++], &pts[0], false);
+    gpencil_buffer_add_point(&verts[v++], stroke, &pts[0], false);
   }
   /* Last adjacency point (not drawn). */
   adj_idx = (is_cyclic) ? 1 : (pts_len - 2);
-  gpencil_buffer_add_point(&verts[v++], &pts[adj_idx], true);
+  gpencil_buffer_add_point(&verts[v++], stroke, &pts[adj_idx], true);
 }
 
 static void gpencil_buffer_add_fill(GPUIndexBufBuilder *ibo, const bGPDstroke *stroke)
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index 57afb87049b..1870aa816d2 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -737,14 +737,25 @@ static void gp_layer_cache_populate(bGPDlayer *layer,
                                     void *thunk)
 {
   gpIterPopulateData *iter = (gpIterPopulateData *)thunk;
+  bGPdata *gpd = (bGPdata *)iter->ob->data;
 
   GPENCIL_tLayer *tgp_layer = gpencil_layer_cache_add_new(iter->pd, iter->ob, layer);
   BLI_LINKS_APPEND(&iter->tgp_ob->layers, tgp_layer);
 
+  const bool is_screenspace = (gpd->flag & GP_DATA_STROKE_KEEPTHICKNESS) != 0;
+
+  float object_scale = mat4_to_scale(iter->ob->obmat);
+  /* Negate thickness sign to tag that strokes are in screen space.
+   * Convert to world units (by default, 1 meter = 2000 px). */
+  float thickness_scale = (is_screenspace) ? -1.0f : (gpd->pixfactor / 2000.0f);
+
   struct GPUShader *sh = GPENCIL_shader_geometry_get(&en_data);
   iter->grp = DRW_shgroup_create(sh, tgp_layer->geom_ps);
   DRW_shgroup_uniform_vec2_copy(iter->grp, "sizeViewportInv", DRW_viewport_invert_size_get());
   DRW_shgroup_uniform_vec2_copy(iter->grp, "sizeViewport", DRW_viewport_size_get());
+  DRW_shgroup_uniform_float_copy(iter->grp, "thicknessScale", object_scale);
+  DRW_shgroup_uniform_float_copy(iter->grp, "thicknessOffset", (float)layer->line_change);
+  DRW_shgroup_uniform_float_copy(iter->grp, "thicknessWorldScale", thickness_scale);
 }
 
 static void gp_stroke_cache_populate(bGPDlayer *UNUSED(layer),
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl
index e65bf8d8298..b9abd914926 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl
@@ -3,12 +3,21 @@
 uniform vec2 sizeViewport;
 uniform vec2 sizeViewportInv;
 
+/* Per Object */
+uniform float thicknessScale;
+uniform float thicknessWorldScale;
+#define thicknessIsScreenSpace (thicknessWorldScale < 0.0)
+
+/* Per Layer */
+uniform float thicknessOffset;
+
 in int ma1;
 in int ma2;
-in vec3 pos;  /* Prev adj vert */
-in vec3 pos1; /* Current edge */
-in vec3 pos2; /* Current edge */
-in vec3 pos3; /* Next adj vert */
+/* Position contains thickness in 4th component. */
+in vec4 pos;  /* Prev adj vert */
+in vec4 pos1; /* Current edge */
+in vec4 pos2; /* Current edge */
+in vec4 pos3; /* Next adj vert */
 
 out vec4 finalColor;
 
@@ -38,13 +47,18 @@ void stroke_vertex()
   }
 
   /* Avoid using a vertex attrib for quad positioning. */
-  float x = float((gl_VertexID & 1));
-  float y = float((gl_VertexID & 2) >> 1);
+  float x = float(gl_VertexID & 1);       /* [0..1] */
+  float y = float(gl_VertexID & 2) - 1.0; /* [-1..1] */
+
+  vec3 wpos_adj = (x == 0.0) ? pos.xyz : pos3.xyz;
+  vec3 wpos1 = pos1.xyz;
+  vec3 wpos2 = pos2.xyz;
 
-  vec3 pos_adj = (x == 0.0) ? pos : pos3;
-  vec4 ndc_adj = point_world_to_ndc(pos_adj);
-  vec4 ndc1 = point_world_to_ndc(pos1);
-  vec4 ndc2 = point_world_to_ndc(pos2);
+  vec4 ndc_adj = point_world_to_ndc(wpos_adj);
+  vec4 ndc1 = point_world_to_ndc(wpos1);
+  vec4 ndc2 = point_world_to_ndc(wpos2);
+
+  gl_Position = (x == 0.0) ? ndc1 : ndc2;
 
   /* TODO case where ndc1 & ndc2 is behind camera */
   vec2 ss_adj = project_to_screenspace(ndc_adj);
@@ -59,8 +73,26 @@ void stroke_vertex()
 
   vec2 miter = rotate_90deg(miter_tan / miter_dot);
 
-  gl_Position = (x == 0.0) ? ndc1 : ndc2;
-  gl_Position.xy += miter * (y - 0.5) * sizeViewportInv.xy * gl_Position.w * 10.0;
+  /* Position contains thickness in 4th component. */
+  float thickness = (x == 0.0) ? pos1.w : pos2.w;
+  /* Modify stroke thickness by object and layer factors.-*/
+  thickness *= thicknessScale;
+  thickness += thicknessOffset;
+  thickness = max(1.0, thickness);
+
+  if (thicknessIsScreenSpace) {
+    /* Multiply offset by view Z so that offset is constant in screenspace.
+     * (e.i: does not change with the distance to camera) */
+    thickness *= gl_Position.w;
+  }
+  else {
+    /* World space point size. */
+    thickness *= thicknessWorldScale * ProjectionMatrix[1][1] * sizeViewport.y;
+  }
+  /* Multiply scalars first. */
+  y *= thickness;
+
+  gl_Position.xy += miter * sizeViewportInv.xy * y;
 
   finalColor = vec4(0.0, 0.0, 0.0, 1.0);
 }
@@ -72,7 +104,8 @@ void dots_vertex()
 
 void fill_vertex()
 {
-  gl_Position = point_world_to_ndc(pos1);
+  vec3 wpos = pos1.xyz;
+  gl_Position = point_world_to_ndc(wpos);
   gl_Position.z += 1e-2;
 
   finalColor = vec4(1.0);



More information about the Bf-blender-cvs mailing list