[Bf-blender-cvs] [12034dc4aaf] greasepencil-refactor: GPencil: Refactor: Add new logic to create batches and store draw passes

Clément Foucault noreply at git.blender.org
Sat Dec 7 15:00:15 CET 2019


Commit: 12034dc4aafc0c623ef057b71473e6cd693044d2
Author: Clément Foucault
Date:   Sat Dec 7 14:56:27 2019 +0100
Branches: greasepencil-refactor
https://developer.blender.org/rB12034dc4aafc0c623ef057b71473e6cd693044d2

GPencil: Refactor: Add new logic to create batches and store draw passes

We introduce a new set of temp objects (GPENCIL_tVfx, GPENCIL_tLayer,
GPENCIL_tObject) allocated in BLI_memblocks to allow fast traversal and
easy memory management.

We also introduce an iterator to iterate over visible strokes of an object
to avoid code duplication.

Strokes are all in one batch and the fill batch will only contain indices
to the stroke buffer.

For now the objects are only drawn at the center only with white 1px stroke
and all strokes are not interupted (the finish at center).

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

M	source/blender/draw/CMakeLists.txt
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_utils.c
M	source/blender/draw/engines/gpencil/gpencil_engine.c
M	source/blender/draw/engines/gpencil/gpencil_engine.h
A	source/blender/draw/engines/gpencil/gpencil_shader.c
A	source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
A	source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl
A	source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl
M	source/blender/makesdna/DNA_gpencil_types.h

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

diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 931d8c058ce..940f93e1ef5 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -116,6 +116,7 @@ set(SRC
   engines/gpencil/gpencil_engine.c
   engines/gpencil/gpencil_engine.h
   engines/gpencil/gpencil_render.c
+  engines/gpencil/gpencil_shader.c
   engines/gpencil/gpencil_shader_fx.c
   engines/select/select_draw_utils.c
   engines/select/select_engine.c
@@ -273,6 +274,10 @@ data_to_c_simple(intern/shaders/common_fxaa_lib.glsl SRC)
 data_to_c_simple(intern/shaders/common_smaa_lib.glsl SRC)
 data_to_c_simple(intern/shaders/common_fullscreen_vert.glsl SRC)
 
+data_to_c_simple(engines/gpencil/shaders/gpencil_frag.glsl SRC)
+data_to_c_simple(engines/gpencil/shaders/gpencil_vert.glsl SRC)
+data_to_c_simple(engines/gpencil/shaders/gpencil_common_lib.glsl SRC)
+
 data_to_c_simple(engines/gpencil/shaders/gpencil_fill_vert.glsl SRC)
 data_to_c_simple(engines/gpencil/shaders/gpencil_fill_frag.glsl SRC)
 data_to_c_simple(engines/gpencil/shaders/gpencil_stroke_vert.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 f9df1342bf8..350c6ce003f 100644
--- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
@@ -33,12 +33,41 @@
 #include "BKE_gpencil.h"
 #include "BKE_object.h"
 
+#include "BLI_memblock.h"
+
 #include "gpencil_engine.h"
 
 #include "draw_cache_impl.h"
 
 #include "DEG_depsgraph.h"
 
+/* TODO remove the _new suffix. */
+GPENCIL_tObject *gpencil_object_cache_add_new(GPENCIL_Data *vedata, Object *UNUSED(ob))
+{
+  GPENCIL_PrivateData *pd = vedata->stl->pd;
+  GPENCIL_tObject *tgp_ob = BLI_memblock_alloc(pd->gp_object_pool);
+
+  tgp_ob->layers.first = tgp_ob->layers.last = NULL;
+  tgp_ob->vfx.first = tgp_ob->vfx.last = NULL;
+
+  return tgp_ob;
+}
+
+/* TODO remove the _new suffix. */
+GPENCIL_tLayer *gpencil_layer_cache_add_new(GPENCIL_Data *vedata,
+                                            Object *UNUSED(ob),
+                                            bGPDlayer *UNUSED(layer))
+{
+  // bGPdata *gpd = (bGPdata *)ob->data;
+  GPENCIL_PrivateData *pd = vedata->stl->pd;
+  GPENCIL_tLayer *tgp_layer = BLI_memblock_alloc(pd->gp_layer_pool);
+
+  DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
+  tgp_layer->geom_ps = DRW_pass_create("GPencil Layer", state);
+
+  return tgp_layer;
+}
+
 /* verify if exist a non instanced version of the object */
 static bool gpencil_has_noninstanced_object(Object *ob_instance)
 {
@@ -302,6 +331,12 @@ static void gpencil_batch_cache_clear(GpencilBatchCache *cache)
   MEM_SAFE_FREE(cache->grp_cache);
   cache->grp_size = 0;
   cache->grp_used = 0;
+
+  /* New code */
+  GPU_BATCH_DISCARD_SAFE(cache->fill_batch);
+  GPU_BATCH_DISCARD_SAFE(cache->stroke_batch);
+  GPU_VERTBUF_DISCARD_SAFE(cache->vbo);
+  GPU_INDEXBUF_DISCARD_SAFE(cache->ibo);
 }
 
 /* get cache */
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 30fc1896bbb..ef22161561f 100644
--- a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
+++ b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
@@ -41,6 +41,190 @@
 
 #include "gpencil_engine.h"
 
+/* -------------------------------------------------------------------- */
+/** \name Dummy vbos
+ *
+ * We need a dummy vbo containing the vertex count to draw instances ranges.
+ *
+ * \{ */
+
+static GPUVertBuf *gpencil_dummy_buffer_get(void)
+{
+  if (en_data.quad == NULL) {
+    GPUVertFormat format = {0};
+    GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_U8, 1, GPU_FETCH_INT);
+    en_data.quad = GPU_vertbuf_create_with_format(&format);
+    GPU_vertbuf_data_alloc(en_data.quad, 4);
+  }
+  return en_data.quad;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Vertex Formats.
+ * \{ */
+
+/* MUST match the format below. */
+typedef struct gpStrokeVert {
+  int mat;
+  float pos[3];
+  float color[4];
+  float thickness;
+  float uvdata[2];
+} gpStrokeVert;
+
+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, "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);
+  }
+  return &format;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Vertex Buffers.
+ * \{ */
+
+typedef struct gpIterData {
+  gpStrokeVert *verts;
+  GPUIndexBufBuilder ibo;
+  int vert_len;
+  int tri_len;
+  /** Index during vbo filling. */
+  int vidx;
+} gpIterData;
+
+static void gpencil_buffer_add_point(gpStrokeVert *verts, const bGPDspoint *pt)
+{
+  /* TODO other attribs */
+  copy_v3_v3(verts->pos, &pt->x);
+}
+
+static void gpencil_buffer_add_stroke(gpStrokeVert *verts, const bGPDstroke *stroke)
+{
+  const bGPDspoint *pts = stroke->points;
+  int pts_len = stroke->totpoints;
+  bool is_cyclic = ((stroke->flag & GP_STROKE_CYCLIC) != 0) && (pts_len > 2);
+  int v = 0;
+
+  /* First point for adjacency (not drawn). */
+  int adj_idx = (is_cyclic) ? (pts_len - 1) : 1;
+  gpencil_buffer_add_point(&verts[v++], &pts[adj_idx]);
+
+  for (int i = 0; i < pts_len; i++) {
+    gpencil_buffer_add_point(&verts[v++], &pts[i]);
+  }
+  /* Draw line to first point to complete the loop for cyclic strokes. */
+  if (is_cyclic) {
+    gpencil_buffer_add_point(&verts[v++], &pts[0]);
+  }
+  /* Last adjacency point (not drawn). */
+  adj_idx = (is_cyclic) ? 1 : (pts_len - 2);
+  gpencil_buffer_add_point(&verts[v++], &pts[adj_idx]);
+}
+
+static void gpencil_buffer_add_fill(GPUIndexBufBuilder *ibo,
+                                    int start_idx,
+                                    const bGPDstroke *stroke)
+{
+  /* TODO ibo filling. */
+  UNUSED_VARS(ibo, start_idx, stroke);
+}
+
+static void gpencil_stroke_iter_cb(bGPDlayer *UNUSED(layer),
+                                   bGPDframe *UNUSED(frame),
+                                   bGPDstroke *stroke,
+                                   void *thunk)
+{
+  gpIterData *iter = (gpIterData *)thunk;
+  bool is_fill = true; /* TODO */
+
+  gpencil_buffer_add_stroke(&iter->verts[iter->vidx], stroke);
+
+  if (is_fill) {
+    gpencil_buffer_add_fill(&iter->ibo, iter->vidx, stroke);
+  }
+
+  /* Consider strokes always cyclic, hence the +1. */
+  iter->vidx += stroke->totpoints + 2 + 1;
+  BLI_assert(iter->vidx <= iter->vert_len);
+}
+
+static void gp_object_verts_count_cb(bGPDlayer *UNUSED(layer),
+                                     bGPDframe *UNUSED(frame),
+                                     bGPDstroke *stroke,
+                                     void *thunk)
+{
+  gpIterData *iter = (gpIterData *)thunk;
+  /* Consider strokes always cyclic, hence the +1. */
+  iter->vert_len += stroke->totpoints + 2 + 1;
+  iter->tri_len += stroke->totpoints - 1;
+}
+
+static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache)
+{
+  if (cache->vbo == NULL) {
+    /* Should be discarded together. */
+    BLI_assert(cache->vbo == NULL && cache->ibo == NULL);
+    BLI_assert(cache->stroke_batch == NULL && cache->stroke_batch == NULL);
+
+    /* First count how many vertices and triangles are needed for the whole object. */
+    gpIterData iter = {
+        .verts = NULL,
+        .ibo = {0},
+        .vert_len = 0,
+        .tri_len = 0,
+        .vidx = 0,
+    };
+    gpencil_object_visible_stroke_iter(ob, gp_object_verts_count_cb, &iter);
+
+    /* Create VBO. */
+    GPUVertFormat *format = gpencil_stroke_format();
+    cache->vbo = GPU_vertbuf_create_with_format(format);
+    GPU_vertbuf_data_alloc(cache->vbo, iter.vert_len);
+    iter.verts = (gpStrokeVert *)cache->vbo->data;
+    /* Create IBO. */
+    GPU_indexbuf_init(&iter.ibo, GPU_PRIM_TRIS, iter.tri_len, iter.vert_len);
+
+    /* Fill buffers with data. */
+    gpencil_object_visible_stroke_iter(ob, gpencil_stroke_iter_cb, &iter);
+
+    /* Finish the IBO. */
+    cache->ibo = GPU_indexbuf_build(&iter.ibo);
+
+    /* 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);
+  }
+}
+
+GPUBatch *GPENCIL_batch_cache_strokes(Object *ob, int cfra)
+{
+  GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra);
+  gpencil_batches_ensure(ob, cache);
+
+  return cache->stroke_batch;
+}
+
+GPUBatch *GPENCIL_batch_cache_fills(Object *ob, int cfra)
+{
+  GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra);
+  gpencil_batches_ensure(ob, cache);
+
+  return cache->fill_batch;
+}
+
+/* ----------- End of new code ----------- */
+
 /* Helper to add stroke point to vbo */
 static void gpencil_set_stroke_point(GPUVertBuf *vbo,
                                      const bGPDspoint *pt,
diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
index f97e0d576b2..3e7b77e8427 100644
--- a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
@@ -50,6 +50,126 @@
 
 #include "UI_resources.h"
 
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Iterators
+ *
+ * Iterate over all visible stroke of all visible layers inside a gpObject.
+ * Also take into account onion skining.
+ *
+ * \{ */
+
+typedef void (*gpIterCb)(bGPDlayer *layer, bGPDframe *frame, bGPDstroke *stroke, void *thunk);
+
+void gpencil_object_visible_stroke_iter(Object *ob, gpIterCb stroke_cb, void *thunk)
+{
+  bGPdata *gpd = (bGPdata *)ob->data;
+

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list