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
diff options
context:
space:
mode:
-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;