Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorAntonioya <blendergit@gmail.com>2018-11-20 21:26:16 +0300
committerAntonioya <blendergit@gmail.com>2018-11-20 22:05:37 +0300
commite63c9472049f64221b34c4d2dd3101086b61520e (patch)
treee75fc34d3a450f88d8805833c04e98fd4442f616 /source
parent140d383393764f28405b34775b2e0dc22c51e5a6 (diff)
GP: Refactor drawing engine to single VBO
This is part of T57829. Reduce the number of batches used to only one by shader type. This reduces GPU overhead and increase a lot the FPS. As the number of batches is small, the time to allocate and free memory was reduced in 90% or more. Also the code has been simplified and all batch management has been removed because this is not necessary. Now, all shading groups are created after all vertex buffer data for all strokes has been created using DRW_shgroup_call_range_add(). All batch cache data has been moved to the Object runtime struct and not as before where some parts (derived data) were saved inside GPD datablock. For particles, now the code is faster and cleaner and gets better FPS. Thanks to Clément Foucault for his help and advices to improve speed.
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_gpencil.h1
-rw-r--r--source/blender/blenkernel/BKE_gpencil_modifier.h5
-rw-r--r--source/blender/blenkernel/intern/gpencil.c48
-rw-r--r--source/blender/blenloader/intern/readfile.c2
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_cache_utils.c246
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c246
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_draw_utils.c950
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.c67
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.h95
-rw-r--r--source/blender/editors/gpencil/gpencil_data.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c4
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c8
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c16
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c9
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpenciltime.c1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c1
-rw-r--r--source/blender/makesdna/DNA_gpencil_types.h3
28 files changed, 931 insertions, 784 deletions
diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h
index 3b8df66668a..34c61083872 100644
--- a/source/blender/blenkernel/BKE_gpencil.h
+++ b/source/blender/blenkernel/BKE_gpencil.h
@@ -65,7 +65,6 @@ bool BKE_gpencil_free_strokes(struct bGPDframe *gpf);
void BKE_gpencil_free_frames(struct bGPDlayer *gpl);
void BKE_gpencil_free_layers(struct ListBase *list);
bool BKE_gpencil_free_frame_runtime_data(struct bGPDframe *derived_gpf);
-void BKE_gpencil_free_derived_frames(struct bGPdata *gpd);
void BKE_gpencil_free(struct bGPdata *gpd, bool free_all);
void BKE_gpencil_batch_cache_dirty_tag(struct bGPdata *gpd);
diff --git a/source/blender/blenkernel/BKE_gpencil_modifier.h b/source/blender/blenkernel/BKE_gpencil_modifier.h
index 91f368613cb..e31f61c909a 100644
--- a/source/blender/blenkernel/BKE_gpencil_modifier.h
+++ b/source/blender/blenkernel/BKE_gpencil_modifier.h
@@ -232,6 +232,11 @@ typedef struct GpencilModifierTypeInfo {
*/
void (*foreachTexLink)(struct GpencilModifierData *md, struct Object *ob,
GreasePencilTexWalkFunc walk, void *userData);
+
+ /* get the number of times the strokes are duplicated in this modifier.
+ * This is used to calculate the size of the GPU VBOs
+ */
+ int (*getDuplicationFactor)(struct GpencilModifierData *md);
} GpencilModifierTypeInfo;
/* Initialize modifier's global data (type info and some common global storages). */
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index f2225bca3f5..98d255df080 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -211,46 +211,6 @@ void BKE_gpencil_free_layers(ListBase *list)
}
}
-/* clear all runtime derived data */
-static void BKE_gpencil_clear_derived(bGPDlayer *gpl)
-{
- if (gpl->runtime.derived_array == NULL) {
- return;
- }
-
- for (int i = 0; i < gpl->runtime.len_derived; i++) {
- bGPDframe *derived_gpf = &gpl->runtime.derived_array[i];
- BKE_gpencil_free_frame_runtime_data(derived_gpf);
- derived_gpf = NULL;
- }
- gpl->runtime.len_derived = 0;
- MEM_SAFE_FREE(gpl->runtime.derived_array);
-}
-
-/* Free all of the gp-layers temp data*/
-static void BKE_gpencil_free_layers_temp_data(ListBase *list)
-{
- bGPDlayer *gpl_next;
-
- /* error checking */
- if (list == NULL) return;
- /* delete layers */
- for (bGPDlayer *gpl = list->first; gpl; gpl = gpl_next) {
- gpl_next = gpl->next;
- BKE_gpencil_clear_derived(gpl);
- }
-}
-
-/* Free temp gpf derived frames */
-void BKE_gpencil_free_derived_frames(bGPdata *gpd)
-{
- /* error checking */
- if (gpd == NULL) return;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- BKE_gpencil_clear_derived(gpl);
- }
-}
-
/** Free (or release) any data used by this grease pencil (does not free the gpencil itself). */
void BKE_gpencil_free(bGPdata *gpd, bool free_all)
{
@@ -258,9 +218,6 @@ void BKE_gpencil_free(bGPdata *gpd, bool free_all)
BKE_animdata_free(&gpd->id, false);
/* free layers */
- if (free_all) {
- BKE_gpencil_free_layers_temp_data(&gpd->layers);
- }
BKE_gpencil_free_layers(&gpd->layers);
/* materials */
@@ -639,8 +596,6 @@ bGPDlayer *BKE_gpencil_layer_duplicate(const bGPDlayer *gpl_src)
/* make a copy of source layer */
gpl_dst = MEM_dupallocN(gpl_src);
gpl_dst->prev = gpl_dst->next = NULL;
- gpl_dst->runtime.derived_array = NULL;
- gpl_dst->runtime.len_derived = 0;
/* copy frames */
BLI_listbase_clear(&gpl_dst->frames);
@@ -1031,9 +986,6 @@ void BKE_gpencil_layer_delete(bGPdata *gpd, bGPDlayer *gpl)
/* free icon providing preview of icon color */
BKE_icon_delete(gpl->runtime.icon_id);
- /* free derived data */
- BKE_gpencil_clear_derived(gpl);
-
BLI_freelinkN(&gpd->layers, gpl);
}
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 9596df58170..50bf2f79fdc 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -6612,8 +6612,6 @@ static void direct_link_gpencil(FileData *fd, bGPdata *gpd)
gpl->actframe = newdataadr(fd, gpl->actframe);
- gpl->runtime.derived_array = NULL;
- gpl->runtime.len_derived = 0;
gpl->runtime.icon_id = 0;
for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
index 30887e3fb19..15ac3f37add 100644
--- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
@@ -26,14 +26,14 @@
#include "DRW_engine.h"
#include "DRW_render.h"
-#include "BKE_global.h"
-
#include "ED_gpencil.h"
#include "ED_view3d.h"
#include "DNA_gpencil_types.h"
#include "DNA_view3d_types.h"
+#include "BKE_gpencil.h"
+
#include "gpencil_engine.h"
#include "draw_cache_impl.h"
@@ -41,63 +41,6 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
-static bool gpencil_check_ob_duplicated(tGPencilObjectCache *cache_array,
- int gp_cache_used, Object *ob, int *r_index)
-{
- if (gp_cache_used == 0) {
- return false;
- }
-
- for (int i = 0; i < gp_cache_used; i++) {
- tGPencilObjectCache *cache_elem = &cache_array[i];
- if (cache_elem->ob == ob) {
- *r_index = cache_elem->data_idx;
- return true;
- }
- }
- return false;
-}
-
-static bool gpencil_check_datablock_duplicated(
- tGPencilObjectCache *cache_array, int gp_cache_used,
- Object *ob, bGPdata *gpd)
-{
- if (gp_cache_used == 0) {
- return false;
- }
-
- for (int i = 0; i < gp_cache_used; i++) {
- tGPencilObjectCache *cache_elem = &cache_array[i];
- if ((cache_elem->ob != ob) &&
- (cache_elem->gpd == gpd))
- {
- return true;
- }
- }
- return false;
-}
-
-static int gpencil_len_datablock_duplicated(
- tGPencilObjectCache *cache_array, int gp_cache_used,
- Object *ob, bGPdata *gpd)
-{
- int tot = 0;
- if (gp_cache_used == 0) {
- return 0;
- }
-
- for (int i = 0; i < gp_cache_used; i++) {
- tGPencilObjectCache *cache_elem = &cache_array[i];
- if ((cache_elem->ob != ob) &&
- (cache_elem->gpd == gpd) &&
- (!cache_elem->is_dup_ob))
- {
- tot++;
- }
- }
- return tot;
-}
-
/* add a gpencil object to cache to defer drawing */
tGPencilObjectCache *gpencil_object_cache_add(
tGPencilObjectCache *cache_array, Object *ob,
@@ -133,38 +76,15 @@ tGPencilObjectCache *gpencil_object_cache_add(
copy_m4_m4(cache_elem->obmat, ob->obmat);
cache_elem->idx = *gp_cache_used;
- /* check if object is duplicated */
- cache_elem->is_dup_ob = gpencil_check_ob_duplicated(
- cache_array,
- *gp_cache_used, ob_orig,
- &cache_elem->data_idx);
-
- if (!cache_elem->is_dup_ob) {
- /* check if object reuse datablock */
- cache_elem->is_dup_data = gpencil_check_datablock_duplicated(
- cache_array, *gp_cache_used,
- ob_orig, cache_elem->gpd);
- if (cache_elem->is_dup_data) {
- cache_elem->data_idx = gpencil_len_datablock_duplicated(
- cache_array, *gp_cache_used,
- ob_orig, cache_elem->gpd);
-
- cache_elem->gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
- }
- else {
- cache_elem->data_idx = 0;
- }
- }
- else {
- cache_elem->is_dup_data = false;
- }
+ /* object is duplicated (particle) */
+ cache_elem->is_dup_ob = ob->base_flag & BASE_FROMDUPLI;
/* save FXs */
cache_elem->pixfactor = cache_elem->gpd->pixfactor;
cache_elem->shader_fx = ob_orig->shader_fx;
- cache_elem->init_grp = 0;
- cache_elem->end_grp = -1;
+ cache_elem->init_grp = NULL;
+ cache_elem->end_grp = NULL;
/* calculate zdepth from point of view */
float zdepth = 0.0;
@@ -198,6 +118,48 @@ tGPencilObjectCache *gpencil_object_cache_add(
return cache_array;
}
+/* add a shading group to the cache to create later */
+GpencilBatchGroup *gpencil_group_cache_add(
+ GpencilBatchGroup *cache_array,
+ bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps,
+ const short type, const bool onion,
+ const int vertex_idx,
+ int *grp_size, int *grp_used)
+{
+ GpencilBatchGroup *cache_elem = NULL;
+ GpencilBatchGroup *p = NULL;
+
+ /* By default a cache is created with one block with a predefined number of free slots,
+ if the size is not enough, the cache is reallocated adding a new block of free slots.
+ This is done in order to keep cache small */
+ if (*grp_used + 1 > *grp_size) {
+ if ((*grp_size == 0) || (cache_array == NULL)) {
+ p = MEM_callocN(sizeof(struct GpencilBatchGroup) * GPENCIL_GROUPS_BLOCK_SIZE, "GpencilBatchGroup");
+ *grp_size = GPENCIL_GROUPS_BLOCK_SIZE;
+ }
+ else {
+ *grp_size += GPENCIL_GROUPS_BLOCK_SIZE;
+ p = MEM_recallocN(cache_array, sizeof(struct GpencilBatchGroup) * *grp_size);
+ }
+ cache_array = p;
+ }
+ /* zero out all data */
+ cache_elem = &cache_array[*grp_used];
+ memset(cache_elem, 0, sizeof(*cache_elem));
+
+ cache_elem->gpl = gpl;
+ cache_elem->gpf = gpf;
+ cache_elem->gps = gps;
+ cache_elem->type = type;
+ cache_elem->onion = onion;
+ cache_elem->vertex_idx = vertex_idx;
+
+ /* increase slots used in cache */
+ (*grp_used)++;
+
+ return cache_array;
+}
+
/* get current cache data */
static GpencilBatchCache *gpencil_batch_get_element(Object *ob)
{
@@ -208,51 +170,33 @@ static GpencilBatchCache *gpencil_batch_get_element(Object *ob)
/* verify if cache is valid */
static bool gpencil_batch_cache_valid(GpencilBatchCache *cache, bGPdata *gpd, int cfra)
{
+ bool valid = true;
if (cache == NULL) {
return false;
}
cache->is_editmode = GPENCIL_ANY_EDIT_MODE(gpd);
-
if (cfra != cache->cache_frame) {
- return false;
+ valid = false;
}
-
- if (gpd->flag & GP_DATA_CACHE_IS_DIRTY) {
- return false;
+ else if (gpd->flag & GP_DATA_CACHE_IS_DIRTY) {
+ valid = false;
}
-
- if (cache->is_editmode) {
- return false;
+ else if (gpd->flag & GP_DATA_SHOW_ONIONSKINS) {
+ /* if onion, set as dirty always
+ * This reduces performance, but avoid any crash in the multiple
+ * overlay and multiwindow options and keep all windows working
+ */
+ valid = false;
}
-
- if (cache->is_dirty) {
- return false;
+ else if (cache->is_editmode) {
+ valid = false;
}
-
- return true;
-}
-
-/* resize the cache to the number of slots */
-static void gpencil_batch_cache_resize(GpencilBatchCache *cache, int slots)
-{
- cache->cache_size = slots;
- cache->batch_stroke = MEM_recallocN(cache->batch_stroke, sizeof(struct Gwn_Batch *) * slots);
- cache->batch_fill = MEM_recallocN(cache->batch_fill, sizeof(struct Gwn_Batch *) * slots);
- cache->batch_edit = MEM_recallocN(cache->batch_edit, sizeof(struct Gwn_Batch *) * slots);
- cache->batch_edlin = MEM_recallocN(cache->batch_edlin, sizeof(struct Gwn_Batch *) * slots);
-}
-
-/* check size and increase if no free slots */
-void gpencil_batch_cache_check_free_slots(Object *ob)
-{
- GpencilBatchCache *cache = gpencil_batch_get_element(ob);
-
- /* the memory is reallocated by chunks, not for one slot only to improve speed */
- if (cache->cache_idx >= cache->cache_size) {
- cache->cache_size += GPENCIL_MIN_BATCH_SLOTS_CHUNK;
- gpencil_batch_cache_resize(cache, cache->cache_size);
+ else if (cache->is_dirty) {
+ valid = false;
}
+
+ return valid;
}
/* cache init */
@@ -263,10 +207,6 @@ static GpencilBatchCache *gpencil_batch_cache_init(Object *ob, int cfra)
GpencilBatchCache *cache = gpencil_batch_get_element(ob);
- if (G.debug_value >= 664) {
- printf("gpencil_batch_cache_init: %s\n", ob->id.name);
- }
-
if (!cache) {
cache = MEM_callocN(sizeof(*cache), __func__);
ob_orig->runtime.gpencil_cache = cache;
@@ -275,19 +215,17 @@ static GpencilBatchCache *gpencil_batch_cache_init(Object *ob, int cfra)
memset(cache, 0, sizeof(*cache));
}
- cache->cache_size = GPENCIL_MIN_BATCH_SLOTS_CHUNK;
- cache->batch_stroke = MEM_callocN(sizeof(struct Gwn_Batch *) * cache->cache_size, "Gpencil_Batch_Stroke");
- cache->batch_fill = MEM_callocN(sizeof(struct Gwn_Batch *) * cache->cache_size, "Gpencil_Batch_Fill");
- cache->batch_edit = MEM_callocN(sizeof(struct Gwn_Batch *) * cache->cache_size, "Gpencil_Batch_Edit");
- cache->batch_edlin = MEM_callocN(sizeof(struct Gwn_Batch *) * cache->cache_size, "Gpencil_Batch_Edlin");
-
cache->is_editmode = GPENCIL_ANY_EDIT_MODE(gpd);
- gpd->flag &= ~GP_DATA_CACHE_IS_DIRTY;
- cache->cache_idx = 0;
cache->is_dirty = true;
+
cache->cache_frame = cfra;
+ /* create array of derived frames equal to number of layers */
+ cache->tot_layers = BLI_listbase_count(&gpd->layers);
+ CLAMP_MIN(cache->tot_layers, 1);
+ cache->derived_array = MEM_callocN(sizeof(struct bGPDframe) * cache->tot_layers, "Derived GPF");
+
return cache;
}
@@ -298,24 +236,30 @@ static void gpencil_batch_cache_clear(GpencilBatchCache *cache)
return;
}
- if (cache->cache_size == 0) {
- return;
- }
-
- if (cache->cache_size > 0) {
- for (int i = 0; i < cache->cache_size; i++) {
- GPU_BATCH_DISCARD_SAFE(cache->batch_stroke[i]);
- GPU_BATCH_DISCARD_SAFE(cache->batch_fill[i]);
- GPU_BATCH_DISCARD_SAFE(cache->batch_edit[i]);
- GPU_BATCH_DISCARD_SAFE(cache->batch_edlin[i]);
- }
- MEM_SAFE_FREE(cache->batch_stroke);
- MEM_SAFE_FREE(cache->batch_fill);
- MEM_SAFE_FREE(cache->batch_edit);
- MEM_SAFE_FREE(cache->batch_edlin);
+ GPU_BATCH_DISCARD_SAFE(cache->b_stroke.batch);
+ GPU_BATCH_DISCARD_SAFE(cache->b_point.batch);
+ GPU_BATCH_DISCARD_SAFE(cache->b_fill.batch);
+ GPU_BATCH_DISCARD_SAFE(cache->b_edit.batch);
+ GPU_BATCH_DISCARD_SAFE(cache->b_edlin.batch);
+
+ MEM_SAFE_FREE(cache->b_stroke.batch);
+ MEM_SAFE_FREE(cache->b_point.batch);
+ MEM_SAFE_FREE(cache->b_fill.batch);
+ MEM_SAFE_FREE(cache->b_edit.batch);
+ MEM_SAFE_FREE(cache->b_edlin.batch);
+
+ MEM_SAFE_FREE(cache->grp_cache);
+ cache->grp_size = 0;
+ cache->grp_used = 0;
+
+ /* clear all frames derived data */
+ for (int i = 0; i < cache->tot_layers; i++) {
+ bGPDframe *derived_gpf = &cache->derived_array[i];
+ BKE_gpencil_free_frame_runtime_data(derived_gpf);
+ derived_gpf = NULL;
}
-
- cache->cache_size = 0;
+ cache->tot_layers = 0;
+ MEM_SAFE_FREE(cache->derived_array);
}
/* get cache */
@@ -326,10 +270,6 @@ GpencilBatchCache *gpencil_batch_cache_get(Object *ob, int cfra)
GpencilBatchCache *cache = gpencil_batch_get_element(ob);
if (!gpencil_batch_cache_valid(cache, gpd, cfra)) {
- if (G.debug_value >= 664) {
- printf("gpencil_batch_cache: %s\n", gpd->id.name);
- }
-
if (cache) {
gpencil_batch_cache_clear(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 f255892de44..ec690fdd14b 100644
--- a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
+++ b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
@@ -87,24 +87,33 @@ static void gpencil_set_fill_point(
GPU_vertbuf_attr_set(vbo, text_id, idx, uv);
}
-/* create batch geometry data for points stroke shader */
-GPUBatch *DRW_gpencil_get_point_geom(bGPDstroke *gps, short thickness, const float ink[4])
+static void gpencil_vbo_ensure_size(GpencilBatchCacheElem *be, int totvertex)
{
- static GPUVertFormat format = { 0 };
- static uint pos_id, color_id, size_id, uvdata_id;
- if (format.attr_len == 0) {
- pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- size_id = GPU_vertformat_attr_add(&format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
- uvdata_id = GPU_vertformat_attr_add(&format, "uvdata", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ if (be->vbo->vertex_alloc <= be->vbo_len + totvertex) {
+ uint newsize = be->vbo->vertex_alloc + (((totvertex / GPENCIL_VBO_BLOCK_SIZE) + 1) * GPENCIL_VBO_BLOCK_SIZE);
+ GPU_vertbuf_data_resize(be->vbo, newsize);
}
+}
- GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
- GPU_vertbuf_data_alloc(vbo, gps->totpoints);
+/* create batch geometry data for points stroke shader */
+void DRW_gpencil_get_point_geom(GpencilBatchCacheElem *be, bGPDstroke *gps, short thickness, const float ink[4])
+{
+ int totvertex = gps->totpoints;
+ if (be->vbo == NULL) {
+ be->pos_id = GPU_vertformat_attr_add(&be->format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ be->color_id = GPU_vertformat_attr_add(&be->format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ be->thickness_id = GPU_vertformat_attr_add(&be->format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ be->uvdata_id = GPU_vertformat_attr_add(&be->format, "uvdata", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ be->vbo = GPU_vertbuf_create_with_format(&be->format);
+ GPU_vertbuf_data_alloc(be->vbo, be->tot_vertex);
+ be->vbo_len = 0;
+ }
+ else {
+ gpencil_vbo_ensure_size(be, totvertex);
+ }
/* draw stroke curve */
const bGPDspoint *pt = gps->points;
- int idx = 0;
float alpha;
float col[4];
@@ -116,86 +125,124 @@ GPUBatch *DRW_gpencil_get_point_geom(bGPDstroke *gps, short thickness, const flo
float thick = max_ff(pt->pressure * thickness, 1.0f);
- GPU_vertbuf_attr_set(vbo, color_id, idx, col);
- GPU_vertbuf_attr_set(vbo, size_id, idx, &thick);
+ GPU_vertbuf_attr_set(be->vbo, be->color_id, be->vbo_len, col);
+ GPU_vertbuf_attr_set(be->vbo, be->thickness_id, be->vbo_len, &thick);
/* transfer both values using the same shader variable */
float uvdata[2] = { pt->uv_fac, pt->uv_rot };
- GPU_vertbuf_attr_set(vbo, uvdata_id, idx, uvdata);
+ GPU_vertbuf_attr_set(be->vbo, be->uvdata_id, be->vbo_len, uvdata);
- GPU_vertbuf_attr_set(vbo, pos_id, idx, &pt->x);
- idx++;
+ GPU_vertbuf_attr_set(be->vbo, be->pos_id, be->vbo_len, &pt->x);
+ be->vbo_len++;
}
-
- return GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
/* create batch geometry data for stroke shader */
-GPUBatch *DRW_gpencil_get_stroke_geom(bGPDstroke *gps, short thickness, const float ink[4])
+void DRW_gpencil_get_stroke_geom(struct GpencilBatchCacheElem *be, bGPDstroke *gps, short thickness, const float ink[4])
{
bGPDspoint *points = gps->points;
int totpoints = gps->totpoints;
/* if cyclic needs more vertex */
int cyclic_add = (gps->flag & GP_STROKE_CYCLIC) ? 1 : 0;
+ int totvertex = totpoints + cyclic_add + 2;
- static GPUVertFormat format = { 0 };
- static uint pos_id, color_id, thickness_id, uvdata_id;
- if (format.attr_len == 0) {
- pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- thickness_id = GPU_vertformat_attr_add(&format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
- uvdata_id = GPU_vertformat_attr_add(&format, "uvdata", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- }
+ if (be->vbo == NULL) {
+ be->pos_id = GPU_vertformat_attr_add(&be->format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ be->color_id = GPU_vertformat_attr_add(&be->format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ be->thickness_id = GPU_vertformat_attr_add(&be->format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ be->uvdata_id = GPU_vertformat_attr_add(&be->format, "uvdata", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
- GPU_vertbuf_data_alloc(vbo, totpoints + cyclic_add + 2);
+ be->vbo = GPU_vertbuf_create_with_format(&be->format);
+ GPU_vertbuf_data_alloc(be->vbo, be->tot_vertex);
+ be->vbo_len = 0;
+ }
+ else {
+ gpencil_vbo_ensure_size(be, totvertex);
+ }
/* draw stroke curve */
const bGPDspoint *pt = points;
- int idx = 0;
for (int i = 0; i < totpoints; i++, pt++) {
/* first point for adjacency (not drawn) */
if (i == 0) {
if (gps->flag & GP_STROKE_CYCLIC && totpoints > 2) {
gpencil_set_stroke_point(
- vbo, &points[totpoints - 1], idx,
- pos_id, color_id, thickness_id, uvdata_id, thickness, ink);
- idx++;
+ be->vbo, &points[totpoints - 1], be->vbo_len,
+ be->pos_id, be->color_id, be->thickness_id, be->uvdata_id, thickness, ink);
+ be->vbo_len++;
}
else {
gpencil_set_stroke_point(
- vbo, &points[1], idx,
- pos_id, color_id, thickness_id, uvdata_id, thickness, ink);
- idx++;
+ be->vbo, &points[1], be->vbo_len,
+ be->pos_id, be->color_id, be->thickness_id, be->uvdata_id, thickness, ink);
+ be->vbo_len++;
}
}
/* set point */
gpencil_set_stroke_point(
- vbo, pt, idx,
- pos_id, color_id, thickness_id, uvdata_id, thickness, ink);
- idx++;
+ be->vbo, pt, be->vbo_len,
+ be->pos_id, be->color_id, be->thickness_id, be->uvdata_id, thickness, ink);
+ be->vbo_len++;
}
if (gps->flag & GP_STROKE_CYCLIC && totpoints > 2) {
/* draw line to first point to complete the cycle */
gpencil_set_stroke_point(
- vbo, &points[0], idx,
- pos_id, color_id, thickness_id, uvdata_id, thickness, ink);
- idx++;
+ be->vbo, &points[0], be->vbo_len,
+ be->pos_id, be->color_id, be->thickness_id, be->uvdata_id, thickness, ink);
+ be->vbo_len++;
/* now add adjacency point (not drawn) */
gpencil_set_stroke_point(
- vbo, &points[1], idx,
- pos_id, color_id, thickness_id, uvdata_id, thickness, ink);
- idx++;
+ be->vbo, &points[1], be->vbo_len,
+ be->pos_id, be->color_id, be->thickness_id, be->uvdata_id, thickness, ink);
+ be->vbo_len++;
}
/* last adjacency point (not drawn) */
else {
gpencil_set_stroke_point(
- vbo, &points[totpoints - 2], idx,
- pos_id, color_id, thickness_id, uvdata_id, thickness, ink);
+ be->vbo, &points[totpoints - 2], be->vbo_len,
+ be->pos_id, be->color_id, be->thickness_id, be->uvdata_id, thickness, ink);
+ be->vbo_len++;
}
+}
- return GPU_batch_create_ex(GPU_PRIM_LINE_STRIP_ADJ, vbo, NULL, GPU_BATCH_OWNS_VBO);
+/* create batch geometry data for stroke shader */
+void DRW_gpencil_get_fill_geom(struct GpencilBatchCacheElem *be, Object *ob, bGPDstroke *gps, const float color[4])
+{
+ BLI_assert(gps->totpoints >= 3);
+
+ /* Calculate triangles cache for filling area (must be done only after changes) */
+ if ((gps->flag & GP_STROKE_RECALC_CACHES) || (gps->tot_triangles == 0) || (gps->triangles == NULL)) {
+ DRW_gpencil_triangulate_stroke_fill(ob, gps);
+ ED_gpencil_calc_stroke_uv(ob, gps);
+ }
+
+ BLI_assert(gps->tot_triangles >= 1);
+ int totvertex = gps->tot_triangles * 3;
+
+ if (be->vbo == NULL) {
+ be->pos_id = GPU_vertformat_attr_add(&be->format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ be->color_id = GPU_vertformat_attr_add(&be->format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ be->uvdata_id = GPU_vertformat_attr_add(&be->format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ be->vbo = GPU_vertbuf_create_with_format(&be->format);
+ GPU_vertbuf_data_alloc(be->vbo, be->tot_vertex);
+ be->vbo_len = 0;
+ }
+ else {
+ gpencil_vbo_ensure_size(be, totvertex);
+ }
+
+ /* Draw all triangles for filling the polygon (cache must be calculated before) */
+ bGPDtriangle *stroke_triangle = gps->triangles;
+ for (int i = 0; i < gps->tot_triangles; i++, stroke_triangle++) {
+ for (int j = 0; j < 3; j++) {
+ gpencil_set_fill_point(
+ be->vbo, be->vbo_len, &gps->points[stroke_triangle->verts[j]], color, stroke_triangle->uv[j],
+ be->pos_id, be->color_id, be->uvdata_id);
+ be->vbo_len++;
+ }
+ }
}
/* create batch geometry data for current buffer stroke shader */
@@ -407,47 +454,8 @@ GPUBatch *DRW_gpencil_get_buffer_fill_geom(bGPdata *gpd)
return GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
-/* create batch geometry data for stroke shader */
-GPUBatch *DRW_gpencil_get_fill_geom(Object *ob, bGPDstroke *gps, const float color[4])
-{
- BLI_assert(gps->totpoints >= 3);
-
- /* Calculate triangles cache for filling area (must be done only after changes) */
- if ((gps->flag & GP_STROKE_RECALC_CACHES) || (gps->tot_triangles == 0) || (gps->triangles == NULL)) {
- DRW_gpencil_triangulate_stroke_fill(ob, gps);
- ED_gpencil_calc_stroke_uv(ob, gps);
- }
-
- BLI_assert(gps->tot_triangles >= 1);
-
- static GPUVertFormat format = { 0 };
- static uint pos_id, color_id, text_id;
- if (format.attr_len == 0) {
- pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- text_id = GPU_vertformat_attr_add(&format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- }
-
- GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
- GPU_vertbuf_data_alloc(vbo, gps->tot_triangles * 3);
-
- /* Draw all triangles for filling the polygon (cache must be calculated before) */
- bGPDtriangle *stroke_triangle = gps->triangles;
- int idx = 0;
- for (int i = 0; i < gps->tot_triangles; i++, stroke_triangle++) {
- for (int j = 0; j < 3; j++) {
- gpencil_set_fill_point(
- vbo, idx, &gps->points[stroke_triangle->verts[j]], color, stroke_triangle->uv[j],
- pos_id, color_id, text_id);
- idx++;
- }
- }
-
- return GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO);
-}
-
/* Draw selected verts for strokes being edited */
-GPUBatch *DRW_gpencil_get_edit_geom(bGPDstroke *gps, float alpha, short dflag)
+void DRW_gpencil_get_edit_geom(struct GpencilBatchCacheElem *be, bGPDstroke *gps, float alpha, short dflag)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
Object *ob = draw_ctx->obact;
@@ -483,16 +491,18 @@ GPUBatch *DRW_gpencil_get_edit_geom(bGPDstroke *gps, float alpha, short dflag)
UI_GetThemeColor3fv(TH_GP_VERTEX, unselectColor);
unselectColor[3] = alpha;
- static GPUVertFormat format = { 0 };
- static uint pos_id, color_id, size_id;
- if (format.attr_len == 0) {
- pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- size_id = GPU_vertformat_attr_add(&format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
- }
+ if (be->vbo == NULL) {
+ be->pos_id = GPU_vertformat_attr_add(&be->format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ be->color_id = GPU_vertformat_attr_add(&be->format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ be->thickness_id = GPU_vertformat_attr_add(&be->format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
- GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
- GPU_vertbuf_data_alloc(vbo, gps->totpoints);
+ be->vbo = GPU_vertbuf_create_with_format(&be->format);
+ GPU_vertbuf_data_alloc(be->vbo, gps->totpoints);
+ be->vbo_len = 0;
+ }
+ else {
+ gpencil_vbo_ensure_size(be, gps->totpoints);
+ }
/* Draw start and end point differently if enabled stroke direction hint */
bool show_direction_hint = (dflag & GP_DATA_SHOW_DIRECTION) && (gps->totpoints > 1);
@@ -501,7 +511,6 @@ GPUBatch *DRW_gpencil_get_edit_geom(bGPDstroke *gps, float alpha, short dflag)
bGPDspoint *pt = gps->points;
MDeformVert *dvert = gps->dvert;
- int idx = 0;
float fcolor[4];
float fsize = 0;
for (int i = 0; i < gps->totpoints; i++, pt++) {
@@ -535,20 +544,18 @@ GPUBatch *DRW_gpencil_get_edit_geom(bGPDstroke *gps, float alpha, short dflag)
}
}
- GPU_vertbuf_attr_set(vbo, color_id, idx, fcolor);
- GPU_vertbuf_attr_set(vbo, size_id, idx, &fsize);
- GPU_vertbuf_attr_set(vbo, pos_id, idx, &pt->x);
- idx++;
+ GPU_vertbuf_attr_set(be->vbo, be->color_id, be->vbo_len, fcolor);
+ GPU_vertbuf_attr_set(be->vbo, be->thickness_id, be->vbo_len, &fsize);
+ GPU_vertbuf_attr_set(be->vbo, be->pos_id, be->vbo_len, &pt->x);
+ be->vbo_len++;
if (gps->dvert != NULL) {
dvert++;
}
}
-
- return GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
/* Draw lines for strokes being edited */
-GPUBatch *DRW_gpencil_get_edlin_geom(bGPDstroke *gps, float alpha, short UNUSED(dflag))
+void DRW_gpencil_get_edlin_geom(struct GpencilBatchCacheElem *be, bGPDstroke *gps, float alpha, short UNUSED(dflag))
{
const DRWContextState *draw_ctx = DRW_context_state_get();
Object *ob = draw_ctx->obact;
@@ -566,21 +573,22 @@ GPUBatch *DRW_gpencil_get_edlin_geom(bGPDstroke *gps, float alpha, short UNUSED(
float linecolor[4];
copy_v4_v4(linecolor, gpd->line_color);
- static GPUVertFormat format = { 0 };
- static uint pos_id, color_id;
- if (format.attr_len == 0) {
- pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- }
+ if (be->vbo == NULL) {
+ be->pos_id = GPU_vertformat_attr_add(&be->format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ be->color_id = GPU_vertformat_attr_add(&be->format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
- GPU_vertbuf_data_alloc(vbo, gps->totpoints);
+ be->vbo = GPU_vertbuf_create_with_format(&be->format);
+ GPU_vertbuf_data_alloc(be->vbo, gps->totpoints);
+ be->vbo_len = 0;
+ }
+ else {
+ gpencil_vbo_ensure_size(be, gps->totpoints);
+ }
/* Draw all the stroke lines (selected or not) */
bGPDspoint *pt = gps->points;
MDeformVert *dvert = gps->dvert;
- int idx = 0;
float fcolor[4];
for (int i = 0; i < gps->totpoints; i++, pt++) {
/* weight paint */
@@ -600,16 +608,14 @@ GPUBatch *DRW_gpencil_get_edlin_geom(bGPDstroke *gps, float alpha, short UNUSED(
}
}
- GPU_vertbuf_attr_set(vbo, color_id, idx, fcolor);
- GPU_vertbuf_attr_set(vbo, pos_id, idx, &pt->x);
- idx++;
+ GPU_vertbuf_attr_set(be->vbo, be->color_id, be->vbo_len, fcolor);
+ GPU_vertbuf_attr_set(be->vbo, be->pos_id, be->vbo_len, &pt->x);
+ be->vbo_len++;
if (gps->dvert != NULL) {
dvert++;
}
}
-
- return GPU_batch_create_ex(GPU_PRIM_LINE_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
static void set_grid_point(
diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
index cba5cfccaf6..9799ab85cfb 100644
--- a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
@@ -65,6 +65,67 @@
#define GP_SET_SRC_GPS(src_gps) if (src_gps) src_gps = src_gps->next
+/* Get number of vertex for using in GPU VBOs */
+void gpencil_calc_vertex(
+ GPENCIL_StorageList *stl, tGPencilObjectCache *cache_ob,
+ GpencilBatchCache *cache, bGPdata *gpd,
+ int cfra_eval)
+{
+ Object *ob = cache_ob->ob;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ bGPDframe *gpf = NULL;
+
+ const bool time_remap = BKE_gpencil_has_time_modifiers(ob);
+
+ cache_ob->tot_vertex = 0;
+ cache_ob->tot_triangles = 0;
+
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ if (gpl->flag & GP_LAYER_HIDE) {
+ continue;
+ }
+
+ /* verify time modifiers */
+ if ((time_remap) && (!stl->storage->simplify_modif)) {
+ int remap_cfra = BKE_gpencil_time_modifier(
+ draw_ctx->depsgraph, draw_ctx->scene, ob, gpl, cfra_eval,
+ stl->storage->is_render);
+ gpf = BKE_gpencil_layer_getframe(gpl, remap_cfra, GP_GETFRAME_USE_PREV);
+ }
+ else {
+ gpf = gpl->actframe;
+ }
+
+ if (gpf == NULL) {
+ continue;
+ }
+
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ cache_ob->tot_vertex += gps->totpoints + 3;
+ cache_ob->tot_triangles += gps->totpoints - 1;
+ }
+ }
+
+ cache->b_fill.tot_vertex = cache_ob->tot_triangles * 3;
+ cache->b_stroke.tot_vertex = cache_ob->tot_vertex;
+ cache->b_point.tot_vertex = cache_ob->tot_vertex;
+
+ /* some modifiers can change the number of points */
+ int factor = 0;
+ GpencilModifierData *md;
+ for (md = ob->greasepencil_modifiers.first; md; md = md->next) {
+ const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
+ /* only modifiers that change size */
+ if (mti && mti->getDuplicationFactor) {
+ factor = mti->getDuplicationFactor(md);
+
+ cache->b_fill.tot_vertex *= factor;
+ cache->b_stroke.tot_vertex *= factor;
+ cache->b_point.tot_vertex *= factor;
+ }
+ }
+}
+
/* Helper for doing all the checks on whether a stroke can be drawn */
static bool gpencil_can_draw_stroke(
struct MaterialGPencilStyle *gp_style, const bGPDstroke *gps,
@@ -182,79 +243,6 @@ static void gpencil_stroke_2d_flat(const bGPDspoint *points, int totpoints, floa
*r_direction = (int)locy[2];
}
-/* Triangulate stroke for high quality fill (this is done only if cache is null or stroke was modified) */
-void DRW_gpencil_triangulate_stroke_fill(Object *ob, bGPDstroke *gps)
-{
- BLI_assert(gps->totpoints >= 3);
-
- bGPdata *gpd = (bGPdata *)ob->data;
-
- /* allocate memory for temporary areas */
- gps->tot_triangles = gps->totpoints - 2;
- uint(*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * gps->tot_triangles, "GP Stroke temp triangulation");
- float(*points2d)[2] = MEM_mallocN(sizeof(*points2d) * gps->totpoints, "GP Stroke temp 2d points");
- float(*uv)[2] = MEM_mallocN(sizeof(*uv) * gps->totpoints, "GP Stroke temp 2d uv data");
-
- int direction = 0;
-
- /* convert to 2d and triangulate */
- gpencil_stroke_2d_flat(gps->points, gps->totpoints, points2d, &direction);
- BLI_polyfill_calc(points2d, (uint)gps->totpoints, direction, tmp_triangles);
-
- /* calc texture coordinates automatically */
- float minv[2];
- float maxv[2];
- /* first needs bounding box data */
- if (gpd->flag & GP_DATA_UV_ADAPTATIVE) {
- gpencil_calc_2d_bounding_box(points2d, gps->totpoints, minv, maxv);
- }
- else {
- ARRAY_SET_ITEMS(minv, -1.0f, -1.0f);
- ARRAY_SET_ITEMS(maxv, 1.0f, 1.0f);
- }
-
- /* calc uv data */
- gpencil_calc_stroke_fill_uv(points2d, gps->totpoints, minv, maxv, uv);
-
- /* Number of triangles */
- gps->tot_triangles = gps->totpoints - 2;
- /* save triangulation data in stroke cache */
- if (gps->tot_triangles > 0) {
- if (gps->triangles == NULL) {
- gps->triangles = MEM_callocN(sizeof(*gps->triangles) * gps->tot_triangles, "GP Stroke triangulation");
- }
- else {
- gps->triangles = MEM_recallocN(gps->triangles, sizeof(*gps->triangles) * gps->tot_triangles);
- }
-
- for (int i = 0; i < gps->tot_triangles; i++) {
- bGPDtriangle *stroke_triangle = &gps->triangles[i];
- memcpy(gps->triangles[i].verts, tmp_triangles[i], sizeof(uint[3]));
- /* copy texture coordinates */
- copy_v2_v2(stroke_triangle->uv[0], uv[tmp_triangles[i][0]]);
- copy_v2_v2(stroke_triangle->uv[1], uv[tmp_triangles[i][1]]);
- copy_v2_v2(stroke_triangle->uv[2], uv[tmp_triangles[i][2]]);
- }
- }
- else {
- /* No triangles needed - Free anything allocated previously */
- if (gps->triangles)
- MEM_freeN(gps->triangles);
-
- gps->triangles = NULL;
- }
-
- /* disable recalculation flag */
- if (gps->flag & GP_STROKE_RECALC_CACHES) {
- gps->flag &= ~GP_STROKE_RECALC_CACHES;
- }
-
- /* clear memory */
- MEM_SAFE_FREE(tmp_triangles);
- MEM_SAFE_FREE(points2d);
- MEM_SAFE_FREE(uv);
-}
-
/* recalc the internal geometry caches for fill and uvs */
static void DRW_gpencil_recalc_geometry_caches(Object *ob, MaterialGPencilStyle *gp_style, bGPDstroke *gps)
{
@@ -466,7 +454,7 @@ DRWShadingGroup *DRW_gpencil_shgroup_stroke_create(
return grp;
}
-/* create shading group for volumetrics */
+/* create shading group for points */
static DRWShadingGroup *DRW_gpencil_shgroup_point_create(
GPENCIL_e_data *e_data, GPENCIL_Data *vedata, DRWPass *pass, GPUShader *shader, Object *ob,
bGPdata *gpd, MaterialGPencilStyle *gp_style, int id, bool onion)
@@ -559,10 +547,10 @@ static DRWShadingGroup *DRW_gpencil_shgroup_point_create(
return grp;
}
-/* add fill shading group to pass */
-static void gpencil_add_fill_shgroup(
- GpencilBatchCache *cache, DRWShadingGroup *fillgrp,
- Object *ob, bGPDframe *gpf, bGPDstroke *gps,
+/* add fill vertex info */
+static void gpencil_add_fill_vertexdata(
+ GpencilBatchCache *cache,
+ Object *ob, bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps,
float opacity, const float tintcolor[4], const bool onion, const bool custonion)
{
MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
@@ -586,17 +574,24 @@ static void gpencil_add_fill_shgroup(
color = tfill;
}
}
- gpencil_batch_cache_check_free_slots(ob);
- cache->batch_fill[cache->cache_idx] = DRW_gpencil_get_fill_geom(ob, gps, color);
+ /* create vertex data */
+ const int old_len = cache->b_fill.vbo_len;
+ DRW_gpencil_get_fill_geom(&cache->b_fill, ob, gps, color);
+
+ /* add to list of groups */
+ if (old_len < cache->b_fill.vbo_len) {
+ cache->grp_cache = gpencil_group_cache_add(
+ cache->grp_cache, gpl, gpf, gps, eGpencilBatchGroupType_Fill, onion,
+ cache->b_fill.vbo_len,
+ &cache->grp_size, &cache->grp_used);
+ }
}
-
- DRW_shgroup_call_add(fillgrp, cache->batch_fill[cache->cache_idx], gpf->runtime.viewmatrix);
}
}
}
-/* add stroke shading group to pass */
-static void gpencil_add_stroke_shgroup(GpencilBatchCache *cache, DRWShadingGroup *strokegrp,
+/* add stroke vertex info */
+static void gpencil_add_stroke_vertexdata(GpencilBatchCache *cache,
Object *ob, bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps,
const float opacity, const float tintcolor[4], const bool onion,
const bool custonion)
@@ -632,19 +627,38 @@ static void gpencil_add_stroke_shgroup(GpencilBatchCache *cache, DRWShadingGroup
sthickness = gps->thickness + gpl->line_change;
CLAMP_MIN(sthickness, 1);
- gpencil_batch_cache_check_free_slots(ob);
+
if ((gps->totpoints > 1) && (gp_style->mode == GP_STYLE_MODE_LINE)) {
- cache->batch_stroke[cache->cache_idx] = DRW_gpencil_get_stroke_geom(gps, sthickness, ink);
+ /* create vertex data */
+ const int old_len = cache->b_stroke.vbo_len;
+ DRW_gpencil_get_stroke_geom(&cache->b_stroke, gps, sthickness, ink);
+
+ /* add to list of groups */
+ if (old_len < cache->b_stroke.vbo_len) {
+ cache->grp_cache = gpencil_group_cache_add(
+ cache->grp_cache, gpl, gpf, gps, eGpencilBatchGroupType_Stroke, onion,
+ cache->b_stroke.vbo_len,
+ &cache->grp_size, &cache->grp_used);
+ }
}
else {
- cache->batch_stroke[cache->cache_idx] = DRW_gpencil_get_point_geom(gps, sthickness, ink);
+ /* create vertex data */
+ const int old_len = cache->b_point.vbo_len;
+ DRW_gpencil_get_point_geom(&cache->b_point, gps, sthickness, ink);
+
+ /* add to list of groups */
+ if (old_len < cache->b_point.vbo_len) {
+ cache->grp_cache = gpencil_group_cache_add(
+ cache->grp_cache, gpl, gpf, gps, eGpencilBatchGroupType_Point, onion,
+ cache->b_point.vbo_len,
+ &cache->grp_size, &cache->grp_used);
+ }
}
}
- DRW_shgroup_call_add(strokegrp, cache->batch_stroke[cache->cache_idx], gpf->runtime.viewmatrix);
}
-/* add edit points shading group to pass */
-static void gpencil_add_editpoints_shgroup(
+/* add edit points vertex info */
+static void gpencil_add_editpoints_vertexdata(
GPENCIL_StorageList *stl, GpencilBatchCache *cache, ToolSettings *UNUSED(ts), Object *ob,
bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps)
{
@@ -662,36 +676,31 @@ static void gpencil_add_editpoints_shgroup(
}
const bool is_weight_paint = (gpd) && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE);
- /* line of the original stroke */
if (cache->is_dirty) {
- gpencil_batch_cache_check_free_slots(ob);
- cache->batch_edlin[cache->cache_idx] = DRW_gpencil_get_edlin_geom(gps, edit_alpha, gpd->flag);
- }
- if (cache->batch_edlin[cache->cache_idx]) {
- if ((obact) && (obact == ob) &&
- ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) &&
- (v3d->gp_flag & V3D_GP_SHOW_EDIT_LINES))
+ if ((obact == ob) &&
+ ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) &&
+ (v3d->gp_flag & V3D_GP_SHOW_EDIT_LINES))
{
- DRW_shgroup_call_add(
- stl->g_data->shgrps_edit_line,
- cache->batch_edlin[cache->cache_idx],
- gpf->runtime.viewmatrix);
+ /* line of the original stroke */
+ DRW_gpencil_get_edlin_geom(&cache->b_edlin, gps, edit_alpha, gpd->flag);
+
+ /* add to list of groups */
+ cache->grp_cache = gpencil_group_cache_add(
+ cache->grp_cache, gpl, gpf, gps, eGpencilBatchGroupType_Edlin, false,
+ cache->b_edlin.vbo_len,
+ &cache->grp_size, &cache->grp_used);
}
- }
- /* edit points */
- if ((gps->flag & GP_STROKE_SELECT) || (is_weight_paint)) {
- if ((gpl->flag & GP_LAYER_UNLOCK_COLOR) || ((gp_style->flag & GP_STYLE_COLOR_LOCKED) == 0)) {
- if (cache->is_dirty) {
- gpencil_batch_cache_check_free_slots(ob);
- cache->batch_edit[cache->cache_idx] = DRW_gpencil_get_edit_geom(gps, edit_alpha, gpd->flag);
- }
- if (cache->batch_edit[cache->cache_idx]) {
- if ((obact) && (obact == ob)) {
- /* edit pass */
- DRW_shgroup_call_add(
- stl->g_data->shgrps_edit_point,
- cache->batch_edit[cache->cache_idx],
- gpf->runtime.viewmatrix);
+ /* edit points */
+ if ((gps->flag & GP_STROKE_SELECT) || (is_weight_paint)) {
+ if ((gpl->flag & GP_LAYER_UNLOCK_COLOR) || ((gp_style->flag & GP_STYLE_COLOR_LOCKED) == 0)) {
+ if (obact == ob) {
+ DRW_gpencil_get_edit_geom(&cache->b_edit, gps, edit_alpha, gpd->flag);
+
+ /* add to list of groups */
+ cache->grp_cache = gpencil_group_cache_add(
+ cache->grp_cache, gpl, gpf, gps, eGpencilBatchGroupType_Edit, false,
+ cache->b_edit.vbo_len,
+ &cache->grp_size, &cache->grp_used);
}
}
}
@@ -699,57 +708,6 @@ static void gpencil_add_editpoints_shgroup(
}
}
-/* function to draw strokes for onion only */
-static void gpencil_draw_onion_strokes(
- GpencilBatchCache *cache, GPENCIL_e_data *e_data, void *vedata, Object *ob,
- bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf,
- const float opacity, const float tintcolor[4], const bool custonion)
-{
- GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- Depsgraph *depsgraph = DRW_context_state_get()->depsgraph;
-
- float viewmatrix[4][4];
-
- /* get parent matrix and save as static data */
- ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, viewmatrix);
- copy_m4_m4(gpf->runtime.viewmatrix, viewmatrix);
-
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
- MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
- copy_v4_v4(gps->runtime.tmp_stroke_rgba, gp_style->stroke_rgba);
- copy_v4_v4(gps->runtime.tmp_fill_rgba, gp_style->fill_rgba);
-
- int id = stl->storage->shgroup_id;
- /* check if stroke can be drawn */
- if (gpencil_can_draw_stroke(gp_style, gps, true, false) == false) {
- continue;
- }
- /* limit the number of shading groups */
- if (id >= GPENCIL_MAX_SHGROUPS) {
- continue;
- }
-
- stl->shgroups[id].shgrps_fill = NULL;
- if ((gps->totpoints > 1) && (gp_style->mode == GP_STYLE_MODE_LINE)) {
- stl->shgroups[id].shgrps_stroke = DRW_gpencil_shgroup_stroke_create(
- e_data, vedata, psl->stroke_pass, e_data->gpencil_stroke_sh, ob, gpd, gp_style, id, true);
- }
- else {
- stl->shgroups[id].shgrps_stroke = DRW_gpencil_shgroup_point_create(
- e_data, vedata, psl->stroke_pass, e_data->gpencil_point_sh, ob, gpd, gp_style, id, true);
- }
-
- /* stroke */
- gpencil_add_stroke_shgroup(
- cache, stl->shgroups[id].shgrps_stroke, ob, gpl, gpf, gps, opacity, tintcolor, true, custonion);
-
- stl->storage->shgroup_id++;
- cache->cache_idx++;
- }
-}
-
-
/* main function to draw strokes */
static void gpencil_draw_strokes(
GpencilBatchCache *cache, GPENCIL_e_data *e_data, void *vedata, ToolSettings *ts, Object *ob,
@@ -763,8 +721,6 @@ static void gpencil_draw_strokes(
Scene *scene = draw_ctx->scene;
View3D *v3d = draw_ctx->v3d;
bGPDstroke *gps, *src_gps;
- DRWShadingGroup *fillgrp;
- DRWShadingGroup *strokegrp;
float viewmatrix[4][4];
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
const bool playing = stl->storage->is_playing;
@@ -810,11 +766,6 @@ static void gpencil_draw_strokes(
GP_SET_SRC_GPS(src_gps);
continue;
}
- /* limit the number of shading groups */
- if (stl->storage->shgroup_id >= GPENCIL_MAX_SHGROUPS) {
- GP_SET_SRC_GPS(src_gps);
- continue;
- }
/* be sure recalc all cache in source stroke to avoid recalculation when frame change
* and improve fps */
@@ -835,38 +786,6 @@ static void gpencil_draw_strokes(
if ((gpl->actframe->framenum == derived_gpf->framenum) ||
(!is_multiedit) || (overlay_multiedit))
{
- int id = stl->storage->shgroup_id;
- if (gps->totpoints > 0) {
- if ((gps->totpoints > 2) && (!stl->storage->simplify_fill) &&
- ((gp_style->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) || (gp_style->fill_style > 0)) &&
- ((gps->flag & GP_STROKE_NOFILL) == 0) &&
- (gp_style->flag & GP_STYLE_FILL_SHOW))
- {
- stl->shgroups[id].shgrps_fill = DRW_gpencil_shgroup_fill_create(
- e_data, vedata, psl->stroke_pass, e_data->gpencil_fill_sh,
- gpd, gpl, gp_style, id);
- }
- else {
- stl->shgroups[id].shgrps_fill = NULL;
- }
- if ((gp_style->mode == GP_STYLE_MODE_LINE) && (gps->totpoints > 1)) {
- stl->shgroups[id].shgrps_stroke = DRW_gpencil_shgroup_stroke_create(
- e_data, vedata, psl->stroke_pass, e_data->gpencil_stroke_sh, ob, gpd, gp_style, id, false);
- }
- else {
- stl->shgroups[id].shgrps_stroke = DRW_gpencil_shgroup_point_create(
- e_data, vedata, psl->stroke_pass, e_data->gpencil_point_sh, ob, gpd, gp_style, id, false);
- }
- }
- else {
- stl->shgroups[id].shgrps_fill = NULL;
- stl->shgroups[id].shgrps_stroke = NULL;
- }
- stl->storage->shgroup_id++;
-
- fillgrp = stl->shgroups[id].shgrps_fill;
- strokegrp = stl->shgroups[id].shgrps_stroke;
-
/* copy color to temp fields to apply temporal changes in the stroke */
copy_v4_v4(gps->runtime.tmp_stroke_rgba, gp_style->stroke_rgba);
copy_v4_v4(gps->runtime.tmp_fill_rgba, gp_style->fill_rgba);
@@ -879,17 +798,20 @@ static void gpencil_draw_strokes(
}
/* fill */
- if ((fillgrp) && (!stl->storage->simplify_fill)) {
- gpencil_add_fill_shgroup(
- cache, fillgrp, ob, derived_gpf, gps,
+ if ((gp_style->flag & GP_STYLE_FILL_SHOW) &&
+ (!stl->storage->simplify_fill))
+ {
+ gpencil_add_fill_vertexdata(
+ cache, ob, gpl, derived_gpf, gps,
opacity, tintcolor, false, custonion);
}
/* stroke */
- if (strokegrp) {
- const float nop = ((gp_style->flag & GP_STYLE_STROKE_SHOW) == 0) || (gp_style->stroke_rgba[3] < GPENCIL_ALPHA_OPACITY_THRESH) ? 0.0f : opacity;
- gpencil_add_stroke_shgroup(
- cache, strokegrp, ob, gpl, derived_gpf, gps,
- nop, tintcolor, false, custonion);
+ if ((gp_style->flag & GP_STYLE_STROKE_SHOW) &&
+ (gp_style->stroke_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH))
+ {
+ gpencil_add_stroke_vertexdata(
+ cache, ob, gpl, derived_gpf, gps,
+ opacity, tintcolor, false, custonion);
}
}
@@ -907,118 +829,11 @@ static void gpencil_draw_strokes(
DRW_shgroup_uniform_vec2(stl->g_data->shgrps_edit_point, "Viewport", viewport_size, 1);
}
- gpencil_add_editpoints_shgroup(stl, cache, ts, ob, gpd, gpl, derived_gpf, src_gps);
- }
- else {
- gpencil_batch_cache_check_free_slots(ob);
+ gpencil_add_editpoints_vertexdata(stl, cache, ts, ob, gpd, gpl, derived_gpf, src_gps);
}
}
GP_SET_SRC_GPS(src_gps);
-
- cache->cache_idx++;
- }
-}
-
- /* draw stroke in drawing buffer */
-void DRW_gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, void *vedata, ToolSettings *ts, Object *ob)
-{
- GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- Brush *brush = BKE_paint_brush(&ts->gp_paint->paint);
- bGPdata *gpd_eval = ob->data;
- /* need the original to avoid cow overhead while drawing */
- bGPdata *gpd = (bGPdata *)DEG_get_original_id(&gpd_eval->id);
-
- MaterialGPencilStyle *gp_style = NULL;
-
- float obscale = mat4_to_scale(ob->obmat);
-
- /* use the brush material */
- Material *ma = BKE_gpencil_get_material_from_brush(brush);
- if (ma != NULL) {
- gp_style = ma->gp_style;
- }
- /* this is not common, but avoid any special situations when brush could be without material */
- if (gp_style == NULL) {
- gp_style = BKE_material_gpencil_settings_get(ob, ob->actcol);
- }
-
- /* drawing strokes */
- /* Check if may need to draw the active stroke cache, only if this layer is the active layer
- * that is being edited. (Stroke buffer is currently stored in gp-data)
- */
- if (ED_gpencil_session_active() && (gpd->runtime.sbuffer_size > 0)) {
- if ((gpd->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0) {
- /* It should also be noted that sbuffer contains temporary point types
- * i.e. tGPspoints NOT bGPDspoints
- */
- short lthick = brush->size * obscale;
- /* if only one point, don't need to draw buffer because the user has no time to see it */
- if (gpd->runtime.sbuffer_size > 1) {
- if ((gp_style) && (gp_style->mode == GP_STYLE_MODE_LINE)) {
- stl->g_data->shgrps_drawing_stroke = DRW_gpencil_shgroup_stroke_create(
- e_data, vedata, psl->drawing_pass, e_data->gpencil_stroke_sh, NULL, gpd, gp_style, -1, false);
- }
- else {
- stl->g_data->shgrps_drawing_stroke = DRW_gpencil_shgroup_point_create(
- e_data, vedata, psl->drawing_pass, e_data->gpencil_point_sh, NULL, gpd, gp_style, -1, false);
- }
-
- /* clean previous version of the batch */
- if (stl->storage->buffer_stroke) {
- GPU_BATCH_DISCARD_SAFE(e_data->batch_buffer_stroke);
- MEM_SAFE_FREE(e_data->batch_buffer_stroke);
- stl->storage->buffer_stroke = false;
- }
-
- /* use unit matrix because the buffer is in screen space and does not need conversion */
- if (gpd->runtime.mode == GP_STYLE_MODE_LINE) {
- e_data->batch_buffer_stroke = DRW_gpencil_get_buffer_stroke_geom(
- gpd, lthick);
- }
- else {
- e_data->batch_buffer_stroke = DRW_gpencil_get_buffer_point_geom(
- gpd, lthick);
- }
-
- if (gp_style->flag & GP_STYLE_STROKE_SHOW) {
- DRW_shgroup_call_add(
- stl->g_data->shgrps_drawing_stroke,
- e_data->batch_buffer_stroke,
- stl->storage->unit_matrix);
- }
-
- if ((gpd->runtime.sbuffer_size >= 3) &&
- (gpd->runtime.sfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) &&
- ((gpd->runtime.sbuffer_sflag & GP_STROKE_NOFILL) == 0) &&
- ((brush->gpencil_settings->flag & GP_BRUSH_DISSABLE_LASSO) == 0) &&
- (gp_style->flag & GP_STYLE_FILL_SHOW))
- {
- /* if not solid, fill is simulated with solid color */
- if (gpd->runtime.bfill_style > 0) {
- gpd->runtime.sfill[3] = 0.5f;
- }
- stl->g_data->shgrps_drawing_fill = DRW_shgroup_create(
- e_data->gpencil_drawing_fill_sh, psl->drawing_pass);
-
- /* clean previous version of the batch */
- if (stl->storage->buffer_fill) {
- GPU_BATCH_DISCARD_SAFE(e_data->batch_buffer_fill);
- MEM_SAFE_FREE(e_data->batch_buffer_fill);
- stl->storage->buffer_fill = false;
- }
-
- e_data->batch_buffer_fill = DRW_gpencil_get_buffer_fill_geom(gpd);
- DRW_shgroup_call_add(
- stl->g_data->shgrps_drawing_fill,
- e_data->batch_buffer_fill,
- stl->storage->unit_matrix);
- stl->storage->buffer_fill = true;
- }
- stl->storage->buffer_stroke = true;
- }
- }
}
}
@@ -1039,6 +854,44 @@ static void gpencil_get_onion_alpha(float color[4], bGPdata *gpd)
CLAMP(color[3], MIN_ALPHA_VALUE, 1.0f);
}
+/* function to draw strokes for onion only */
+static void gpencil_draw_onion_strokes(
+ GpencilBatchCache *cache, GPENCIL_e_data *e_data, void *vedata, Object *ob,
+ bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf,
+ const float opacity, const float tintcolor[4], const bool custonion)
+{
+ GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+ Depsgraph *depsgraph = DRW_context_state_get()->depsgraph;
+
+ float viewmatrix[4][4];
+
+ /* get parent matrix and save as static data */
+ ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, viewmatrix);
+ copy_m4_m4(gpf->runtime.viewmatrix, viewmatrix);
+
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
+ copy_v4_v4(gps->runtime.tmp_stroke_rgba, gp_style->stroke_rgba);
+ copy_v4_v4(gps->runtime.tmp_fill_rgba, gp_style->fill_rgba);
+
+ int id = stl->storage->shgroup_id;
+ /* check if stroke can be drawn */
+ if (gpencil_can_draw_stroke(gp_style, gps, true, false) == false) {
+ continue;
+ }
+ /* limit the number of shading groups */
+ if (id >= GPENCIL_MAX_SHGROUPS) {
+ continue;
+ }
+
+ /* stroke */
+ gpencil_add_stroke_vertexdata(
+ cache, ob, gpl, gpf, gps, opacity, tintcolor, true, custonion);
+
+ stl->storage->shgroup_id++;
+ }
+}
+
/* draw onion-skinning for a layer */
static void gpencil_draw_onionskins(
GpencilBatchCache *cache, GPENCIL_e_data *e_data, void *vedata,
@@ -1058,7 +911,6 @@ static void gpencil_draw_onionskins(
colflag = (bool)gpd->onion_flag & GP_ONION_GHOST_PREVCOL;
-
/* -------------------------------
* 1) Draw Previous Frames First
* ------------------------------- */
@@ -1183,9 +1035,348 @@ static void gpencil_draw_onionskins(
}
}
+static void gpencil_copy_frame(bGPDframe *gpf, bGPDframe *derived_gpf)
+{
+ derived_gpf->prev = gpf->prev;
+ derived_gpf->next = gpf->next;
+ derived_gpf->framenum = gpf->framenum;
+ derived_gpf->flag = gpf->flag;
+ derived_gpf->key_type = gpf->key_type;
+ derived_gpf->runtime = gpf->runtime;
+ copy_m4_m4(derived_gpf->runtime.viewmatrix, gpf->runtime.viewmatrix);
+
+ /* copy strokes */
+ BLI_listbase_clear(&derived_gpf->strokes);
+ for (bGPDstroke *gps_src = gpf->strokes.first; gps_src; gps_src = gps_src->next) {
+ /* make copy of source stroke */
+ bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps_src);
+ BLI_addtail(&derived_gpf->strokes, gps_dst);
+ }
+}
+
+/* Triangulate stroke for high quality fill (this is done only if cache is null or stroke was modified) */
+void DRW_gpencil_triangulate_stroke_fill(Object *ob, bGPDstroke *gps)
+{
+ BLI_assert(gps->totpoints >= 3);
+
+ bGPdata *gpd = (bGPdata *)ob->data;
+
+ /* allocate memory for temporary areas */
+ gps->tot_triangles = gps->totpoints - 2;
+ uint(*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * gps->tot_triangles, "GP Stroke temp triangulation");
+ float(*points2d)[2] = MEM_mallocN(sizeof(*points2d) * gps->totpoints, "GP Stroke temp 2d points");
+ float(*uv)[2] = MEM_mallocN(sizeof(*uv) * gps->totpoints, "GP Stroke temp 2d uv data");
+
+ int direction = 0;
+
+ /* convert to 2d and triangulate */
+ gpencil_stroke_2d_flat(gps->points, gps->totpoints, points2d, &direction);
+ BLI_polyfill_calc(points2d, (uint)gps->totpoints, direction, tmp_triangles);
+
+ /* calc texture coordinates automatically */
+ float minv[2];
+ float maxv[2];
+ /* first needs bounding box data */
+ if (gpd->flag & GP_DATA_UV_ADAPTATIVE) {
+ gpencil_calc_2d_bounding_box(points2d, gps->totpoints, minv, maxv);
+ }
+ else {
+ ARRAY_SET_ITEMS(minv, -1.0f, -1.0f);
+ ARRAY_SET_ITEMS(maxv, 1.0f, 1.0f);
+ }
+
+ /* calc uv data */
+ gpencil_calc_stroke_fill_uv(points2d, gps->totpoints, minv, maxv, uv);
+
+ /* Number of triangles */
+ gps->tot_triangles = gps->totpoints - 2;
+ /* save triangulation data in stroke cache */
+ if (gps->tot_triangles > 0) {
+ if (gps->triangles == NULL) {
+ gps->triangles = MEM_callocN(sizeof(*gps->triangles) * gps->tot_triangles, "GP Stroke triangulation");
+ }
+ else {
+ gps->triangles = MEM_recallocN(gps->triangles, sizeof(*gps->triangles) * gps->tot_triangles);
+ }
+
+ for (int i = 0; i < gps->tot_triangles; i++) {
+ bGPDtriangle *stroke_triangle = &gps->triangles[i];
+ memcpy(gps->triangles[i].verts, tmp_triangles[i], sizeof(uint[3]));
+ /* copy texture coordinates */
+ copy_v2_v2(stroke_triangle->uv[0], uv[tmp_triangles[i][0]]);
+ copy_v2_v2(stroke_triangle->uv[1], uv[tmp_triangles[i][1]]);
+ copy_v2_v2(stroke_triangle->uv[2], uv[tmp_triangles[i][2]]);
+ }
+ }
+ else {
+ /* No triangles needed - Free anything allocated previously */
+ if (gps->triangles)
+ MEM_freeN(gps->triangles);
+
+ gps->triangles = NULL;
+ }
+
+ /* disable recalculation flag */
+ if (gps->flag & GP_STROKE_RECALC_CACHES) {
+ gps->flag &= ~GP_STROKE_RECALC_CACHES;
+ }
+
+ /* clear memory */
+ MEM_SAFE_FREE(tmp_triangles);
+ MEM_SAFE_FREE(points2d);
+ MEM_SAFE_FREE(uv);
+}
+
+/* draw stroke in drawing buffer */
+void DRW_gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, void *vedata, ToolSettings *ts, Object *ob)
+{
+ GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
+ GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+ Brush *brush = BKE_paint_brush(&ts->gp_paint->paint);
+ bGPdata *gpd_eval = ob->data;
+ /* need the original to avoid cow overhead while drawing */
+ bGPdata *gpd = (bGPdata *)DEG_get_original_id(&gpd_eval->id);
+
+ MaterialGPencilStyle *gp_style = NULL;
+
+ float obscale = mat4_to_scale(ob->obmat);
+
+ /* use the brush material */
+ Material *ma = BKE_gpencil_get_material_from_brush(brush);
+ if (ma != NULL) {
+ gp_style = ma->gp_style;
+ }
+ /* this is not common, but avoid any special situations when brush could be without material */
+ if (gp_style == NULL) {
+ gp_style = BKE_material_gpencil_settings_get(ob, ob->actcol);
+ }
+
+ /* drawing strokes */
+ /* Check if may need to draw the active stroke cache, only if this layer is the active layer
+ * that is being edited. (Stroke buffer is currently stored in gp-data)
+ */
+ if (ED_gpencil_session_active() && (gpd->runtime.sbuffer_size > 0)) {
+ if ((gpd->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0) {
+ /* It should also be noted that sbuffer contains temporary point types
+ * i.e. tGPspoints NOT bGPDspoints
+ */
+ short lthick = brush->size * obscale;
+ /* if only one point, don't need to draw buffer because the user has no time to see it */
+ if (gpd->runtime.sbuffer_size > 1) {
+ if ((gp_style) && (gp_style->mode == GP_STYLE_MODE_LINE)) {
+ stl->g_data->shgrps_drawing_stroke = DRW_gpencil_shgroup_stroke_create(
+ e_data, vedata, psl->drawing_pass, e_data->gpencil_stroke_sh, NULL, gpd, gp_style, -1, false);
+ }
+ else {
+ stl->g_data->shgrps_drawing_stroke = DRW_gpencil_shgroup_point_create(
+ e_data, vedata, psl->drawing_pass, e_data->gpencil_point_sh, NULL, gpd, gp_style, -1, false);
+ }
+
+ /* clean previous version of the batch */
+ if (stl->storage->buffer_stroke) {
+ GPU_BATCH_DISCARD_SAFE(e_data->batch_buffer_stroke);
+ MEM_SAFE_FREE(e_data->batch_buffer_stroke);
+ stl->storage->buffer_stroke = false;
+ }
+
+ /* use unit matrix because the buffer is in screen space and does not need conversion */
+ if (gpd->runtime.mode == GP_STYLE_MODE_LINE) {
+ e_data->batch_buffer_stroke = DRW_gpencil_get_buffer_stroke_geom(
+ gpd, lthick);
+ }
+ else {
+ e_data->batch_buffer_stroke = DRW_gpencil_get_buffer_point_geom(
+ gpd, lthick);
+ }
+
+ if (gp_style->flag & GP_STYLE_STROKE_SHOW) {
+ DRW_shgroup_call_add(
+ stl->g_data->shgrps_drawing_stroke,
+ e_data->batch_buffer_stroke,
+ stl->storage->unit_matrix);
+ }
+
+ if ((gpd->runtime.sbuffer_size >= 3) &&
+ (gpd->runtime.sfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) &&
+ ((gpd->runtime.sbuffer_sflag & GP_STROKE_NOFILL) == 0) &&
+ ((brush->gpencil_settings->flag & GP_BRUSH_DISSABLE_LASSO) == 0) &&
+ (gp_style->flag & GP_STYLE_FILL_SHOW))
+ {
+ /* if not solid, fill is simulated with solid color */
+ if (gpd->runtime.bfill_style > 0) {
+ gpd->runtime.sfill[3] = 0.5f;
+ }
+ stl->g_data->shgrps_drawing_fill = DRW_shgroup_create(
+ e_data->gpencil_drawing_fill_sh, psl->drawing_pass);
+
+ /* clean previous version of the batch */
+ if (stl->storage->buffer_fill) {
+ GPU_BATCH_DISCARD_SAFE(e_data->batch_buffer_fill);
+ MEM_SAFE_FREE(e_data->batch_buffer_fill);
+ stl->storage->buffer_fill = false;
+ }
+
+ e_data->batch_buffer_fill = DRW_gpencil_get_buffer_fill_geom(gpd);
+ DRW_shgroup_call_add(
+ stl->g_data->shgrps_drawing_fill,
+ e_data->batch_buffer_fill,
+ stl->storage->unit_matrix);
+ stl->storage->buffer_fill = true;
+ }
+ stl->storage->buffer_stroke = true;
+ }
+ }
+ }
+}
+
+/* create all missing batches */
+static void DRW_gpencil_create_batches(GpencilBatchCache *cache)
+{
+ if ((cache->b_point.vbo) && (cache->b_point.batch == NULL)) {
+ cache->b_point.batch = GPU_batch_create_ex(GPU_PRIM_POINTS, cache->b_point.vbo, NULL, GPU_BATCH_OWNS_VBO);
+ }
+ if ((cache->b_stroke.vbo) && (cache->b_stroke.batch == NULL)) {
+ cache->b_stroke.batch = GPU_batch_create_ex(GPU_PRIM_LINE_STRIP_ADJ, cache->b_stroke.vbo, NULL, GPU_BATCH_OWNS_VBO);
+ }
+ if ((cache->b_fill.vbo) && (cache->b_fill.batch == NULL)) {
+ cache->b_fill.batch = GPU_batch_create_ex(GPU_PRIM_TRIS, cache->b_fill.vbo, NULL, GPU_BATCH_OWNS_VBO);
+ }
+ if ((cache->b_edit.vbo) && (cache->b_edit.batch == NULL)) {
+ cache->b_edit.batch = GPU_batch_create_ex(GPU_PRIM_POINTS, cache->b_edit.vbo, NULL, GPU_BATCH_OWNS_VBO);
+ }
+ if ((cache->b_edlin.vbo) && (cache->b_edlin.batch == NULL)) {
+ cache->b_edlin.batch = GPU_batch_create_ex(GPU_PRIM_LINE_STRIP, cache->b_edlin.vbo, NULL, GPU_BATCH_OWNS_VBO);
+ }
+}
+
+/* create all shading groups */
+static void DRW_gpencil_shgroups_create(
+ GPENCIL_e_data *e_data, void *vedata,
+ Object *ob, bGPdata *gpd,
+ GpencilBatchCache *cache, tGPencilObjectCache *cache_ob)
+{
+ GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+ GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
+ DRWShadingGroup *shgrp = NULL;
+
+ int start_stroke = 0;
+ int start_point = 0;
+ int start_fill = 0;
+ int start_edit = 0;
+ int start_edlin = 0;
+
+ cache_ob->init_grp = NULL;
+ cache_ob->end_grp = NULL;
+
+ for (int i = 0; i < cache->grp_used; i++) {
+ GpencilBatchGroup *elm = &cache->grp_cache[i];
+ bGPDlayer *gpl = elm->gpl;
+ bGPDframe *gpf = elm->gpf;
+ bGPDstroke *gps = elm->gps;
+ MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
+
+ /* limit the number of shading groups */
+ if (i >= GPENCIL_MAX_SHGROUPS) {
+ break;
+ }
+
+ switch (elm->type) {
+ case eGpencilBatchGroupType_Stroke:
+ {
+ const int len = elm->vertex_idx - start_stroke;
+
+ shgrp = DRW_gpencil_shgroup_stroke_create(
+ e_data, vedata, psl->stroke_pass, e_data->gpencil_stroke_sh,
+ ob, gpd, gp_style, stl->storage->shgroup_id, elm->onion);
+
+ DRW_shgroup_call_range_add(
+ shgrp, cache->b_stroke.batch,
+ (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : cache_ob->obmat,
+ start_stroke, len);
+
+ stl->storage->shgroup_id++;
+ start_stroke = elm->vertex_idx;
+ break;
+ }
+ case eGpencilBatchGroupType_Point:
+ {
+ const int len = elm->vertex_idx - start_point;
+
+ shgrp = DRW_gpencil_shgroup_point_create(
+ e_data, vedata, psl->stroke_pass, e_data->gpencil_point_sh,
+ ob, gpd, gp_style, stl->storage->shgroup_id, elm->onion);
+
+ DRW_shgroup_call_range_add(
+ shgrp, cache->b_point.batch,
+ (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : cache_ob->obmat,
+ start_point, len);
+
+ stl->storage->shgroup_id++;
+ start_point = elm->vertex_idx;
+ break;
+ }
+ case eGpencilBatchGroupType_Fill:
+ {
+ const int len = elm->vertex_idx - start_fill;
+
+ shgrp = DRW_gpencil_shgroup_fill_create(
+ e_data, vedata, psl->stroke_pass, e_data->gpencil_fill_sh,
+ gpd, gpl, gp_style, stl->storage->shgroup_id);
+
+ DRW_shgroup_call_range_add(
+ shgrp, cache->b_fill.batch,
+ (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : cache_ob->obmat,
+ start_fill, len);
+
+ stl->storage->shgroup_id++;
+ start_fill = elm->vertex_idx;
+ break;
+ }
+ case eGpencilBatchGroupType_Edit:
+ {
+ const int len = elm->vertex_idx - start_edit;
+ /* use always the same group */
+ DRW_shgroup_call_range_add(
+ stl->g_data->shgrps_edit_point,
+ cache->b_edit.batch,
+ (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : cache_ob->obmat,
+ start_edit, len);
+
+ start_edit = elm->vertex_idx;
+ break;
+ }
+ case eGpencilBatchGroupType_Edlin:
+ {
+ const int len = elm->vertex_idx - start_edlin;
+ /* use always the same group */
+ DRW_shgroup_call_range_add(
+ stl->g_data->shgrps_edit_line,
+ cache->b_edlin.batch,
+ (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : cache_ob->obmat,
+ start_edlin, len);
+
+ start_edlin = elm->vertex_idx;
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ /* save first group */
+ if ((shgrp != NULL) && (cache_ob->init_grp == NULL)) {
+ cache_ob->init_grp = shgrp;
+ }
+ }
+
+ /* save last group */
+ if (shgrp != NULL) {
+ cache_ob->end_grp = shgrp;
+ }
+}
/* populate a datablock for multiedit (no onions, no modifiers) */
void DRW_gpencil_populate_multiedit(
- GPENCIL_e_data *e_data, void *vedata, Scene *scene, Object *ob,
+ GPENCIL_e_data *e_data, void *vedata, Object *ob,
tGPencilObjectCache *cache_ob)
{
bGPdata *gpd = (bGPdata *)ob->data;
@@ -1195,12 +1386,15 @@ void DRW_gpencil_populate_multiedit(
const DRWContextState *draw_ctx = DRW_context_state_get();
int cfra_eval = (int)DEG_get_ctime(draw_ctx->depsgraph);
GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra_eval);
+ Scene *scene = draw_ctx->scene;
ToolSettings *ts = scene->toolsettings;
- cache->cache_idx = 0;
/* check if playing animation */
bool playing = stl->storage->is_playing;
+ /* calc max size of VBOs */
+ gpencil_calc_vertex(stl, cache_ob, cache, gpd, cfra_eval);
+
/* draw strokes */
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
/* don't draw layer if hidden */
@@ -1228,36 +1422,23 @@ void DRW_gpencil_populate_multiedit(
}
- cache->is_dirty = false;
-}
-
-static void gpencil_copy_frame(bGPDframe *gpf, bGPDframe *derived_gpf)
-{
- derived_gpf->prev = gpf->prev;
- derived_gpf->next = gpf->next;
- derived_gpf->framenum = gpf->framenum;
- derived_gpf->flag = gpf->flag;
- derived_gpf->key_type = gpf->key_type;
- derived_gpf->runtime = gpf->runtime;
+ /* create batchs and shading groups */
+ DRW_gpencil_create_batches(cache);
+ DRW_gpencil_shgroups_create(e_data, vedata, ob, gpd, cache, cache_ob);
- /* copy strokes */
- BLI_listbase_clear(&derived_gpf->strokes);
- for (bGPDstroke *gps_src = gpf->strokes.first; gps_src; gps_src = gps_src->next) {
- /* make copy of source stroke */
- bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps_src);
- BLI_addtail(&derived_gpf->strokes, gps_dst);
- }
+ cache->is_dirty = false;
}
/* helper for populate a complete grease pencil datablock */
void DRW_gpencil_populate_datablock(
GPENCIL_e_data *e_data, void *vedata,
- Scene *scene, Object *ob,
+ Object *ob,
tGPencilObjectCache *cache_ob)
{
GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
const DRWContextState *draw_ctx = DRW_context_state_get();
const ViewLayer *view_layer = DEG_get_evaluated_view_layer(draw_ctx->depsgraph);
+ Scene *scene = draw_ctx->scene;
bGPdata *gpd_eval = (bGPdata *)ob->data;
bGPdata *gpd = (bGPdata *)DEG_get_original_id(&gpd_eval->id);
@@ -1273,7 +1454,6 @@ void DRW_gpencil_populate_datablock(
const bool time_remap = BKE_gpencil_has_time_modifiers(ob);
float opacity;
- bGPDframe *p = NULL;
bGPDframe *gpf = NULL;
bGPDlayer *gpl_active = BKE_gpencil_layer_getactive(gpd);
@@ -1281,7 +1461,15 @@ void DRW_gpencil_populate_datablock(
bool playing = stl->storage->is_playing;
GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra_eval);
- cache->cache_idx = 0;
+
+ /* if object is duplicate, only create shading groups */
+ if (cache_ob->is_dup_ob) {
+ DRW_gpencil_shgroups_create(e_data, vedata, ob, gpd, cache, cache_ob);
+ return;
+ }
+
+ /* calc max size of VBOs */
+ gpencil_calc_vertex(stl, cache_ob, cache, gpd, cfra_eval);
/* init general modifiers data */
if (!stl->storage->simplify_modif) {
@@ -1302,16 +1490,15 @@ void DRW_gpencil_populate_datablock(
}
}
- if ((!time_remap) || (stl->storage->simplify_modif)) {
- gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_USE_PREV);
+ /* remap time */
+ int remap_cfra = cfra_eval;
+ if ((time_remap) && (!stl->storage->simplify_modif)) {
+ remap_cfra = BKE_gpencil_time_modifier(
+ draw_ctx->depsgraph, scene, ob, gpl, cfra_eval,
+ stl->storage->is_render);
}
- else {
- int remap_cfra = BKE_gpencil_time_modifier(
- draw_ctx->depsgraph, scene, ob, gpl, cfra_eval,
- stl->storage->is_render);
- gpf = BKE_gpencil_layer_getframe(gpl, remap_cfra, GP_GETFRAME_USE_PREV);
- }
+ gpf = BKE_gpencil_layer_getframe(gpl, remap_cfra, GP_GETFRAME_USE_PREV);
if (gpf == NULL)
continue;
@@ -1331,24 +1518,9 @@ void DRW_gpencil_populate_datablock(
opacity = opacity * v3d->overlay.gpencil_fade_layer;
}
- /* create derived array data or expand */
- if (cache_ob->data_idx + 1 > gpl->runtime.len_derived) {
- if ((gpl->runtime.len_derived == 0) ||
- (gpl->runtime.derived_array == NULL))
- {
- p = MEM_callocN(sizeof(struct bGPDframe), "bGPDframe array");
- gpl->runtime.len_derived = 1;
- }
- else {
- gpl->runtime.len_derived++;
- p = MEM_recallocN(gpl->runtime.derived_array, sizeof(struct bGPDframe) * gpl->runtime.len_derived);
- }
- gpl->runtime.derived_array = p;
-
- derived_gpf = &gpl->runtime.derived_array[cache_ob->data_idx];
- }
-
- derived_gpf = &gpl->runtime.derived_array[cache_ob->data_idx];
+ /* create derived frames array data or expand */
+ int derived_idx = BLI_findindex(&gpd->layers, gpl);
+ derived_gpf = &cache->derived_array[derived_idx];
/* if no derived frame or dirty cache, create a new one */
if ((derived_gpf == NULL) || (cache->is_dirty)) {
@@ -1362,8 +1534,7 @@ void DRW_gpencil_populate_datablock(
/* draw onion skins */
if (!ID_IS_LINKED(&gpd->id)) {
- if ((!cache_ob->is_dup_data) &&
- (gpd->flag & GP_DATA_SHOW_ONIONSKINS) &&
+ if ((gpd->flag & GP_DATA_SHOW_ONIONSKINS) &&
(do_onion) && (gpl->onion_flag & GP_LAYER_ONIONSKIN) &&
((!playing) || (gpd->onion_flag & GP_ONION_GHOST_ALWAYS)) &&
(!cache_ob->is_dup_ob) && (gpd->id.us <= 1))
@@ -1376,18 +1547,9 @@ void DRW_gpencil_populate_datablock(
}
}
/* draw normal strokes */
- if (!cache_ob->is_dup_ob) {
- /* save batch index */
- gpl->runtime.batch_index = cache->cache_idx;
- }
- else {
- cache->cache_idx = gpl->runtime.batch_index;
- }
-
gpencil_draw_strokes(
cache, e_data, vedata, ts, ob, gpd, gpl, gpf, derived_gpf,
opacity, gpl->tintcolor, false, cache_ob);
-
}
/* clear any lattice data */
@@ -1395,5 +1557,25 @@ void DRW_gpencil_populate_datablock(
BKE_gpencil_lattice_clear(ob);
}
+ /* create batchs and shading groups */
+ DRW_gpencil_create_batches(cache);
+ DRW_gpencil_shgroups_create(e_data, vedata, ob, gpd, cache, cache_ob);
+
cache->is_dirty = false;
}
+
+void DRW_gpencil_populate_particles(GPENCIL_e_data *e_data, void *vedata)
+{
+ GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+
+ /* add particles */
+ for (int i = 0; i < stl->g_data->gp_cache_used; i++) {
+ tGPencilObjectCache *cache_ob = &stl->g_data->gp_object_cache[i];
+ Object *ob = cache_ob->ob;
+ if (cache_ob->is_dup_ob) {
+ bGPdata *gpd = (bGPdata *)ob->data;
+ GpencilBatchCache *cache = ob->runtime.gpencil_cache;
+ DRW_gpencil_shgroups_create(e_data, vedata, ob, gpd, cache, cache_ob);
+ }
+ }
+}
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index 52cd79e4394..7be06d501f1 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -315,9 +315,6 @@ void GPENCIL_cache_init(void *vedata)
if (!stl->shgroups) {
/* Alloc maximum size because count strokes is very slow and can be very complex due onion skinning.
- I tried to allocate only one block and using realloc, increasing the size when read a new strokes
- in cache_finish, but the realloc produce weird things on screen, so we keep as is while we found
- a better solution
*/
stl->shgroups = MEM_mallocN(sizeof(GPENCIL_shgroup) * GPENCIL_MAX_SHGROUPS, "GPENCIL_shgroup");
}
@@ -498,28 +495,22 @@ void GPENCIL_cache_init(void *vedata)
static void gpencil_add_draw_data(void *vedata, Object *ob)
{
GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- const DRWContextState *draw_ctx = DRW_context_state_get();
- Scene *scene = draw_ctx->scene;
bGPdata *gpd = (bGPdata *)ob->data;
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
int i = stl->g_data->gp_cache_used - 1;
tGPencilObjectCache *cache_ob = &stl->g_data->gp_object_cache[i];
- /* save init shading group */
- cache_ob->init_grp = stl->storage->shgroup_id;
-
- /* fill shading groups */
- if ((!is_multiedit) || (cache_ob->is_dup_ob)) {
- DRW_gpencil_populate_datablock(&e_data, vedata, scene, ob, cache_ob);
- }
- else {
- DRW_gpencil_populate_multiedit(&e_data, vedata, scene, ob, cache_ob);
+ if (!cache_ob->is_dup_ob) {
+ /* fill shading groups */
+ if (!is_multiedit) {
+ DRW_gpencil_populate_datablock(&e_data, vedata, ob, cache_ob);
+ }
+ else {
+ DRW_gpencil_populate_multiedit(&e_data, vedata, ob, cache_ob);
+ }
}
- /* save end shading group */
- cache_ob->end_grp = stl->storage->shgroup_id - 1;
-
/* FX passses */
cache_ob->has_fx = false;
if ((!stl->storage->simplify_fx) &&
@@ -549,25 +540,12 @@ void GPENCIL_cache_populate(void *vedata, Object *ob)
if (ob->type == OB_GPENCIL && ob->data) {
bGPdata *gpd = (bGPdata *)ob->data;
- /* if onion, set as dirty always
- * This reduces performance, but avoid any crash in the multiple
- * overlay and multiwindow options
- */
- if (gpd->flag & GP_DATA_SHOW_ONIONSKINS) {
- gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
- }
-
/* when start/stop animation the cache must be set as dirty to reset all data */
if (stl->storage->reset_cache) {
gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
stl->storage->reset_cache = false;
}
- /* is edit mode only current object, not particle instances */
- if ((ob->base_flag & BASE_FROMDUPLI) && GPENCIL_ANY_EDIT_MODE(gpd)) {
- return;
- }
-
if ((stl->g_data->session_flag & GP_DRW_PAINT_READY) == 0) {
/* save gp objects for drawing later */
@@ -618,10 +596,9 @@ void GPENCIL_cache_populate(void *vedata, Object *ob)
}
}
-void GPENCIL_cache_finish(void *UNUSED(vedata))
+void GPENCIL_cache_finish(void *vedata)
{
- return;
-
+ DRW_gpencil_populate_particles(&e_data, vedata);
}
/* helper function to sort inverse gpencil objects using qsort */
@@ -657,6 +634,13 @@ static void gpencil_prepare_fast_drawing(
static void gpencil_free_obj_runtime(GPENCIL_StorageList *stl)
{
+ /* reset all cache flags */
+ for (int i = 0; i < stl->g_data->gp_cache_used; i++) {
+ tGPencilObjectCache *cache_ob = &stl->g_data->gp_object_cache[i];
+ bGPdata *gpd = cache_ob->gpd;
+ gpd->flag &= ~GP_DATA_CACHE_IS_DIRTY;
+ }
+
/* free the cache itself */
MEM_SAFE_FREE(stl->g_data->gp_object_cache);
}
@@ -672,7 +656,6 @@ void GPENCIL_draw_scene(void *ved)
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
GPENCIL_TextureList *txl = ((GPENCIL_Data *)vedata)->txl;
- int init_grp, end_grp;
tGPencilObjectCache *cache_ob;
const float clearcol[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
@@ -729,33 +712,27 @@ void GPENCIL_draw_scene(void *ved)
for (int i = 0; i < stl->g_data->gp_cache_used; i++) {
cache_ob = &stl->g_data->gp_object_cache[i];
bGPdata *gpd = cache_ob->gpd;
- init_grp = cache_ob->init_grp;
- end_grp = cache_ob->end_grp;
/* Render stroke in separated framebuffer */
GPU_framebuffer_bind(fbl->temp_fb_a);
GPU_framebuffer_clear_color_depth(fbl->temp_fb_a, clearcol, 1.0f);
- /* Stroke Pass: DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | DRW_STATE_WRITE_DEPTH
- * draw only a subset that usually start with a fill and end with stroke because the
- * shading groups are created by pairs */
- if (end_grp >= init_grp) {
+ /* Stroke Pass:
+ * draw only a subset that usually starts with a fill and ends with stroke
+ */
+ if (cache_ob->init_grp) {
/* previews don't use AA */
if (!stl->storage->is_mat_preview) {
MULTISAMPLE_GP_SYNC_ENABLE(stl->storage->multisamples, fbl);
}
DRW_draw_pass_subset(
- psl->stroke_pass,
- stl->shgroups[init_grp].shgrps_fill != NULL ?
- stl->shgroups[init_grp].shgrps_fill : stl->shgroups[init_grp].shgrps_stroke,
- stl->shgroups[end_grp].shgrps_stroke);
+ psl->stroke_pass, cache_ob->init_grp, cache_ob->end_grp);
if (!stl->storage->is_mat_preview) {
MULTISAMPLE_GP_SYNC_DISABLE(stl->storage->multisamples, fbl, fbl->temp_fb_a, txl);
}
}
-
/* Current buffer drawing */
if ((!is_render) && (cache_ob->is_dup_ob == false)) {
DRW_draw_pass(psl->drawing_pass);
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h
index 8e68fdef952..0fe25ba9f0f 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.h
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.h
@@ -40,7 +40,10 @@ struct RenderLayer;
#define GPENCIL_CACHE_BLOCK_SIZE 8
#define GPENCIL_MAX_SHGROUPS 65536
-#define GPENCIL_MIN_BATCH_SLOTS_CHUNK 16
+#define GPENCIL_GROUPS_BLOCK_SIZE 1024
+
+/* used to expand VBOs. Size has a big impact in the speed */
+#define GPENCIL_VBO_BLOCK_SIZE 128
#define GPENCIL_COLOR_SOLID 0
#define GPENCIL_COLOR_TEXTURE 1
@@ -60,7 +63,8 @@ struct RenderLayer;
typedef struct tGPencilObjectCache {
struct Object *ob;
struct bGPdata *gpd;
- int init_grp, end_grp;
+ DRWShadingGroup *init_grp;
+ DRWShadingGroup *end_grp;
int idx; /*original index, can change after sort */
/* effects */
@@ -82,8 +86,10 @@ typedef struct tGPencilObjectCache {
float obmat[4][4];
float zdepth; /* z-depth value to sort gp object */
bool is_dup_ob; /* flag to tag duplicate objects */
- bool is_dup_data; /* other object uses datablock already */
- int data_idx; /* derived data index */
+
+ /* GPU data size */
+ int tot_vertex;
+ int tot_triangles;
} tGPencilObjectCache;
/* *********** LISTS *********** */
@@ -98,8 +104,6 @@ typedef struct GPENCIL_shgroup {
int fill_style;
int keep_size;
float obj_scale;
- struct DRWShadingGroup *shgrps_fill;
- struct DRWShadingGroup *shgrps_stroke;
} GPENCIL_shgroup;
typedef struct GPENCIL_Storage {
@@ -276,24 +280,57 @@ typedef struct GPENCIL_e_data {
} GPENCIL_e_data; /* Engine data */
/* GPUBatch Cache */
+typedef struct GpencilBatchCacheElem {
+ GPUBatch *batch;
+ GPUVertBuf *vbo;
+ int vbo_len;
+ /* attr ids */
+ GPUVertFormat format;
+ uint pos_id;
+ uint color_id;
+ uint thickness_id;
+ uint uvdata_id;
+
+ /* size for VBO alloc */
+ int tot_vertex;
+} GpencilBatchCacheElem;
+
+typedef struct GpencilBatchGroup {
+ bGPDlayer *gpl; /* reference to original layer */
+ bGPDframe *gpf; /* reference to original frame */
+ bGPDstroke *gps; /* reference to original stroke */
+ short type; /* type of element */
+ bool onion; /* the group is part of onion skin */
+ int vertex_idx; /* index of vertex data */
+} GpencilBatchGroup;
+
+typedef enum GpencilBatchGroup_Type {
+ eGpencilBatchGroupType_Stroke = 1,
+ eGpencilBatchGroupType_Point = 2,
+ eGpencilBatchGroupType_Fill = 3,
+ eGpencilBatchGroupType_Edit = 4,
+ eGpencilBatchGroupType_Edlin = 5,
+} GpencilBatchGroup_Type;
+
typedef struct GpencilBatchCache {
- /* For normal strokes, a variable number of batch can be needed depending of number of strokes.
- It could use the stroke number as total size, but when activate the onion skining, the number
- can change, so the size is changed dynamically.
- */
- GPUBatch **batch_stroke;
- GPUBatch **batch_fill;
- GPUBatch **batch_edit;
- GPUBatch **batch_edlin;
+ GpencilBatchCacheElem b_stroke;
+ GpencilBatchCacheElem b_point;
+ GpencilBatchCacheElem b_fill;
+ GpencilBatchCacheElem b_edit;
+ GpencilBatchCacheElem b_edlin;
/* settings to determine if cache is invalid */
bool is_dirty;
bool is_editmode;
int cache_frame;
- /* keep information about the size of the cache */
- int cache_size; /* total batch slots available */
- int cache_idx; /* current slot index */
+ /* data with the shading groups */
+ int grp_used; /* total groups in arrays */
+ int grp_size; /* max size of the array */
+ struct GpencilBatchGroup *grp_cache; /* array of elements */
+
+ int tot_layers;
+ struct bGPDframe *derived_array; /* runtime data created by modifiers */
} GpencilBatchCache;
/* general drawing functions */
@@ -302,23 +339,24 @@ struct DRWShadingGroup *DRW_gpencil_shgroup_stroke_create(
struct Object *ob, struct bGPdata *gpd, struct MaterialGPencilStyle *gp_style, int id, bool onion);
void DRW_gpencil_populate_datablock(
struct GPENCIL_e_data *e_data, void *vedata,
- struct Scene *scene,
struct Object *ob, struct tGPencilObjectCache *cache_ob);
void DRW_gpencil_populate_buffer_strokes(
struct GPENCIL_e_data *e_data, void *vedata, struct ToolSettings *ts, struct Object *ob);
void DRW_gpencil_populate_multiedit(
struct GPENCIL_e_data *e_data, void *vedata,
- struct Scene *scene, struct Object *ob, struct tGPencilObjectCache *cache_ob);
+ struct Object *ob, struct tGPencilObjectCache *cache_ob);
void DRW_gpencil_triangulate_stroke_fill(struct Object *ob, struct bGPDstroke *gps);
+void DRW_gpencil_populate_particles(struct GPENCIL_e_data *e_data, void *vedata);
void DRW_gpencil_multisample_ensure(struct GPENCIL_Data *vedata, int rect_w, int rect_h);
/* create geometry functions */
-struct GPUBatch *DRW_gpencil_get_point_geom(struct bGPDstroke *gps, short thickness, const float ink[4]);
-struct GPUBatch *DRW_gpencil_get_stroke_geom(struct bGPDstroke *gps, short thickness, const float ink[4]);
-struct GPUBatch *DRW_gpencil_get_fill_geom(struct Object *ob, struct bGPDstroke *gps, const float color[4]);
-struct GPUBatch *DRW_gpencil_get_edit_geom(struct bGPDstroke *gps, float alpha, short dflag);
-struct GPUBatch *DRW_gpencil_get_edlin_geom(struct bGPDstroke *gps, float alpha, short dflag);
+void DRW_gpencil_get_point_geom(struct GpencilBatchCacheElem *be, struct bGPDstroke *gps, short thickness, const float ink[4]);
+void DRW_gpencil_get_stroke_geom(struct GpencilBatchCacheElem *be, struct bGPDstroke *gps, short thickness, const float ink[4]);
+void DRW_gpencil_get_fill_geom(struct GpencilBatchCacheElem *be, struct Object *ob, struct bGPDstroke *gps, const float color[4]);
+void DRW_gpencil_get_edit_geom(struct GpencilBatchCacheElem *be, struct bGPDstroke *gps, float alpha, short dflag);
+void DRW_gpencil_get_edlin_geom(struct GpencilBatchCacheElem *be, struct bGPDstroke *gps, float alpha, short dflag);
+
struct GPUBatch *DRW_gpencil_get_buffer_stroke_geom(struct bGPdata *gpd, short thickness);
struct GPUBatch *DRW_gpencil_get_buffer_fill_geom(struct bGPdata *gpd);
struct GPUBatch *DRW_gpencil_get_buffer_point_geom(struct bGPdata *gpd, short thickness);
@@ -329,8 +367,15 @@ struct tGPencilObjectCache *gpencil_object_cache_add(
struct tGPencilObjectCache *cache_array, struct Object *ob,
int *gp_cache_size, int *gp_cache_used);
+/* shading groups cache functions */
+struct GpencilBatchGroup *gpencil_group_cache_add(
+ struct GpencilBatchGroup *cache_array,
+ struct bGPDlayer *gpl, struct bGPDframe *gpf, struct bGPDstroke *gps,
+ const short type, const bool onion,
+ const int vertex_idx,
+ int *grp_size, int *grp_used);
+
/* geometry batch cache functions */
-void gpencil_batch_cache_check_free_slots(struct Object *ob);
struct GpencilBatchCache *gpencil_batch_cache_get(struct Object *ob, int cfra);
/* effects */
diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c
index 20100354070..b7568ce20dd 100644
--- a/source/blender/editors/gpencil/gpencil_data.c
+++ b/source/blender/editors/gpencil/gpencil_data.c
@@ -479,8 +479,6 @@ static int gp_layer_duplicate_object_exec(bContext *C, wmOperator *op)
/* make copy of layer */
bGPDlayer *gpl_dst = MEM_dupallocN(gpl_src);
gpl_dst->prev = gpl_dst->next = NULL;
- gpl_dst->runtime.derived_array = NULL;
- gpl_dst->runtime.len_derived = 0;
BLI_addtail(&gpd_dst->layers, gpl_dst);
BLI_uniquename(&gpd_dst->layers, gpl_dst, DATA_("GP_Layer"), '.', offsetof(bGPDlayer, info), sizeof(gpl_dst->info));
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index db4ff053537..5078d071dd8 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -1844,7 +1844,9 @@ void ED_gpencil_calc_stroke_uv(Object *ob, bGPDstroke *gps)
float factor;
/* if image, use texture width */
- if ((gp_style) && (gp_style->sima)) {
+ if ((gp_style) && (gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) &&
+ (gp_style->sima))
+ {
factor = gp_style->sima->gen_x;
}
else if (totlen == 0) {
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c
index 69a48a2c93b..55728ca581f 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c
@@ -203,4 +203,5 @@ GpencilModifierTypeInfo modifierType_Gpencil_Armature = {
/* foreachObjectLink */ foreachObjectLink,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
+ /* getDuplicationFactor */ NULL,
};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c
index 0d0ce7476b9..553d9087c3f 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c
@@ -315,6 +315,13 @@ static void foreachObjectLink(
walk(userData, ob, &mmd->object, IDWALK_CB_NOP);
}
+static int getDuplicationFactor(GpencilModifierData *md)
+{
+ ArrayGpencilModifierData *mmd = (ArrayGpencilModifierData *)md;
+ int t = mmd->count;
+ CLAMP_MIN(t, 1);
+ return t;
+}
GpencilModifierTypeInfo modifierType_Gpencil_Array = {
/* name */ "Array",
@@ -338,4 +345,5 @@ GpencilModifierTypeInfo modifierType_Gpencil_Array = {
/* foreachObjectLink */ foreachObjectLink,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
+ /* getDuplicationFactor */ getDuplicationFactor,
};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
index e2a257fcb43..ba814c8538a 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
@@ -553,4 +553,5 @@ GpencilModifierTypeInfo modifierType_Gpencil_Build = {
/* foreachObjectLink */ NULL,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
+ /* getDuplicationFactor */ NULL,
};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c
index 4c1418fe0e3..94c5e9ddbdf 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c
@@ -164,4 +164,5 @@ GpencilModifierTypeInfo modifierType_Gpencil_Color = {
/* foreachObjectLink */ NULL,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
+ /* getDuplicationFactor */ NULL,
};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c
index 1ec6103939a..97f260f307f 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c
@@ -353,4 +353,5 @@ GpencilModifierTypeInfo modifierType_Gpencil_Hook = {
/* foreachObjectLink */ foreachObjectLink,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
+ /* getDuplicationFactor */ NULL,
};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c b/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c
index d9ec81b70b9..1d8f2c20b59 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c
@@ -211,4 +211,5 @@ GpencilModifierTypeInfo modifierType_Gpencil_Lattice = {
/* foreachObjectLink */ foreachObjectLink,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
+ /* getDuplicationFactor */ NULL,
};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c
index 9c3d3dc9235..7599e7e9bce 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c
@@ -189,6 +189,21 @@ static void foreachObjectLink(
walk(userData, ob, &mmd->object, IDWALK_CB_NOP);
}
+static int getDuplicationFactor(GpencilModifierData *md)
+{
+ MirrorGpencilModifierData *mmd = (MirrorGpencilModifierData *)md;
+ int factor = 1;
+ /* create a duplication for each axis */
+ for (int xi = 0; xi < 3; ++xi) {
+ if (mmd->flag & (GP_MIRROR_AXIS_X << xi)) {
+ factor++;
+ }
+ }
+ CLAMP_MIN(factor, 1);
+
+ return factor;
+}
+
GpencilModifierTypeInfo modifierType_Gpencil_Mirror = {
/* name */ "Mirror",
/* structName */ "MirrorGpencilModifierData",
@@ -211,4 +226,5 @@ GpencilModifierTypeInfo modifierType_Gpencil_Mirror = {
/* foreachObjectLink */ foreachObjectLink,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
+ /* getDuplicationFactor */ getDuplicationFactor,
};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c
index 399ff27eafb..097b5702721 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c
@@ -285,4 +285,5 @@ GpencilModifierTypeInfo modifierType_Gpencil_Noise = {
/* foreachObjectLink */ NULL,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
+ /* getDuplicationFactor */ NULL,
};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c
index 43af4b94c15..2c2a5c2f994 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c
@@ -143,4 +143,5 @@ GpencilModifierTypeInfo modifierType_Gpencil_Offset = {
/* foreachObjectLink */ NULL,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
+ /* getDuplicationFactor */ NULL,
};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c
index b89c3792455..7033b246e1c 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c
@@ -183,4 +183,5 @@ GpencilModifierTypeInfo modifierType_Gpencil_Opacity = {
/* foreachObjectLink */ NULL,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
+ /* getDuplicationFactor */ NULL,
};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c
index 2d0b90e6de7..6ddf40df6c0 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c
@@ -123,4 +123,5 @@ GpencilModifierTypeInfo modifierType_Gpencil_Simplify = {
/* foreachObjectLink */ NULL,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
+ /* getDuplicationFactor */ NULL,
};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c
index 8d93980a9d0..ece7ebc9816 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c
@@ -150,4 +150,5 @@ GpencilModifierTypeInfo modifierType_Gpencil_Smooth = {
/* foreachObjectLink */ NULL,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
+ /* getDuplicationFactor */ NULL,
};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c
index 38aa4159632..71881de50fc 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c
@@ -97,6 +97,14 @@ static void bakeModifier(
}
}
+static int getDuplicationFactor(GpencilModifierData *md)
+{
+ SubdivGpencilModifierData *mmd = (SubdivGpencilModifierData *)md;
+ int t = (mmd->level + 1) * (mmd->level + 1);
+ CLAMP_MIN(t, 2);
+ return t;
+}
+
GpencilModifierTypeInfo modifierType_Gpencil_Subdiv = {
/* name */ "Subdivision",
/* structName */ "SubdivGpencilModifierData",
@@ -119,4 +127,5 @@ GpencilModifierTypeInfo modifierType_Gpencil_Subdiv = {
/* foreachObjectLink */ NULL,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
+ /* getDuplicationFactor */ getDuplicationFactor,
};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c
index 8046545ef71..441cab909d3 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c
@@ -171,4 +171,5 @@ GpencilModifierTypeInfo modifierType_Gpencil_Thick = {
/* foreachObjectLink */ NULL,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
+ /* getDuplicationFactor */ NULL,
};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciltime.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciltime.c
index e220d5a5e85..d90dea91af9 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpenciltime.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciltime.c
@@ -187,4 +187,5 @@ GpencilModifierTypeInfo modifierType_Gpencil_Time = {
/* foreachObjectLink */ NULL,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
+ /* getDuplicationFactor */ NULL,
};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c
index ba3b2d84861..385296c943e 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c
@@ -172,4 +172,5 @@ GpencilModifierTypeInfo modifierType_Gpencil_Tint = {
/* foreachObjectLink */ NULL,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
+ /* getDuplicationFactor */ NULL,
};
diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h
index 503ad2f28d9..8a1bccc6957 100644
--- a/source/blender/makesdna/DNA_gpencil_types.h
+++ b/source/blender/makesdna/DNA_gpencil_types.h
@@ -236,10 +236,7 @@ typedef enum eGPDframe_Flag {
/* Runtime temp data for bGPDlayer */
typedef struct bGPDlayer_Runtime {
- struct bGPDframe *derived_array;/* runtime data created by modifiers */
int icon_id; /* id for dynamic icon used to show annotation color preview for layer */
- int batch_index; /* batch used for dupli instances */
- int len_derived; /* len of the derived array */
char pad_[4];
} bGPDlayer_Runtime;