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:
Diffstat (limited to 'source/blender/draw/engines/gpencil/gpencil_draw_utils.c')
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_draw_utils.c950
1 files changed, 566 insertions, 384 deletions
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);
+ }
+ }
+}