[Bf-blender-cvs] [94d228a4e4c] greasepencil-refactor: GPencil: Refactor: Add stroke fast drawing

Clément Foucault noreply at git.blender.org
Fri Jan 3 22:28:34 CET 2020


Commit: 94d228a4e4c4aca3b08abb1129c8b6f1f2011e33
Author: Clément Foucault
Date:   Fri Jan 3 21:49:46 2020 +0100
Branches: greasepencil-refactor
https://developer.blender.org/rB94d228a4e4c4aca3b08abb1129c8b6f1f2011e33

GPencil: Refactor: Add stroke fast drawing

This use the same behavior as previous implementation. It uses a temp
buffer to store the screen and avoid redraw.

But this will be only on demand as the drawing may not match the final
look when releasing the pen. The UI option has not been added yet.

This mode still supports blending and VFX. Just stroke ordering with the
scene not supported.

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

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/gpencil_engine.h

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

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 32c7d393955..bc6fe7efe75 100644
--- a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
+++ b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
@@ -321,6 +321,7 @@ bool GPENCIL_batch_from_sbuffer(Object *ob,
       copy_v2_v2(tpoints2d[i], &tpoints[i].x);
     }
     /* Compute directly inside the IBO data buffer. */
+    /* OPTI: This is a bottleneck if the stroke is very long. */
     BLI_polyfill_calc(tpoints2d, (uint)vert_len, 0, (uint(*)[3])ibo_builder.data);
     /* Add stroke start offset. */
     for (int i = 0; i < gps->tot_triangles * 3; i++) {
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index 8ee57a71e1b..58bf9db3e38 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -312,6 +312,8 @@ static void GPENCIL_engine_init_new(void *ved)
   stl->pd->last_material_pool = NULL;
   stl->pd->tobjects.first = NULL;
   stl->pd->tobjects.last = NULL;
+  stl->pd->sbuffer_tobjects.first = NULL;
+  stl->pd->sbuffer_tobjects.last = NULL;
   stl->pd->draw_depth_only = !DRW_state_is_fbo();
   stl->pd->scene_depth_tx = stl->pd->draw_depth_only ? txl->dummy_texture : dtxl->depth;
   stl->pd->is_render = true; /* TODO */
@@ -447,6 +449,8 @@ static void GPENCIL_cache_init_new(void *ved)
 {
   GPENCIL_Data *vedata = (GPENCIL_Data *)ved;
   GPENCIL_PassList *psl = vedata->psl;
+  GPENCIL_TextureList *txl = vedata->txl;
+  GPENCIL_FramebufferList *fbl = vedata->fbl;
   GPENCIL_PrivateData *pd = vedata->stl->pd;
   DRWShadingGroup *grp;
 
@@ -472,7 +476,7 @@ static void GPENCIL_cache_init_new(void *ved)
     pd->sbuffer_layer = NULL;
     pd->stroke_batch = NULL;
     pd->fill_batch = NULL;
-    pd->do_stroke_fast_drawing = true;
+    pd->do_fast_drawing = false;
 
     Object *ob = draw_ctx->obact;
     if (ob && ob->type == OB_GPENCIL) {
@@ -481,10 +485,33 @@ static void GPENCIL_cache_init_new(void *ved)
               ob, &pd->stroke_batch, &pd->fill_batch, &pd->sbuffer_stroke)) {
         pd->sbuffer_gpd = (bGPdata *)ob->data;
         pd->sbuffer_layer = BKE_gpencil_layer_getactive(pd->sbuffer_gpd);
+        pd->do_fast_drawing = false; /* TODO option */
       }
     }
   }
 
+  if (pd->do_fast_drawing) {
+    pd->snapshot_buffer_dirty = (txl->snapshot_color_tx == NULL);
+    const float *size = DRW_viewport_size_get();
+    DRW_texture_ensure_2d(&txl->snapshot_depth_tx, size[0], size[1], GPU_DEPTH24_STENCIL8, 0);
+    DRW_texture_ensure_2d(&txl->snapshot_color_tx, size[0], size[1], GPU_R11F_G11F_B10F, 0);
+    DRW_texture_ensure_2d(&txl->snapshot_reveal_tx, size[0], size[1], GPU_R11F_G11F_B10F, 0);
+
+    GPU_framebuffer_ensure_config(&fbl->snapshot_fb,
+                                  {
+                                      GPU_ATTACHMENT_TEXTURE(txl->snapshot_depth_tx),
+                                      GPU_ATTACHMENT_TEXTURE(txl->snapshot_color_tx),
+                                      GPU_ATTACHMENT_TEXTURE(txl->snapshot_reveal_tx),
+                                  });
+  }
+  else {
+    /* Free uneeded buffers. */
+    GPU_FRAMEBUFFER_FREE_SAFE(fbl->snapshot_fb);
+    DRW_TEXTURE_FREE_SAFE(txl->snapshot_depth_tx);
+    DRW_TEXTURE_FREE_SAFE(txl->snapshot_color_tx);
+    DRW_TEXTURE_FREE_SAFE(txl->snapshot_reveal_tx);
+  }
+
   {
     DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM;
     DRW_PASS_CREATE(psl->composite_ps, state);
@@ -932,7 +959,8 @@ static void gp_layer_cache_populate(bGPDlayer *gpl,
     gp_sbuffer_cache_populate(iter);
   }
   else {
-    iter->do_sbuffer_call = (gpd == iter->pd->sbuffer_gpd) && (gpl == iter->pd->sbuffer_layer);
+    iter->do_sbuffer_call = !iter->pd->do_fast_drawing && (gpd == iter->pd->sbuffer_gpd) &&
+                            (gpl == iter->pd->sbuffer_layer);
   }
 
   GPENCIL_tLayer *tgp_layer_prev = iter->tgp_ob->layers.last;
@@ -1062,6 +1090,37 @@ static void gp_stroke_cache_populate(bGPDlayer *UNUSED(gpl),
   iter->stroke_index_last = gps->runtime.stroke_start + gps->totpoints + 1;
 }
 
+static void gp_sbuffer_cache_populate_fast(GPENCIL_Data *vedata, gpIterPopulateData *iter)
+{
+  bGPdata *gpd = (bGPdata *)iter->ob->data;
+  if (gpd != iter->pd->sbuffer_gpd) {
+    return;
+  }
+
+  GPENCIL_TextureList *txl = vedata->txl;
+  GPUTexture *depth_texture = iter->pd->scene_depth_tx;
+  GPENCIL_tObject *last_tgp_ob = iter->pd->tobjects.last;
+  /* Create another temp object that only contain the stroke. */
+  iter->tgp_ob = gpencil_object_cache_add_new(iter->pd, iter->ob);
+  /* Remove from the main list. */
+  iter->pd->tobjects.last = last_tgp_ob;
+  last_tgp_ob->next = NULL;
+  /* Add to sbuffer tgpobject list. */
+  BLI_LINKS_APPEND(&iter->pd->sbuffer_tobjects, iter->tgp_ob);
+  /* Remove depth test with scene (avoid self occlusion). */
+  iter->pd->scene_depth_tx = txl->dummy_texture;
+
+  gp_layer_cache_populate(iter->pd->sbuffer_layer, iter->pd->sbuffer_layer->actframe, NULL, iter);
+  iter->do_sbuffer_call = DRAW_NOW;
+  gp_stroke_cache_populate(NULL, NULL, iter->pd->sbuffer_stroke, iter);
+
+  gpencil_vfx_cache_populate(vedata, iter->ob, iter->tgp_ob);
+
+  /* Restore state. */
+  iter->do_sbuffer_call = 0;
+  iter->pd->scene_depth_tx = depth_texture;
+}
+
 static void GPENCIL_cache_populate_new(void *ved, Object *ob)
 {
   GPENCIL_Data *vedata = (GPENCIL_Data *)ved;
@@ -1090,6 +1149,10 @@ static void GPENCIL_cache_populate_new(void *ved, Object *ob)
     }
 
     gpencil_vfx_cache_populate(vedata, ob, iter.tgp_ob);
+
+    if (pd->do_fast_drawing) {
+      gp_sbuffer_cache_populate_fast(vedata, &iter);
+    }
   }
 
   if (ob->type == OB_LAMP) {
@@ -1502,45 +1565,44 @@ static void GPENCIL_draw_scene_depth_only(void *ved)
   pd->gp_object_pool = pd->gp_layer_pool = pd->gp_vfx_pool = NULL;
 }
 
-static void GPENCIL_draw_scene_new(void *ved)
+static void GPENCIL_draw_object(GPENCIL_Data *vedata, GPENCIL_tObject *ob)
 {
-  GPENCIL_Data *vedata = (GPENCIL_Data *)ved;
   GPENCIL_PassList *psl = vedata->psl;
   GPENCIL_PrivateData *pd = vedata->stl->pd;
   GPENCIL_FramebufferList *fbl = vedata->fbl;
   DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
   float clear_cols[2][4] = {{0.0f, 0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}};
 
-  if (pd->draw_depth_only) {
-    GPENCIL_draw_scene_depth_only(vedata);
-    return;
-  }
+  DRW_stats_group_start("GPencil Object");
 
-  if (pd->tobjects.first == NULL) {
-    return;
-  }
-
-  GPU_framebuffer_bind(fbl->gpencil_fb);
-  GPU_framebuffer_multi_clear(fbl->gpencil_fb, clear_cols);
-
-  for (GPENCIL_tObject *ob = pd->tobjects.first; ob; ob = ob->next) {
-    DRW_stats_group_start("GPencil Object");
+  GPUFrameBuffer *fb_object = (ob->vfx.first) ? fbl->object_fb : fbl->gpencil_fb;
 
-    GPUFrameBuffer *fb_object = (ob->vfx.first) ? fbl->object_fb : fbl->gpencil_fb;
+  GPU_framebuffer_bind(fb_object);
+  GPU_framebuffer_clear_depth_stencil(fb_object, ob->is_drawmode3d ? 1.0f : 0.0f, 0x00);
 
-    GPU_framebuffer_bind(fb_object);
-    GPU_framebuffer_clear_depth_stencil(fb_object, ob->is_drawmode3d ? 1.0f : 0.0f, 0x00);
+  if (ob->vfx.first) {
+    GPU_framebuffer_multi_clear(fb_object, clear_cols);
+  }
 
-    if (ob->vfx.first) {
-      GPU_framebuffer_multi_clear(fb_object, clear_cols);
+  for (GPENCIL_tLayer *layer = ob->layers.first; layer; layer = layer->next) {
+    if (layer->blend_ps) {
+      GPU_framebuffer_bind(fbl->layer_fb);
+      GPU_framebuffer_multi_clear(fbl->layer_fb, clear_cols);
     }
-
-    for (GPENCIL_tLayer *layer = ob->layers.first; layer; layer = layer->next) {
-      if (layer->blend_ps) {
-        GPU_framebuffer_bind(fbl->layer_fb);
-        GPU_framebuffer_multi_clear(fbl->layer_fb, clear_cols);
+    else if (layer->is_masked) {
+      GPU_framebuffer_bind(fbl->masked_fb);
+      if (layer->do_masked_clear) {
+        GPU_framebuffer_multi_clear(fbl->masked_fb, clear_cols);
       }
-      else if (layer->is_masked) {
+    }
+    else {
+      GPU_framebuffer_bind(fb_object);
+    }
+
+    DRW_draw_pass(layer->geom_ps);
+
+    if (layer->blend_ps) {
+      if (layer->is_masked) {
         GPU_framebuffer_bind(fbl->masked_fb);
         if (layer->do_masked_clear) {
           GPU_framebuffer_multi_clear(fbl->masked_fb, clear_cols);
@@ -1549,38 +1611,95 @@ static void GPENCIL_draw_scene_new(void *ved)
       else {
         GPU_framebuffer_bind(fb_object);
       }
+      DRW_draw_pass(layer->blend_ps);
+    }
+  }
 
-      DRW_draw_pass(layer->geom_ps);
+  for (GPENCIL_tVfx *vfx = ob->vfx.first; vfx; vfx = vfx->next) {
+    GPU_framebuffer_bind(*(vfx->target_fb));
+    DRW_draw_pass(vfx->vfx_ps);
+  }
 
-      if (layer->blend_ps) {
-        if (layer->is_masked) {
-          GPU_framebuffer_bind(fbl->masked_fb);
-          if (layer->do_masked_clear) {
-            GPU_framebuffer_multi_clear(fbl->masked_fb, clear_cols);
-          }
-        }
-        else {
-          GPU_framebuffer_bind(fb_object);
-        }
-        DRW_draw_pass(layer->blend_ps);
-      }
-    }
+  copy_m4_m4(pd->object_bound_mat, ob->plane_mat);
+  pd->is_stroke_order_3d = ob->is_drawmode3d;
 
-    for (GPENCIL_tVfx *vfx = ob->vfx.first; vfx; vfx = vfx->next) {
-      GPU_framebuffer_bind(*(vfx->target_fb));
-      DRW_draw_pass(vfx->vfx_ps);
-    }
+  /* TODO fix for render */
+  if (dfbl->depth_only_fb) {
+    GPU_framebuffer_bind(dfbl->depth_only_fb);
+    DRW_draw_pass(psl->merge_depth_ps);
+  }
 
-    copy_m4_m4(pd->object_bound_mat, ob->plane_mat);
-    pd->is_stroke_order_3d = ob->is_drawmode3d;
+  DRW_stats_group_end();
+}
 
-    /* TODO fix for render */
-    if (dfbl->depth_only_fb) {
-      GPU_framebuffer_bind(dfbl->depth_only_fb);
-      DRW_draw_pass(psl->merge_depth_ps);
-    }
+static void GPENCIL_fast_draw_start(GPENCIL_Data *vedata)
+{
+  GPENCIL_PrivateData *pd = vedata->stl->pd;
+  GPENCIL_FramebufferList *fbl = vedata->fbl;
+  DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+
+  if (!pd->snapshot_buffer_dirty) {
+    /* Copy back cached render. */
+    GP

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list