[Bf-blender-cvs] [a5e6e56a6d3] greasepencil-refactor: GPencil: Refactor: Draw gpencil strokes using instanced quad

Clément Foucault noreply at git.blender.org
Sun Dec 8 01:39:09 CET 2019


Commit: a5e6e56a6d32918119a1ee66f295400847a24851
Author: Clément Foucault
Date:   Sun Dec 8 01:23:17 2019 +0100
Branches: greasepencil-refactor
https://developer.blender.org/rBa5e6e56a6d32918119a1ee66f295400847a24851

GPencil: Refactor: Draw gpencil strokes using instanced quad

Using the instance range drawing (DRW) & the attrib multiload (GPU) we
use the instancing of quad geometry to draw arbitrary thick lines using
only the vertex shader.

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

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_frag.glsl
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 f4fd90f6e92..67e3635b880 100644
--- a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
+++ b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
@@ -69,9 +69,9 @@ static GPUVertBuf *gpencil_dummy_buffer_get(void)
 typedef struct gpStrokeVert {
   int mat;
   float pos[3];
-  float color[4];
-  float thickness;
-  float uvdata[2];
+  // float col[4];
+  // float rad;
+  // float uv[2];
 } gpStrokeVert;
 
 static GPUVertFormat *gpencil_stroke_format(void)
@@ -79,11 +79,13 @@ static GPUVertFormat *gpencil_stroke_format(void)
   static GPUVertFormat format = {0};
   if (format.attr_len == 0) {
     /* TODO Try reducing format size. */
-    GPU_vertformat_attr_add(&format, "mat", GPU_COMP_U32, 1, GPU_FETCH_INT);
+    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, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
-    GPU_vertformat_attr_add(&format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
-    GPU_vertformat_attr_add(&format, "uvdata", GPU_COMP_F32, 2, 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);
   }
   return &format;
 }
@@ -184,7 +186,7 @@ static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache)
     gpIterData iter = {
         .verts = NULL,
         .ibo = {0},
-        .vert_len = 0,
+        .vert_len = 1, /* Start at 1 for the gl_InstanceID trick to work (see vert shader). */
         .tri_len = 0,
     };
     gpencil_object_visible_stroke_iter(ob, NULL, gp_object_verts_count_cb, &iter);
@@ -192,7 +194,8 @@ static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache)
     /* Create VBO. */
     GPUVertFormat *format = gpencil_stroke_format();
     cache->vbo = GPU_vertbuf_create_with_format(format);
-    GPU_vertbuf_data_alloc(cache->vbo, iter.vert_len);
+    /* Add extra space at the end of the buffer because of quad load. */
+    GPU_vertbuf_data_alloc(cache->vbo, iter.vert_len + 2);
     iter.verts = (gpStrokeVert *)cache->vbo->data;
     /* Create IBO. */
     GPU_indexbuf_init(&iter.ibo, GPU_PRIM_TRIS, iter.tri_len, iter.vert_len);
@@ -205,7 +208,8 @@ static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache)
 
     /* Create the batches */
     cache->fill_batch = GPU_batch_create(GPU_PRIM_TRIS, cache->vbo, cache->ibo);
-    cache->stroke_batch = GPU_batch_create(GPU_PRIM_LINE_STRIP, cache->vbo, NULL);
+    cache->stroke_batch = GPU_batch_create(GPU_PRIM_TRI_STRIP, gpencil_dummy_buffer_get(), NULL);
+    GPU_batch_instbuf_add_ex(cache->stroke_batch, cache->vbo, 0);
 
     gpd->flag &= ~GP_DATA_CACHE_IS_DIRTY;
     cache->is_dirty = false;
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index 388f8e5aa71..4d527265aa3 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -743,6 +743,8 @@ static void gp_layer_cache_populate(bGPDlayer *layer,
 
   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());
 }
 
 static void gp_stroke_cache_populate(bGPDlayer *UNUSED(layer),
@@ -752,12 +754,23 @@ static void gp_stroke_cache_populate(bGPDlayer *UNUSED(layer),
 {
   gpIterPopulateData *iter = (gpIterPopulateData *)thunk;
 
-  GPUBatch *geom = GPENCIL_batch_cache_strokes(iter->ob, iter->pd->cfra);
-  /* Don't skip start adjacent vert. */
-  int vfirst = stroke->runtime.stroke_start;
-  /* Include "potential" cyclic vertex and start adj vertex (see shader). */
-  int vcount = stroke->totpoints + 1 + 1;
-  DRW_shgroup_call_range(iter->grp, geom, vfirst, vcount);
+  MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(iter->ob, stroke->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 show_stroke = (gp_style->flag & GP_STYLE_STROKE_SHOW) != 0;
+
+  if (show_stroke) {
+    GPUBatch *geom = GPENCIL_batch_cache_strokes(iter->ob, iter->pd->cfra);
+    /* Start one vert before to have gl_InstanceID > 0 (see shader). */
+    int vfirst = stroke->runtime.stroke_start - 1;
+    /* Include "potential" cyclic vertex and start adj vertex (see shader). */
+    int vcount = stroke->totpoints + 1 + 1;
+    DRW_shgroup_call_instance_range(iter->grp, geom, vfirst, vcount);
+  }
 }
 
 static void GPENCIL_cache_populate_new(void *ved, Object *ob)
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl
index 9447dfe6acd..7f39c3254ae 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl
@@ -1,7 +1,9 @@
 
+in vec4 finalColor;
+
 out vec4 fragColor;
 
 void main()
 {
-  fragColor = vec4(1.0);
+  fragColor = finalColor;
 }
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl
index 190115cf0d8..cd7b520a2c2 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl
@@ -1,13 +1,61 @@
 
-in int mat;
-in vec3 pos;
+/* TODO UBO */
+uniform vec2 sizeViewport;
+uniform vec2 sizeViewportInv;
+
+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 */
+
+out vec4 finalColor;
+
+void discard_vert()
+{
+  /* We set the vertex at the camera origin to generate 0 fragments. */
+  gl_Position = vec4(0.0, 0.0, -3e36, 0.0);
+}
+
+vec2 project_to_screenspace(vec4 v)
+{
+  return ((v.xy / v.w) * 0.5 + 0.5) * sizeViewport;
+}
 
 void main()
 {
-  gl_Position = point_world_to_ndc(pos);
+  /* Trick to detect if a drawcall is stroke or fill. */
+  bool is_fill = (gl_InstanceID == 0);
 
-  if (mat == -1) {
+  if (!is_fill) {
     /* Enpoints, we discard the vertices. */
-    gl_Position = vec4(0.0, 0.0, -3e36, 0.0);
+    if (ma1 == -1 || ma2 == -1) {
+      discard_vert();
+      return;
+    }
+
+    /* Avoid using a vertex attrib for quad positioning. */
+    float x = float((gl_VertexID & 1));
+    float y = float((gl_VertexID & 2) >> 1);
+
+    vec4 ndc1 = point_world_to_ndc(pos1);
+    vec4 ndc2 = point_world_to_ndc(pos2);
+
+    /* TODO case where ndc2 is behind camera */
+    vec2 ss1 = project_to_screenspace(ndc1);
+    vec2 ss2 = project_to_screenspace(ndc2);
+    vec2 perp = normalize(ss2 - ss1);
+    perp = vec2(-perp.y, perp.x);
+
+    gl_Position = (x == 0.0) ? ndc1 : ndc2;
+    gl_Position.xy += perp * (y - 0.5) * sizeViewportInv.xy * gl_Position.w * 10.0;
+
+    finalColor = vec4(0.0, 0.0, 0.0, 1.0);
+  }
+  else {
+    gl_Position = point_world_to_ndc(pos1);
+
+    finalColor = vec4(1.0);
   }
 }



More information about the Bf-blender-cvs mailing list