Fix T66924 : Move GPencil Modifiers evaluation to Depsgraph

Before, the evaluation of modifers were done in draw manager. The reason of the old design was grease pencil was designed before depsgraph was in place.

This commit moves this logic to depsgraph to follow general design and reduce Draw Manager complexity. Also, this is required in order to use modifiers in Edit modes.

Really, there is nothing really new in the creation of derived data, only the logic has been moved to depsgraph, but the main logic is the same. In order to get a reference to the original stroke and points, a pointer is added to Runtime data as part of the evaluated data. These pointers allow to know and use the original data.

As the modifiers now are evaluated in Depsgraph, the evaluated stroke is usable in Edit modes, so now it's possible to work with the evaluated version instead to use a "ghost" of the final image over the original geometry as work today.

Reviewed By: brecht

Differential Revision: https://developer.blender.org/D5470
This commit is contained in:
Antonio Vazquez 2019-08-23 23:10:41 +02:00
parent d795dd1fa7
commit ee4ec69b28
Notes: blender-bot 2023-03-24 17:05:22 +01:00
Referenced by issue blender/blender-addons#66924, bpy.ops.preferences.addon_enable() only checks for changes in __init__.py; Problem for multi-file add-ons
13 changed files with 300 additions and 220 deletions

View File

@ -24,6 +24,7 @@
* \ingroup bke
*/
struct Scene;
struct ArrayGpencilModifierData;
struct BoundBox;
struct Brush;
@ -49,6 +50,23 @@ struct bGPdata;
struct MDeformVert;
struct MDeformWeight;
#define GPENCIL_SIMPLIFY(scene) ((scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ENABLE))
#define GPENCIL_SIMPLIFY_ONPLAY(playing) \
(((playing == true) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ON_PLAY)) || \
((scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ON_PLAY) == 0))
#define GPENCIL_SIMPLIFY_FILL(scene, playing) \
((GPENCIL_SIMPLIFY_ONPLAY(playing) && (GPENCIL_SIMPLIFY(scene)) && \
(scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_FILL)))
#define GPENCIL_SIMPLIFY_MODIF(scene, playing) \
((GPENCIL_SIMPLIFY_ONPLAY(playing) && (GPENCIL_SIMPLIFY(scene)) && \
(scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_MODIFIER)))
#define GPENCIL_SIMPLIFY_FX(scene, playing) \
((GPENCIL_SIMPLIFY_ONPLAY(playing) && (GPENCIL_SIMPLIFY(scene)) && \
(scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_FX)))
#define GPENCIL_SIMPLIFY_BLEND(scene, playing) \
((GPENCIL_SIMPLIFY_ONPLAY(playing) && (GPENCIL_SIMPLIFY(scene)) && \
(scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_BLEND)))
/* ------------ Grease-Pencil API ------------------ */
void BKE_gpencil_free_point_weights(struct MDeformVert *dvert);
@ -57,7 +75,7 @@ void BKE_gpencil_free_stroke(struct bGPDstroke *gps);
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);
bool BKE_gpencil_free_frame_runtime_data(struct bGPDframe *eval_gpf);
void BKE_gpencil_free(struct bGPdata *gpd, bool free_all);
void BKE_gpencil_batch_cache_dirty_tag(struct bGPdata *gpd);

View File

@ -27,7 +27,6 @@
struct BMEditMesh;
struct DepsNodeHandle;
struct Depsgraph;
struct DerivedMesh;
struct GpencilModifierData;
struct ID;
struct ListBase;
@ -328,4 +327,8 @@ int BKE_gpencil_time_modifier(struct Depsgraph *depsgraph,
void BKE_gpencil_lattice_init(struct Object *ob);
void BKE_gpencil_lattice_clear(struct Object *ob);
void BKE_gpencil_modifiers_calc(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob);
#endif /* __BKE_GPENCIL_MODIFIER_H__ */

View File

@ -148,19 +148,19 @@ bool BKE_gpencil_free_strokes(bGPDframe *gpf)
}
/* Free strokes and colors belonging to a gp-frame */
bool BKE_gpencil_free_frame_runtime_data(bGPDframe *derived_gpf)
bool BKE_gpencil_free_frame_runtime_data(bGPDframe *eval_gpf)
{
bGPDstroke *gps_next;
if (!derived_gpf) {
if (!eval_gpf) {
return false;
}
/* free strokes */
for (bGPDstroke *gps = derived_gpf->strokes.first; gps; gps = gps_next) {
for (bGPDstroke *gps = eval_gpf->strokes.first; gps; gps = gps_next) {
gps_next = gps->next;
BKE_gpencil_free_stroke(gps);
}
BLI_listbase_clear(&derived_gpf->strokes);
BLI_listbase_clear(&eval_gpf->strokes);
return true;
}

View File

@ -43,6 +43,7 @@
#include "BKE_library_query.h"
#include "BKE_gpencil.h"
#include "BKE_lattice.h"
#include "BKE_material.h"
#include "BKE_gpencil_modifier.h"
#include "BKE_object.h"
@ -446,14 +447,6 @@ void BKE_gpencil_eval_geometry(Depsgraph *depsgraph, bGPdata *gpd)
gpl->actframe = BKE_gpencil_layer_getframe(gpl, ctime, GP_GETFRAME_USE_PREV);
}
/* TODO: Move "derived_gpf" logic here from DRW_gpencil_populate_datablock()?
* This would be better than inventing our own logic for this stuff...
*/
/* TODO: Move the following code to "BKE_gpencil_eval_done()" (marked as an exit node)
* later when there's more happening here. For now, let's just keep this in here to avoid
* needing to have one more node slowing down evaluation...
*/
if (DEG_is_active(depsgraph)) {
bGPdata *gpd_orig = (bGPdata *)DEG_get_original_id(&gpd->id);
@ -714,6 +707,8 @@ void BKE_gpencil_subdivide(bGPDstroke *gps, int level, int flag)
pt_final->strength = pt->strength;
pt_final->time = pt->time;
pt_final->flag = pt->flag;
pt_final->runtime.pt_orig = pt->runtime.pt_orig;
pt_final->runtime.idx_orig = pt->runtime.idx_orig;
if (gps->dvert != NULL) {
dvert = &temp_dverts[i];
@ -736,6 +731,7 @@ void BKE_gpencil_subdivide(bGPDstroke *gps, int level, int flag)
pt_final->strength = interpf(pt->strength, next->strength, 0.5f);
CLAMP(pt_final->strength, GPENCIL_STRENGTH_MIN, 1.0f);
pt_final->time = interpf(pt->time, next->time, 0.5f);
pt_final->runtime.pt_orig = NULL;
if (gps->dvert != NULL) {
dvert = &temp_dverts[i];
@ -781,3 +777,132 @@ void BKE_gpencil_subdivide(bGPDstroke *gps, int level, int flag)
}
}
}
/* Copy frame but do not assign new memory */
static void gpencil_frame_copy_noalloc(Object *ob, bGPDframe *gpf, bGPDframe *eval_gpf)
{
eval_gpf->prev = gpf->prev;
eval_gpf->next = gpf->next;
eval_gpf->framenum = gpf->framenum;
eval_gpf->flag = gpf->flag;
eval_gpf->key_type = gpf->key_type;
eval_gpf->runtime = gpf->runtime;
copy_m4_m4(eval_gpf->runtime.parent_obmat, gpf->runtime.parent_obmat);
/* copy strokes */
BLI_listbase_clear(&eval_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);
/* copy color to temp fields to apply temporal changes in the stroke */
MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps_src->mat_nr + 1);
copy_v4_v4(gps_dst->runtime.tmp_stroke_rgba, gp_style->stroke_rgba);
copy_v4_v4(gps_dst->runtime.tmp_fill_rgba, gp_style->fill_rgba);
/* Save original pointers for using in edit and select operators. */
gps_dst->runtime.gps_orig = gps_src;
for (int i = 0; i < gps_src->totpoints; i++) {
bGPDspoint *pt_dst = &gps_dst->points[i];
pt_dst->runtime.pt_orig = &gps_src->points[i];
pt_dst->runtime.idx_orig = i;
}
BLI_addtail(&eval_gpf->strokes, gps_dst);
}
}
/* Ensure there is a evaluated frame */
static void gpencil_evaluated_frame_ensure(
int idx, Object *ob, bGPDlayer *gpl, bGPDframe *gpf, bGPDframe **eval_gpf)
{
/* Create evaluated frames array data or expand. */
bGPDframe *evaluated_frames = ob->runtime.gpencil_evaluated_frames;
*eval_gpf = &evaluated_frames[idx];
/* If already exist a evaluated frame create a new one. */
if (*eval_gpf != NULL) {
/* first clear temp data */
BKE_gpencil_free_frame_runtime_data(*eval_gpf);
}
/* Copy data (do not assign new memory). */
gpencil_frame_copy_noalloc(ob, gpf, *eval_gpf);
}
/* Calculate gpencil modifiers */
void BKE_gpencil_modifiers_calc(Depsgraph *depsgraph, Scene *scene, Object *ob)
{
/* use original data to set reference pointers to original data */
Object *ob_orig = DEG_get_original_object(ob);
bGPdata *gpd = (bGPdata *)ob_orig->data;
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
const bool simplify_modif = GPENCIL_SIMPLIFY_MODIF(scene, false);
const bool is_render = (bool)(DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
const bool time_remap = BKE_gpencil_has_time_modifiers(ob);
int cfra_eval = (int)DEG_get_ctime(depsgraph);
/* Create array of evaluated frames equal to number of layers. */
ob->runtime.gpencil_tot_layers = BLI_listbase_count(&gpd->layers);
CLAMP_MIN(ob->runtime.gpencil_tot_layers, 1);
if (ob->runtime.gpencil_evaluated_frames == NULL) {
ob->runtime.gpencil_evaluated_frames = MEM_callocN(
sizeof(struct bGPDframe) * ob->runtime.gpencil_tot_layers, __func__);
}
else {
ob->runtime.gpencil_evaluated_frames = MEM_recallocN(ob->runtime.gpencil_evaluated_frames,
sizeof(struct bGPDframe) *
ob->runtime.gpencil_tot_layers);
}
/* Init general modifiers data. */
if (ob->greasepencil_modifiers.first) {
BKE_gpencil_lattice_init(ob);
}
/* *****************************************************************
* Loop all layers, duplicate data and apply modifiers.
*
* ******************************************************************/
int idx = 0;
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
/* Remap frame (Time modifier) */
int remap_cfra = cfra_eval;
if ((time_remap) && (!simplify_modif)) {
remap_cfra = BKE_gpencil_time_modifier(depsgraph, scene, ob, gpl, cfra_eval, is_render);
}
bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, remap_cfra, GP_GETFRAME_USE_PREV);
if (gpf == NULL) {
idx++;
continue;
}
/* Create a duplicate data set of stroke to modify. */
bGPDframe *eval_gpf = NULL;
gpencil_evaluated_frame_ensure(idx, ob, gpl, gpf, &eval_gpf);
/* Skip all if some disable flag is enabled. */
if ((ob->greasepencil_modifiers.first == NULL) || (is_multiedit) || (simplify_modif)) {
idx++;
continue;
}
/* Apply geometry modifiers (create new geometry). */
if (BKE_gpencil_has_geometry_modifiers(ob)) {
BKE_gpencil_geometry_modifiers(depsgraph, ob, gpl, eval_gpf, is_render);
}
/* Loop all strokes and deform them. */
for (bGPDstroke *gps = eval_gpf->strokes.first; gps; gps = gps->next) {
/* Apply modifiers that only deform geometry */
BKE_gpencil_stroke_modifiers(depsgraph, ob, gpl, eval_gpf, gps, is_render);
}
idx++;
}
/* Clear any lattice data. */
if (ob->greasepencil_modifiers.first) {
BKE_gpencil_lattice_clear(ob);
}
}

View File

@ -43,6 +43,7 @@
#include "BKE_displist.h"
#include "BKE_editmesh.h"
#include "BKE_effect.h"
#include "BKE_gpencil_modifier.h"
#include "BKE_image.h"
#include "BKE_key.h"
#include "BKE_layer.h"
@ -215,6 +216,9 @@ void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *o
case OB_LATTICE:
BKE_lattice_modifiers_calc(depsgraph, scene, ob);
break;
case OB_GPENCIL:
BKE_gpencil_modifiers_calc(depsgraph, scene, ob);
break;
}
/* particles */

View File

@ -274,11 +274,6 @@ static GpencilBatchCache *gpencil_batch_cache_init(Object *ob, int cfra)
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;
}
@ -301,18 +296,16 @@ static void gpencil_batch_cache_clear(GpencilBatchCache *cache)
MEM_SAFE_FREE(cache->b_edit.batch);
MEM_SAFE_FREE(cache->b_edlin.batch);
/* internal format data */
MEM_SAFE_FREE(cache->b_stroke.format);
MEM_SAFE_FREE(cache->b_point.format);
MEM_SAFE_FREE(cache->b_fill.format);
MEM_SAFE_FREE(cache->b_edit.format);
MEM_SAFE_FREE(cache->b_edlin.format);
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->tot_layers = 0;
MEM_SAFE_FREE(cache->derived_array);
}
/* get cache */
@ -355,4 +348,14 @@ void DRW_gpencil_freecache(struct Object *ob)
gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
}
}
/* clear all frames evaluated data */
for (int i = 0; i < ob->runtime.gpencil_tot_layers; i++) {
bGPDframe *eval_gpf = &ob->runtime.gpencil_evaluated_frames[i];
BKE_gpencil_free_frame_runtime_data(eval_gpf);
eval_gpf = NULL;
}
ob->runtime.gpencil_tot_layers = 0;
MEM_SAFE_FREE(ob->runtime.gpencil_evaluated_frames);
}

View File

@ -129,6 +129,13 @@ static void gpencil_vbo_ensure_size(GpencilBatchCacheElem *be, int totvertex)
}
}
static void gpencil_elem_format_ensure(GpencilBatchCacheElem *be)
{
if (be->format == NULL) {
be->format = MEM_callocN(sizeof(GPUVertFormat), __func__);
}
}
/* create batch geometry data for points stroke shader */
void gpencil_get_point_geom(GpencilBatchCacheElem *be,
bGPDstroke *gps,
@ -138,16 +145,17 @@ void gpencil_get_point_geom(GpencilBatchCacheElem *be,
{
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);
gpencil_elem_format_ensure(be);
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->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->format, "uvdata", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
be->prev_pos_id = GPU_vertformat_attr_add(
&be->format, "prev_pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
be->format, "prev_pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
be->vbo = GPU_vertbuf_create_with_format(&be->format);
be->vbo = GPU_vertbuf_create_with_format(be->format);
GPU_vertbuf_data_alloc(be->vbo, be->tot_vertex);
be->vbo_len = 0;
}
@ -223,14 +231,15 @@ void gpencil_get_stroke_geom(struct GpencilBatchCacheElem *be,
int totvertex = totpoints + cyclic_add + 2;
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);
gpencil_elem_format_ensure(be);
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->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->format, "uvdata", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
be->vbo = GPU_vertbuf_create_with_format(&be->format);
be->vbo = GPU_vertbuf_create_with_format(be->format);
GPU_vertbuf_data_alloc(be->vbo, be->tot_vertex);
be->vbo_len = 0;
}
@ -336,12 +345,13 @@ void gpencil_get_fill_geom(struct GpencilBatchCacheElem *be,
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);
gpencil_elem_format_ensure(be);
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->format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
be->vbo = GPU_vertbuf_create_with_format(&be->format);
be->vbo = GPU_vertbuf_create_with_format(be->format);
GPU_vertbuf_data_alloc(be->vbo, be->tot_vertex);
be->vbo_len = 0;
}
@ -703,6 +713,7 @@ void gpencil_get_edit_geom(struct GpencilBatchCacheElem *be,
Object *ob = draw_ctx->obact;
bGPdata *gpd = ob->data;
const bool is_weight_paint = (gpd) && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE);
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
int vgindex = ob->actdef - 1;
if (!BLI_findlink(&ob->defbase, vgindex)) {
@ -733,13 +744,17 @@ void gpencil_get_edit_geom(struct GpencilBatchCacheElem *be,
UI_GetThemeColor3fv(TH_GP_VERTEX, unselectColor);
unselectColor[3] = alpha;
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);
float linecolor[4];
copy_v4_v4(linecolor, gpd->line_color);
be->vbo = GPU_vertbuf_create_with_format(&be->format);
if (be->vbo == NULL) {
gpencil_elem_format_ensure(be);
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);
be->vbo = GPU_vertbuf_create_with_format(be->format);
GPU_vertbuf_data_alloc(be->vbo, be->tot_vertex);
be->vbo_len = 0;
}
@ -776,6 +791,12 @@ void gpencil_get_edit_geom(struct GpencilBatchCacheElem *be,
ARRAY_SET_ITEMS(fcolor, 1.0f, 0.0f, 0.0f, 1.0f);
fsize = vsize + 1;
}
else if ((!is_multiedit) && (pt->runtime.pt_orig == NULL)) {
ARRAY_SET_ITEMS(fcolor, linecolor[0], linecolor[1], linecolor[2], selectColor[3]);
mul_v4_fl(fcolor, 0.9f);
copy_v4_v4(fcolor, fcolor);
fsize = vsize * 0.8f;
}
else if (pt->flag & GP_SPOINT_SELECT) {
copy_v4_v4(fcolor, selectColor);
fsize = vsize;
@ -819,10 +840,11 @@ void gpencil_get_edlin_geom(struct GpencilBatchCacheElem *be,
copy_v4_v4(linecolor, gpd->line_color);
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);
gpencil_elem_format_ensure(be);
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->vbo = GPU_vertbuf_create_with_format(&be->format);
be->vbo = GPU_vertbuf_create_with_format(be->format);
GPU_vertbuf_data_alloc(be->vbo, be->tot_vertex);
be->vbo_len = 0;
}

View File

@ -61,10 +61,6 @@
#define TEXTURE 4
#define PATTERN 5
#define GP_SET_SRC_GPS(src_gps) \
if (src_gps) \
src_gps = src_gps->next
/* Get number of vertex for using in GPU VBOs */
static void gpencil_calc_vertex(GPENCIL_StorageList *stl,
tGPencilObjectCache *cache_ob,
@ -88,16 +84,17 @@ static void gpencil_calc_vertex(GPENCIL_StorageList *stl,
const bool do_onion = (bool)((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0) && overlay &&
main_onion && gpencil_onion_active(gpd) && !playing;
const bool time_remap = BKE_gpencil_has_time_modifiers(ob);
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
cache_ob->tot_vertex = 0;
cache_ob->tot_triangles = 0;
int eval_idx = 0;
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
bGPDframe *init_gpf = NULL;
const bool is_onion = ((do_onion) && (gpl->onion_flag & GP_LAYER_ONIONSKIN));
if (gpl->flag & GP_LAYER_HIDE) {
eval_idx++;
continue;
}
@ -106,15 +103,7 @@ static void gpencil_calc_vertex(GPENCIL_StorageList *stl,
init_gpf = gpl->frames.first;
}
else {
/* 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);
init_gpf = BKE_gpencil_layer_getframe(gpl, remap_cfra, GP_GETFRAME_USE_PREV);
}
else {
init_gpf = gpl->actframe;
}
init_gpf = &ob->runtime.gpencil_evaluated_frames[eval_idx];
}
if (init_gpf == NULL) {
@ -130,6 +119,7 @@ static void gpencil_calc_vertex(GPENCIL_StorageList *stl,
break;
}
}
eval_idx++;
}
cache->b_fill.tot_vertex = cache_ob->tot_triangles * 3;
@ -1009,8 +999,7 @@ static void gpencil_draw_strokes(GpencilBatchCache *cache,
Object *ob,
bGPdata *gpd,
bGPDlayer *gpl,
bGPDframe *src_gpf,
bGPDframe *derived_gpf,
bGPDframe *gpf,
const float opacity,
const float tintcolor[4],
const bool custonion,
@ -1021,7 +1010,7 @@ static void gpencil_draw_strokes(GpencilBatchCache *cache,
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
View3D *v3d = draw_ctx->v3d;
bGPDstroke *gps, *src_gps;
bGPDstroke *gps;
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
const bool playing = stl->storage->is_playing;
const bool is_render = (bool)stl->storage->is_render;
@ -1036,42 +1025,24 @@ static void gpencil_draw_strokes(GpencilBatchCache *cache,
/* get parent matrix and save as static data */
if ((cache_ob != NULL) && (cache_ob->is_dup_ob)) {
copy_m4_m4(derived_gpf->runtime.parent_obmat, cache_ob->obmat);
copy_m4_m4(gpf->runtime.parent_obmat, cache_ob->obmat);
}
else {
ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, derived_gpf->runtime.parent_obmat);
ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, gpf->runtime.parent_obmat);
}
/* apply geometry modifiers */
if ((cache->is_dirty) && (ob->greasepencil_modifiers.first) && (!is_multiedit)) {
if (!stl->storage->simplify_modif) {
if (BKE_gpencil_has_geometry_modifiers(ob)) {
BKE_gpencil_geometry_modifiers(depsgraph, ob, gpl, derived_gpf, stl->storage->is_render);
}
}
}
if (src_gpf) {
src_gps = src_gpf->strokes.first;
}
else {
src_gps = NULL;
}
for (gps = derived_gpf->strokes.first; gps; gps = gps->next) {
for (gps = gpf->strokes.first; gps; gps = gps->next) {
MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
/* check if stroke can be drawn */
if (gpencil_can_draw_stroke(gp_style, gps, false, is_mat_preview) == false) {
GP_SET_SRC_GPS(src_gps);
continue;
}
/* be sure recalc all cache in source stroke to avoid recalculation when frame change
* and improve fps */
if (src_gps) {
gpencil_recalc_geometry_caches(ob, gpl, gp_style, src_gps);
}
gpencil_recalc_geometry_caches(
ob, gpl, gp_style, (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps);
/* if the fill has any value, it's considered a fill and is not drawn if simplify fill is
* enabled */
@ -1080,32 +1051,19 @@ static void gpencil_draw_strokes(GpencilBatchCache *cache,
if ((gp_style->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) ||
(gp_style->fill_style > GP_STYLE_FILL_STYLE_SOLID) ||
(gpl->blend_mode != eGplBlendMode_Regular)) {
GP_SET_SRC_GPS(src_gps);
continue;
}
}
if ((gpl->actframe->framenum == derived_gpf->framenum) || (!is_multiedit) ||
(overlay_multiedit)) {
/* 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);
/* apply modifiers (only modify geometry, but not create ) */
if ((cache->is_dirty) && (ob->greasepencil_modifiers.first) && (!is_multiedit)) {
if (!stl->storage->simplify_modif) {
BKE_gpencil_stroke_modifiers(
depsgraph, ob, gpl, derived_gpf, gps, stl->storage->is_render);
}
}
if ((gpl->actframe->framenum == gpf->framenum) || (!is_multiedit) || (overlay_multiedit)) {
/* hide any blend layer */
if ((!stl->storage->simplify_blend) || (gpl->blend_mode == eGplBlendMode_Regular)) {
/* fill */
if ((gp_style->flag & GP_STYLE_FILL_SHOW) && (!stl->storage->simplify_fill) &&
((gps->flag & GP_STROKE_NOFILL) == 0)) {
gpencil_add_fill_vertexdata(
cache, ob, gpl, derived_gpf, gps, opacity, tintcolor, false, custonion);
cache, ob, gpl, gpf, gps, opacity, tintcolor, false, custonion);
}
/* stroke */
/* No fill strokes, must show stroke always */
@ -1118,14 +1076,13 @@ static void gpencil_draw_strokes(GpencilBatchCache *cache,
}
gpencil_add_stroke_vertexdata(
cache, ob, gpl, derived_gpf, gps, opacity, tintcolor, false, custonion);
cache, ob, gpl, gpf, gps, opacity, tintcolor, false, custonion);
}
}
}
/* edit points (only in edit mode and not play animation not render) */
if ((draw_ctx->obact == ob) && (src_gps) && (!playing) && (!is_render) &&
(!cache_ob->is_dup_ob)) {
if ((draw_ctx->obact == ob) && (!playing) && (!is_render) && (!cache_ob->is_dup_ob)) {
if ((gpl->flag & GP_LAYER_LOCKED) == 0) {
if (!stl->g_data->shgrps_edit_line) {
stl->g_data->shgrps_edit_line = DRW_shgroup_create(e_data->gpencil_line_sh,
@ -1138,11 +1095,9 @@ static void gpencil_draw_strokes(GpencilBatchCache *cache,
DRW_shgroup_uniform_vec2(stl->g_data->shgrps_edit_point, "Viewport", viewport_size, 1);
}
gpencil_add_editpoints_vertexdata(cache, ob, gpd, gpl, derived_gpf, src_gps);
gpencil_add_editpoints_vertexdata(cache, ob, gpd, gpl, gpf, gps);
}
}
GP_SET_SRC_GPS(src_gps);
}
}
@ -1356,25 +1311,6 @@ static void gpencil_draw_onionskins(GpencilBatchCache *cache,
}
}
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.parent_obmat, gpf->runtime.parent_obmat);
/* 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 gpencil_triangulate_stroke_fill(Object *ob, bGPDstroke *gps)
@ -1881,7 +1817,6 @@ void gpencil_populate_multiedit(GPENCIL_e_data *e_data,
gpd,
gpl,
gpf,
gpf,
gpl->opacity,
gpl->tintcolor,
false,
@ -1899,7 +1834,6 @@ void gpencil_populate_multiedit(GPENCIL_e_data *e_data,
gpd,
gpl,
gpf,
gpf,
gpl->opacity,
gpl->tintcolor,
false,
@ -1915,28 +1849,6 @@ void gpencil_populate_multiedit(GPENCIL_e_data *e_data,
cache->is_dirty = false;
}
/* ensure there is a derived frame */
static void gpencil_ensure_derived_frame(bGPdata *gpd,
bGPDlayer *gpl,
bGPDframe *gpf,
GpencilBatchCache *cache,
bGPDframe **derived_gpf)
{
/* 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)) {
if (*derived_gpf != NULL) {
/* first clear temp data */
BKE_gpencil_free_frame_runtime_data(*derived_gpf);
}
/* create new data (do not assign new memory)*/
gpencil_copy_frame(gpf, *derived_gpf);
}
}
/* helper for populate a complete grease pencil datablock */
void gpencil_populate_datablock(GPENCIL_e_data *e_data,
void *vedata,
@ -1948,12 +1860,14 @@ void gpencil_populate_datablock(GPENCIL_e_data *e_data,
const ViewLayer *view_layer = DEG_get_evaluated_view_layer(draw_ctx->depsgraph);
Scene *scene = draw_ctx->scene;
bGPdata *gpd = (bGPdata *)ob->data;
/* Use original data to shared in edit/transform operators */
bGPdata *gpd_eval = (bGPdata *)ob->data;
bGPdata *gpd = (bGPdata *)DEG_get_original_id(&gpd_eval->id);
View3D *v3d = draw_ctx->v3d;
int cfra_eval = (int)DEG_get_ctime(draw_ctx->depsgraph);
bGPDframe *derived_gpf = NULL;
bGPDframe *eval_gpf = NULL;
const bool overlay = v3d != NULL ? (bool)((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) : true;
const bool time_remap = BKE_gpencil_has_time_modifiers(ob);
@ -1975,12 +1889,6 @@ void gpencil_populate_datablock(GPENCIL_e_data *e_data,
/* calc max size of VBOs */
gpencil_calc_vertex(stl, cache_ob, cache, gpd, cfra_eval);
/* init general modifiers data */
if (!stl->storage->simplify_modif) {
if ((cache->is_dirty) && (ob->greasepencil_modifiers.first)) {
BKE_gpencil_lattice_init(ob);
}
}
/* draw normal strokes */
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
/* don't draw layer if hidden */
@ -2028,8 +1936,9 @@ void gpencil_populate_datablock(GPENCIL_e_data *e_data,
opacity = opacity * v3d->overlay.gpencil_fade_layer;
}
/* create derived frames array data or expand */
gpencil_ensure_derived_frame(gpd, gpl, gpf, cache, &derived_gpf);
/* Get evaluated frames array data */
int eval_idx = BLI_findindex(&gpd->layers, gpl);
eval_gpf = &ob->runtime.gpencil_evaluated_frames[eval_idx];
/* draw onion skins */
if (!ID_IS_LINKED(&gpd->id)) {
@ -2043,23 +1952,8 @@ void gpencil_populate_datablock(GPENCIL_e_data *e_data,
}
}
/* draw normal strokes */
gpencil_draw_strokes(cache,
e_data,
vedata,
ob,
gpd,
gpl,
gpf,
derived_gpf,
opacity,
gpl->tintcolor,
false,
cache_ob);
}
/* clear any lattice data */
if ((cache->is_dirty) && (ob->greasepencil_modifiers.first)) {
BKE_gpencil_lattice_clear(ob);
gpencil_draw_strokes(
cache, e_data, vedata, ob, gpd, gpl, eval_gpf, opacity, gpl->tintcolor, false, cache_ob);
}
/* create batchs and shading groups */

View File

@ -405,10 +405,10 @@ void GPENCIL_cache_init(void *vedata)
}
/* save simplify flags (can change while drawing, so it's better to save) */
stl->storage->simplify_fill = GP_SIMPLIFY_FILL(scene, stl->storage->is_playing);
stl->storage->simplify_modif = GP_SIMPLIFY_MODIF(scene, stl->storage->is_playing);
stl->storage->simplify_fx = GP_SIMPLIFY_FX(scene, stl->storage->is_playing);
stl->storage->simplify_blend = GP_SIMPLIFY_BLEND(scene, stl->storage->is_playing);
stl->storage->simplify_fill = GPENCIL_SIMPLIFY_FILL(scene, stl->storage->is_playing);
stl->storage->simplify_modif = GPENCIL_SIMPLIFY_MODIF(scene, stl->storage->is_playing);
stl->storage->simplify_fx = GPENCIL_SIMPLIFY_FX(scene, stl->storage->is_playing);
stl->storage->simplify_blend = GPENCIL_SIMPLIFY_BLEND(scene, stl->storage->is_playing);
/* xray mode */
if (v3d) {

View File

@ -35,6 +35,10 @@ struct RenderLayer;
struct bGPDstroke;
struct tGPspoint;
struct GPUBatch;
struct GPUVertBuf;
struct GPUVertFormat;
#define GPENCIL_CACHE_BLOCK_SIZE 8
#define GPENCIL_MAX_SHGROUPS 65536
#define GPENCIL_GROUPS_BLOCK_SIZE 1024
@ -46,23 +50,6 @@ struct tGPspoint;
#define GPENCIL_COLOR_TEXTURE 1
#define GPENCIL_COLOR_PATTERN 2
#define GP_SIMPLIFY(scene) ((scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ENABLE))
#define GP_SIMPLIFY_ONPLAY(playing) \
(((playing == true) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ON_PLAY)) || \
((scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ON_PLAY) == 0))
#define GP_SIMPLIFY_FILL(scene, playing) \
((GP_SIMPLIFY_ONPLAY(playing) && (GP_SIMPLIFY(scene)) && \
(scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_FILL)))
#define GP_SIMPLIFY_MODIF(scene, playing) \
((GP_SIMPLIFY_ONPLAY(playing) && (GP_SIMPLIFY(scene)) && \
(scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_MODIFIER)))
#define GP_SIMPLIFY_FX(scene, playing) \
((GP_SIMPLIFY_ONPLAY(playing) && (GP_SIMPLIFY(scene)) && \
(scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_FX)))
#define GP_SIMPLIFY_BLEND(scene, playing) \
((GP_SIMPLIFY_ONPLAY(playing) && (GP_SIMPLIFY(scene)) && \
(scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_BLEND)))
#define GP_IS_CAMERAVIEW ((rv3d != NULL) && (rv3d->persp == RV3D_CAMOB && v3d->camera))
/* *********** OBJECTS CACHE *********** */
@ -341,13 +328,13 @@ typedef struct GPENCIL_e_data {
} GPENCIL_e_data; /* Engine data */
/* GPUBatch Cache */
/* GPUBatch Cache Element */
typedef struct GpencilBatchCacheElem {
GPUBatch *batch;
GPUVertBuf *vbo;
int vbo_len;
/* attr ids */
GPUVertFormat format;
GPUVertFormat *format;
uint pos_id;
uint color_id;
uint thickness_id;
@ -358,6 +345,7 @@ typedef struct GpencilBatchCacheElem {
int tot_vertex;
} GpencilBatchCacheElem;
/* Defines each batch group to define later the shgroup */
typedef struct GpencilBatchGroup {
struct bGPDlayer *gpl; /* reference to original layer */
struct bGPDframe *gpf; /* reference to original frame */
@ -375,6 +363,7 @@ typedef enum GpencilBatchGroup_Type {
eGpencilBatchGroupType_Edlin = 5,
} GpencilBatchGroup_Type;
/* Runtime data for GPU and evaluated frames after applying modifiers */
typedef struct GpencilBatchCache {
GpencilBatchCacheElem b_stroke;
GpencilBatchCacheElem b_point;
@ -382,18 +371,19 @@ typedef struct GpencilBatchCache {
GpencilBatchCacheElem b_edit;
GpencilBatchCacheElem b_edlin;
/* settings to determine if cache is invalid */
/** Cache is dirty */
bool is_dirty;
/** Edit mode flag */
bool is_editmode;
/** Last cache frame */
int cache_frame;
/* 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 */
/** Total groups in arrays */
int grp_used;
/** Max size of the array */
int grp_size;
/** Array of cache elements */
struct GpencilBatchGroup *grp_cache;
} GpencilBatchCache;
/* general drawing functions */

View File

@ -2886,7 +2886,7 @@ static int gpencil_color_select_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
/* copy on write tag is needed, or else no refresh happens */
DEG_id_tag_update(&gpd->id, ID_RECALC_COPY_ON_WRITE);
DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
/* notifiers */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);

View File

@ -51,6 +51,14 @@ typedef struct bGPDcontrolpoint {
int size;
} bGPDcontrolpoint;
typedef struct bGPDspoint_Runtime {
/** Original point (used to dereference evaluated data) */
struct bGPDspoint *pt_orig;
/** Original index array position */
int idx_orig;
char _pad0[4];
} bGPDspoint_Runtime;
/* Grease-Pencil Annotations - 'Stroke Point'
* -> Coordinates may either be 2d or 3d depending on settings at the time
* -> Coordinates of point on stroke, in proportions of window size
@ -72,6 +80,10 @@ typedef struct bGPDspoint {
float uv_fac;
/** Uv rotation for dot mode. */
float uv_rot;
/** Runtime data */
char _pad2[4];
bGPDspoint_Runtime runtime;
} bGPDspoint;
/* bGPDspoint->flag */
@ -156,15 +168,21 @@ typedef enum eGPDpalette_Flag {
/* Runtime temp data for bGPDstroke */
typedef struct bGPDstroke_Runtime {
/* runtime final colors (result of original colors and modifiers) */
/** runtime final colors (result of original colors and modifiers) */
float tmp_stroke_rgba[4];
/** runtime final fill colors (result of original colors and modifiers) */
float tmp_fill_rgba[4];
/* temporary layer name only used during copy/paste to put the stroke in the original layer */
/** temporary layer name only used during copy/paste to put the stroke in the original layer */
char tmp_layerinfo[128];
/** Runtime falloff factor (only for transform). */
float multi_frame_falloff;
char _pad[4];
/** Original stroke (used to dereference evaluated data) */
struct bGPDstroke *gps_orig;
} bGPDstroke_Runtime;
/* Grease-Pencil Annotations - 'Stroke'
@ -210,7 +228,6 @@ typedef struct bGPDstroke {
void *_pad3;
bGPDstroke_Runtime runtime;
char _pad2[4];
} bGPDstroke;
/* bGPDstroke->flag */
@ -468,7 +485,6 @@ typedef struct bGPdata {
ListBase layers;
/** Settings for this data-block. */
int flag;
char _pad1[4];
/* Palettes */

View File

@ -176,6 +176,11 @@ typedef struct Object_Runtime {
/** Runtime grease pencil drawing data */
struct GpencilBatchCache *gpencil_cache;
/** Runtime grease pencil total layers used for evaluated data created by modifiers */
int gpencil_tot_layers;
char _pad4[4];
/** Runtime grease pencil evaluated data created by modifiers */
struct bGPDframe *gpencil_evaluated_frames;
void *_pad2; /* Padding is here for win32s unconventional struct alignment rules. */
} Object_Runtime;