2 * Copyright 2017, Blender Foundation.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * Contributor(s): Antonio Vazquez
22 /** \file blender/draw/engines/gpencil/gpencil_draw_utils.c
26 #include "BLI_polyfill_2d.h"
28 #include "DRW_engine.h"
29 #include "DRW_render.h"
31 #include "BKE_brush.h"
32 #include "BKE_gpencil.h"
33 #include "BKE_gpencil_modifier.h"
34 #include "BKE_image.h"
35 #include "BKE_material.h"
36 #include "BKE_paint.h"
38 #include "ED_gpencil.h"
39 #include "ED_view3d.h"
41 #include "DNA_gpencil_types.h"
42 #include "DNA_material_types.h"
43 #include "DNA_view3d_types.h"
44 #include "DNA_gpencil_modifier_types.h"
46 /* If builtin shaders are needed */
47 #include "GPU_shader.h"
48 #include "GPU_texture.h"
50 /* For EvaluationContext... */
51 #include "DEG_depsgraph.h"
52 #include "DEG_depsgraph_query.h"
54 #include "IMB_imbuf_types.h"
56 #include "gpencil_engine.h"
58 /* fill type to communicate to shader */
66 #define GP_SET_SRC_GPS(src_gps) if (src_gps) src_gps = src_gps->next
68 /* Get number of vertex for using in GPU VBOs */
69 static void gpencil_calc_vertex(
70 GPENCIL_StorageList *stl, tGPencilObjectCache *cache_ob,
71 GpencilBatchCache *cache, bGPdata *gpd,
74 Object *ob = cache_ob->ob;
75 const DRWContextState *draw_ctx = DRW_context_state_get();
76 const bool main_onion = draw_ctx->v3d != NULL ? (draw_ctx->v3d->gp_flag & V3D_GP_SHOW_ONION_SKIN) : true;
77 const bool playing = stl->storage->is_playing;
78 const bool do_onion = (bool)((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0) &&
79 main_onion && DRW_gpencil_onion_active(gpd) && !playing;
81 const bool time_remap = BKE_gpencil_has_time_modifiers(ob);
82 const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
84 cache_ob->tot_vertex = 0;
85 cache_ob->tot_triangles = 0;
87 for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
88 bGPDframe *init_gpf = NULL;
89 const bool is_onion = ((do_onion) && (gpl->onion_flag & GP_LAYER_ONIONSKIN));
90 if (gpl->flag & GP_LAYER_HIDE) {
94 /* if multiedit or onion skin need to count all frames of the layer */
95 if ((is_multiedit) || (is_onion)) {
96 init_gpf = gpl->frames.first;
99 /* verify time modifiers */
100 if ((time_remap) && (!stl->storage->simplify_modif)) {
101 int remap_cfra = BKE_gpencil_time_modifier(
102 draw_ctx->depsgraph, draw_ctx->scene, ob, gpl, cfra_eval,
103 stl->storage->is_render);
104 init_gpf = BKE_gpencil_layer_getframe(gpl, remap_cfra, GP_GETFRAME_USE_PREV);
107 init_gpf = gpl->actframe;
111 if (init_gpf == NULL) {
115 for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
116 for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
117 cache_ob->tot_vertex += gps->totpoints + 3;
118 cache_ob->tot_triangles += gps->totpoints - 1;
120 if ((!is_multiedit) && (!is_onion)) {
126 cache->b_fill.tot_vertex = cache_ob->tot_triangles * 3;
127 cache->b_stroke.tot_vertex = cache_ob->tot_vertex;
128 cache->b_point.tot_vertex = cache_ob->tot_vertex;
129 cache->b_edit.tot_vertex = cache_ob->tot_vertex;
130 cache->b_edlin.tot_vertex = cache_ob->tot_vertex;
132 /* some modifiers can change the number of points */
134 GpencilModifierData *md;
135 for (md = ob->greasepencil_modifiers.first; md; md = md->next) {
136 const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
137 /* only modifiers that change size */
138 if (mti && mti->getDuplicationFactor) {
139 factor = mti->getDuplicationFactor(md);
141 cache->b_fill.tot_vertex *= factor;
142 cache->b_stroke.tot_vertex *= factor;
143 cache->b_point.tot_vertex *= factor;
144 cache->b_edit.tot_vertex *= factor;
145 cache->b_edlin.tot_vertex *= factor;
150 /* Helper for doing all the checks on whether a stroke can be drawn */
151 static bool gpencil_can_draw_stroke(
152 struct MaterialGPencilStyle *gp_style, const bGPDstroke *gps,
153 const bool onion, const bool is_mat_preview)
155 /* skip stroke if it doesn't have any valid data */
156 if ((gps->points == NULL) || (gps->totpoints < 1) || (gp_style == NULL))
159 /* if mat preview render always visible */
160 if (is_mat_preview) {
164 /* check if the color is visible */
165 if ((gp_style == NULL) ||
166 (gp_style->flag & GP_STYLE_COLOR_HIDE) ||
167 (onion && (gp_style->flag & GP_STYLE_COLOR_ONIONSKIN)))
172 /* stroke can be drawn */
176 /* calc bounding box in 2d using flat projection data */
177 static void gpencil_calc_2d_bounding_box(
178 const float(*points2d)[2], int totpoints, float minv[2], float maxv[2])
180 minv[0] = points2d[0][0];
181 minv[1] = points2d[0][1];
182 maxv[0] = points2d[0][0];
183 maxv[1] = points2d[0][1];
185 for (int i = 1; i < totpoints; i++) {
187 if (points2d[i][0] < minv[0]) {
188 minv[0] = points2d[i][0];
190 if (points2d[i][1] < minv[1]) {
191 minv[1] = points2d[i][1];
194 if (points2d[i][0] > maxv[0]) {
195 maxv[0] = points2d[i][0];
197 if (points2d[i][1] > maxv[1]) {
198 maxv[1] = points2d[i][1];
201 /* use a perfect square */
202 if (maxv[0] > maxv[1]) {
210 /* calc texture coordinates using flat projected points */
211 static void gpencil_calc_stroke_fill_uv(
212 const float(*points2d)[2], int totpoints, float minv[2], float maxv[2], float(*r_uv)[2])
215 d[0] = maxv[0] - minv[0];
216 d[1] = maxv[1] - minv[1];
217 for (int i = 0; i < totpoints; i++) {
218 r_uv[i][0] = (points2d[i][0] - minv[0]) / d[0];
219 r_uv[i][1] = (points2d[i][1] - minv[1]) / d[1];
223 /* recalc the internal geometry caches for fill and uvs */
224 static void DRW_gpencil_recalc_geometry_caches(
225 Object *ob, bGPDlayer *gpl, MaterialGPencilStyle *gp_style, bGPDstroke *gps)
227 if (gps->flag & GP_STROKE_RECALC_GEOMETRY) {
228 /* Calculate triangles cache for filling area (must be done only after changes) */
229 if ((gps->tot_triangles == 0) || (gps->triangles == NULL)) {
230 if ((gps->totpoints > 2) &&
231 ((gp_style->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) ||
232 (gp_style->fill_style > 0) || (gpl->blend_mode != eGplBlendMode_Normal)))
234 DRW_gpencil_triangulate_stroke_fill(ob, gps);
238 /* calc uv data along the stroke */
239 ED_gpencil_calc_stroke_uv(ob, gps);
242 gps->flag &= ~GP_STROKE_RECALC_GEOMETRY;
246 /* create shading group for filling */
247 static DRWShadingGroup *DRW_gpencil_shgroup_fill_create(
248 GPENCIL_e_data *e_data, GPENCIL_Data *vedata, DRWPass *pass,
249 GPUShader *shader, bGPdata *gpd, bGPDlayer *gpl,
250 MaterialGPencilStyle *gp_style, int id)
252 GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
254 /* e_data.gpencil_fill_sh */
255 DRWShadingGroup *grp = DRW_shgroup_create(shader, pass);
257 DRW_shgroup_uniform_vec4(grp, "color2", gp_style->mix_rgba, 1);
260 switch (gp_style->fill_style) {
261 case GP_STYLE_FILL_STYLE_SOLID:
262 stl->shgroups[id].fill_style = SOLID;
264 case GP_STYLE_FILL_STYLE_GRADIENT:
265 if (gp_style->gradient_type == GP_STYLE_GRADIENT_LINEAR) {
266 stl->shgroups[id].fill_style = GRADIENT;
269 stl->shgroups[id].fill_style = RADIAL;
272 case GP_STYLE_FILL_STYLE_CHESSBOARD:
273 stl->shgroups[id].fill_style = CHESS;
275 case GP_STYLE_FILL_STYLE_TEXTURE:
276 if (gp_style->flag & GP_STYLE_FILL_PATTERN) {
277 stl->shgroups[id].fill_style = PATTERN;
280 stl->shgroups[id].fill_style = TEXTURE;
284 stl->shgroups[id].fill_style = GP_STYLE_FILL_STYLE_SOLID;
287 DRW_shgroup_uniform_int(grp, "fill_type", &stl->shgroups[id].fill_style, 1);
289 DRW_shgroup_uniform_float(grp, "mix_factor", &gp_style->mix_factor, 1);
291 DRW_shgroup_uniform_float(grp, "gradient_angle", &gp_style->gradient_angle, 1);
292 DRW_shgroup_uniform_float(grp, "gradient_radius", &gp_style->gradient_radius, 1);
293 DRW_shgroup_uniform_float(grp, "pattern_gridsize", &gp_style->pattern_gridsize, 1);
294 DRW_shgroup_uniform_vec2(grp, "gradient_scale", gp_style->gradient_scale, 1);
295 DRW_shgroup_uniform_vec2(grp, "gradient_shift", gp_style->gradient_shift, 1);
297 DRW_shgroup_uniform_float(grp, "texture_angle", &gp_style->texture_angle, 1);
298 DRW_shgroup_uniform_vec2(grp, "texture_scale", gp_style->texture_scale, 1);
299 DRW_shgroup_uniform_vec2(grp, "texture_offset", gp_style->texture_offset, 1);
300 DRW_shgroup_uniform_float(grp, "texture_opacity", &gp_style->texture_opacity, 1);
301 DRW_shgroup_uniform_float(grp, "layer_opacity", &gpl->opacity, 1);
303 stl->shgroups[id].texture_mix = gp_style->flag & GP_STYLE_COLOR_TEX_MIX ? 1 : 0;
304 DRW_shgroup_uniform_int(grp, "texture_mix", &stl->shgroups[id].texture_mix, 1);
306 stl->shgroups[id].texture_flip = gp_style->flag & GP_STYLE_COLOR_FLIP_FILL ? 1 : 0;
307 DRW_shgroup_uniform_int(grp, "texture_flip", &stl->shgroups[id].texture_flip, 1);
309 DRW_shgroup_uniform_int(grp, "xraymode", (const int *) &gpd->xray_mode, 1);
311 if ((gp_style->flag & GP_STYLE_COLOR_TEX_MIX) ||
312 (gp_style->fill_style & GP_STYLE_FILL_STYLE_TEXTURE))
315 Image *image = gp_style->ima;
316 ImageUser iuser = { NULL };
321 ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
323 if (ibuf == NULL || ibuf->rect == NULL) {
324 BKE_image_release_ibuf(image, ibuf, NULL);
327 GPUTexture *texture = GPU_texture_from_blender(gp_style->ima, &iuser, GL_TEXTURE_2D, true, 0.0);
328 DRW_shgroup_uniform_texture(grp, "myTexture", texture);
330 stl->shgroups[id].texture_clamp = gp_style->flag & GP_STYLE_COLOR_TEX_CLAMP ? 1 : 0;
331 DRW_shgroup_uniform_int(grp, "texture_clamp", &stl->shgroups[id].texture_clamp, 1);
333 BKE_image_release_ibuf(image, ibuf, NULL);
337 /* if no texture defined, need a blank texture to avoid errors in draw manager */
338 DRW_shgroup_uniform_texture(grp, "myTexture", e_data->gpencil_blank_texture);
339 stl->shgroups[id].texture_clamp = 0;
340 DRW_shgroup_uniform_int(grp, "texture_clamp", &stl->shgroups[id].texture_clamp, 1);
346 /* check if some onion is enabled */
347 bool DRW_gpencil_onion_active(bGPdata *gpd)
349 for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
350 if (gpl->onion_flag & GP_LAYER_ONIONSKIN) {
357 /* create shading group for strokes */
358 DRWShadingGroup *DRW_gpencil_shgroup_stroke_create(
359 GPENCIL_e_data *e_data, GPENCIL_Data *vedata, DRWPass *pass, GPUShader *shader, Object *ob,
360 bGPdata *gpd, bGPDstroke *gps, MaterialGPencilStyle *gp_style, int id, bool onion)
362 GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
363 const float *viewport_size = DRW_viewport_size_get();
365 /* e_data.gpencil_stroke_sh */
366 DRWShadingGroup *grp = DRW_shgroup_create(shader, pass);
368 DRW_shgroup_uniform_vec2(grp, "Viewport", viewport_size, 1);
370 DRW_shgroup_uniform_float(grp, "pixsize", stl->storage->pixsize, 1);
372 /* avoid wrong values */
373 if ((gpd) && (gpd->pixfactor == 0)) {
374 gpd->pixfactor = GP_DEFAULT_PIX_FACTOR;
377 /* object scale and depth */
378 if ((ob) && (id > -1)) {
379 stl->shgroups[id].obj_scale = mat4_to_scale(ob->obmat);
380 DRW_shgroup_uniform_float(grp, "objscale", &stl->shgroups[id].obj_scale, 1);
381 stl->shgroups[id].keep_size = (int)((gpd) && (gpd->flag & GP_DATA_STROKE_KEEPTHICKNESS));
382 DRW_shgroup_uniform_int(grp, "keep_size", &stl->shgroups[id].keep_size, 1);
384 stl->shgroups[id].stroke_style = gp_style->stroke_style;
385 stl->shgroups[id].color_type = GPENCIL_COLOR_SOLID;
386 if ((gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) && (!onion)) {
387 stl->shgroups[id].color_type = GPENCIL_COLOR_TEXTURE;
388 if (gp_style->flag & GP_STYLE_STROKE_PATTERN) {
389 stl->shgroups[id].color_type = GPENCIL_COLOR_PATTERN;
392 DRW_shgroup_uniform_int(grp, "color_type", &stl->shgroups[id].color_type, 1);
393 DRW_shgroup_uniform_float(grp, "pixfactor", &gpd->pixfactor, 1);
395 stl->shgroups[id].caps_mode[0] = gps->caps[0];
396 stl->shgroups[id].caps_mode[1] = gps->caps[1];
397 DRW_shgroup_uniform_int(grp, "caps_mode", &stl->shgroups[id].caps_mode[0], 2);
400 stl->storage->obj_scale = 1.0f;
401 stl->storage->keep_size = 0;
402 stl->storage->pixfactor = GP_DEFAULT_PIX_FACTOR;
403 DRW_shgroup_uniform_float(grp, "objscale", &stl->storage->obj_scale, 1);
404 DRW_shgroup_uniform_int(grp, "keep_size", &stl->storage->keep_size, 1);
405 DRW_shgroup_uniform_int(grp, "color_type", &stl->storage->color_type, 1);
407 DRW_shgroup_uniform_float(grp, "pixfactor", &gpd->pixfactor, 1);
410 DRW_shgroup_uniform_float(grp, "pixfactor", &stl->storage->pixfactor, 1);
412 const int zero[2] = { 0, 0 };
413 DRW_shgroup_uniform_int(grp, "caps_mode", &zero[0], 2);
416 if ((gpd) && (id > -1)) {
417 DRW_shgroup_uniform_int(grp, "xraymode", (const int *) &gpd->xray_mode, 1);
420 /* for drawing always on predefined z-depth */
421 DRW_shgroup_uniform_int(grp, "xraymode", &stl->storage->xray, 1);
424 /* image texture for pattern */
425 if ((gp_style) && (gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) && (!onion)) {
427 Image *image = gp_style->sima;
428 ImageUser iuser = { NULL };
433 ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
435 if (ibuf == NULL || ibuf->rect == NULL) {
436 BKE_image_release_ibuf(image, ibuf, NULL);
439 GPUTexture *texture = GPU_texture_from_blender(gp_style->sima, &iuser, GL_TEXTURE_2D, true, 0.0f);
440 DRW_shgroup_uniform_texture(grp, "myTexture", texture);
442 BKE_image_release_ibuf(image, ibuf, NULL);
446 /* if no texture defined, need a blank texture to avoid errors in draw manager */
447 DRW_shgroup_uniform_texture(grp, "myTexture", e_data->gpencil_blank_texture);
453 /* create shading group for points */
454 static DRWShadingGroup *DRW_gpencil_shgroup_point_create(
455 GPENCIL_e_data *e_data, GPENCIL_Data *vedata, DRWPass *pass, GPUShader *shader, Object *ob,
456 bGPdata *gpd, MaterialGPencilStyle *gp_style, int id, bool onion)
458 GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
459 const float *viewport_size = DRW_viewport_size_get();
461 /* e_data.gpencil_stroke_sh */
462 DRWShadingGroup *grp = DRW_shgroup_create(shader, pass);
464 DRW_shgroup_uniform_vec2(grp, "Viewport", viewport_size, 1);
465 DRW_shgroup_uniform_float(grp, "pixsize", stl->storage->pixsize, 1);
467 /* avoid wrong values */
468 if ((gpd) && (gpd->pixfactor == 0)) {
469 gpd->pixfactor = GP_DEFAULT_PIX_FACTOR;
472 /* object scale and depth */
473 if ((ob) && (id > -1)) {
474 stl->shgroups[id].obj_scale = mat4_to_scale(ob->obmat);
475 DRW_shgroup_uniform_float(grp, "objscale", &stl->shgroups[id].obj_scale, 1);
476 stl->shgroups[id].keep_size = (int)((gpd) && (gpd->flag & GP_DATA_STROKE_KEEPTHICKNESS));
477 DRW_shgroup_uniform_int(grp, "keep_size", &stl->shgroups[id].keep_size, 1);
479 stl->shgroups[id].mode = gp_style->mode;
480 stl->shgroups[id].stroke_style = gp_style->stroke_style;
481 stl->shgroups[id].color_type = GPENCIL_COLOR_SOLID;
482 if ((gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) && (!onion)) {
483 stl->shgroups[id].color_type = GPENCIL_COLOR_TEXTURE;
484 if (gp_style->flag & GP_STYLE_STROKE_PATTERN) {
485 stl->shgroups[id].color_type = GPENCIL_COLOR_PATTERN;
488 DRW_shgroup_uniform_int(grp, "color_type", &stl->shgroups[id].color_type, 1);
489 DRW_shgroup_uniform_int(grp, "mode", &stl->shgroups[id].mode, 1);
490 DRW_shgroup_uniform_float(grp, "pixfactor", &gpd->pixfactor, 1);
493 stl->storage->obj_scale = 1.0f;
494 stl->storage->keep_size = 0;
495 stl->storage->pixfactor = GP_DEFAULT_PIX_FACTOR;
496 stl->storage->mode = gp_style->mode;
497 DRW_shgroup_uniform_float(grp, "objscale", &stl->storage->obj_scale, 1);
498 DRW_shgroup_uniform_int(grp, "keep_size", &stl->storage->keep_size, 1);
499 DRW_shgroup_uniform_int(grp, "color_type", &stl->storage->color_type, 1);
500 DRW_shgroup_uniform_int(grp, "mode", &stl->storage->mode, 1);
502 DRW_shgroup_uniform_float(grp, "pixfactor", &gpd->pixfactor, 1);
505 DRW_shgroup_uniform_float(grp, "pixfactor", &stl->storage->pixfactor, 1);
510 DRW_shgroup_uniform_int(grp, "xraymode", (const int *)&gpd->xray_mode, 1);
513 /* for drawing always on on predefined z-depth */
514 DRW_shgroup_uniform_int(grp, "xraymode", &stl->storage->xray, 1);
518 if ((gp_style) && (gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) && (!onion)) {
520 Image *image = gp_style->sima;
521 ImageUser iuser = { NULL };
526 ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
528 if (ibuf == NULL || ibuf->rect == NULL) {
529 BKE_image_release_ibuf(image, ibuf, NULL);
532 GPUTexture *texture = GPU_texture_from_blender(gp_style->sima, &iuser, GL_TEXTURE_2D, true, 0.0f);
533 DRW_shgroup_uniform_texture(grp, "myTexture", texture);
535 BKE_image_release_ibuf(image, ibuf, NULL);
539 /* if no texture defined, need a blank texture to avoid errors in draw manager */
540 DRW_shgroup_uniform_texture(grp, "myTexture", e_data->gpencil_blank_texture);
546 /* add fill vertex info */
547 static void gpencil_add_fill_vertexdata(
548 GpencilBatchCache *cache,
549 Object *ob, bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps,
550 float opacity, const float tintcolor[4], const bool onion, const bool custonion)
552 MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
553 if (gps->totpoints >= 3) {
555 /* set color using material, tint color and opacity */
556 interp_v3_v3v3(tfill, gps->runtime.tmp_fill_rgba, tintcolor, tintcolor[3]);
557 tfill[3] = gps->runtime.tmp_fill_rgba[3] * opacity;
558 if ((tfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) ||
559 (gp_style->fill_style > 0) ||
560 (gpl->blend_mode != eGplBlendMode_Normal))
562 if (cache->is_dirty) {
572 ARRAY_SET_ITEMS(tfill, UNPACK3(gps->runtime.tmp_fill_rgba), tintcolor[3]);
576 /* create vertex data */
577 const int old_len = cache->b_fill.vbo_len;
578 DRW_gpencil_get_fill_geom(&cache->b_fill, ob, gps, color);
580 /* add to list of groups */
581 if (old_len < cache->b_fill.vbo_len) {
582 cache->grp_cache = gpencil_group_cache_add(
583 cache->grp_cache, gpl, gpf, gps,
584 eGpencilBatchGroupType_Fill, onion,
585 cache->b_fill.vbo_len,
586 &cache->grp_size, &cache->grp_used);
593 /* add stroke vertex info */
594 static void gpencil_add_stroke_vertexdata(
595 GpencilBatchCache *cache,
596 Object *ob, bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps,
597 const float opacity, const float tintcolor[4], const bool onion,
598 const bool custonion)
603 MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
605 /* set color using base color, tint color and opacity */
606 if (cache->is_dirty) {
608 /* if special stroke, use fill color as stroke color */
609 if (gps->flag & GP_STROKE_NOFILL) {
610 interp_v3_v3v3(tcolor, gps->runtime.tmp_fill_rgba, tintcolor, tintcolor[3]);
611 tcolor[3] = gps->runtime.tmp_fill_rgba[3] * opacity;
614 interp_v3_v3v3(tcolor, gps->runtime.tmp_stroke_rgba, tintcolor, tintcolor[3]);
615 tcolor[3] = gps->runtime.tmp_stroke_rgba[3] * opacity;
617 copy_v4_v4(ink, tcolor);
621 copy_v4_v4(ink, tintcolor);
624 ARRAY_SET_ITEMS(tcolor, UNPACK3(gps->runtime.tmp_stroke_rgba), opacity);
625 copy_v4_v4(ink, tcolor);
629 sthickness = gps->thickness + gpl->line_change;
630 CLAMP_MIN(sthickness, 1);
632 if ((gps->totpoints > 1) && (gp_style->mode == GP_STYLE_MODE_LINE)) {
633 /* create vertex data */
634 const int old_len = cache->b_stroke.vbo_len;
635 DRW_gpencil_get_stroke_geom(&cache->b_stroke, gps, sthickness, ink);
637 /* add to list of groups */
638 if (old_len < cache->b_stroke.vbo_len) {
639 cache->grp_cache = gpencil_group_cache_add(
640 cache->grp_cache, gpl, gpf, gps,
641 eGpencilBatchGroupType_Stroke, onion,
642 cache->b_stroke.vbo_len,
643 &cache->grp_size, &cache->grp_used);
647 /* create vertex data */
648 const int old_len = cache->b_point.vbo_len;
649 DRW_gpencil_get_point_geom(&cache->b_point, gps, sthickness, ink);
651 /* add to list of groups */
652 if (old_len < cache->b_point.vbo_len) {
653 cache->grp_cache = gpencil_group_cache_add(
654 cache->grp_cache, gpl, gpf, gps, eGpencilBatchGroupType_Point, onion,
655 cache->b_point.vbo_len,
656 &cache->grp_size, &cache->grp_used);
662 /* add edit points vertex info */
663 static void gpencil_add_editpoints_vertexdata(
664 GPENCIL_StorageList *UNUSED(stl), GpencilBatchCache *cache, ToolSettings *UNUSED(ts), Object *ob,
665 bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps)
667 const DRWContextState *draw_ctx = DRW_context_state_get();
668 View3D *v3d = draw_ctx->v3d;
669 MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
671 /* alpha factor for edit points/line to make them more subtle */
672 float edit_alpha = v3d->vertex_opacity;
674 if (GPENCIL_ANY_EDIT_MODE(gpd)) {
675 Object *obact = DRW_context_state_get()->obact;
676 if ((!obact) || (obact->type != OB_GPENCIL)) {
679 const bool is_weight_paint = (gpd) && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE);
681 if (cache->is_dirty) {
683 ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) &&
684 (v3d->gp_flag & V3D_GP_SHOW_EDIT_LINES))
686 /* line of the original stroke */
687 DRW_gpencil_get_edlin_geom(&cache->b_edlin, gps, edit_alpha, gpd->flag);
689 /* add to list of groups */
690 cache->grp_cache = gpencil_group_cache_add(
691 cache->grp_cache, gpl, gpf, gps,
692 eGpencilBatchGroupType_Edlin, false,
693 cache->b_edlin.vbo_len,
694 &cache->grp_size, &cache->grp_used);
697 if ((gps->flag & GP_STROKE_SELECT) || (is_weight_paint)) {
698 if ((gpl->flag & GP_LAYER_UNLOCK_COLOR) || ((gp_style->flag & GP_STYLE_COLOR_LOCKED) == 0)) {
700 DRW_gpencil_get_edit_geom(&cache->b_edit, gps, edit_alpha, gpd->flag);
702 /* add to list of groups */
703 cache->grp_cache = gpencil_group_cache_add(
704 cache->grp_cache, gpl, gpf, gps,
705 eGpencilBatchGroupType_Edit, false,
706 cache->b_edit.vbo_len,
707 &cache->grp_size, &cache->grp_used);
715 /* main function to draw strokes */
716 static void gpencil_draw_strokes(
717 GpencilBatchCache *cache, GPENCIL_e_data *e_data, void *vedata, ToolSettings *ts, Object *ob,
718 bGPdata *gpd, bGPDlayer *gpl, bGPDframe *src_gpf, bGPDframe *derived_gpf,
719 const float opacity, const float tintcolor[4],
720 const bool custonion, tGPencilObjectCache *cache_ob)
722 GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
723 GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
724 const DRWContextState *draw_ctx = DRW_context_state_get();
725 Scene *scene = draw_ctx->scene;
726 View3D *v3d = draw_ctx->v3d;
727 bGPDstroke *gps, *src_gps;
728 float viewmatrix[4][4];
729 const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
730 const bool playing = stl->storage->is_playing;
731 const bool is_render = (bool)stl->storage->is_render;
732 const bool is_mat_preview = (bool)stl->storage->is_mat_preview;
733 const bool overlay_multiedit = v3d != NULL ? (v3d->gp_flag & V3D_GP_SHOW_MULTIEDIT_LINES) : true;
735 /* Get evaluation context */
736 /* NOTE: We must check if C is valid, otherwise we get crashes when trying to save files
737 * (i.e. the thumbnail offscreen rendering fails)
739 Depsgraph *depsgraph = DRW_context_state_get()->depsgraph;
741 /* get parent matrix and save as static data */
742 ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, viewmatrix);
743 copy_m4_m4(derived_gpf->runtime.viewmatrix, viewmatrix);
745 if ((cache_ob != NULL) && (cache_ob->is_dup_ob)) {
746 copy_m4_m4(derived_gpf->runtime.viewmatrix, cache_ob->obmat);
749 /* apply geometry modifiers */
750 if ((cache->is_dirty) && (ob->greasepencil_modifiers.first) && (!is_multiedit)) {
751 if (!stl->storage->simplify_modif) {
752 if (BKE_gpencil_has_geometry_modifiers(ob)) {
753 BKE_gpencil_geometry_modifiers(depsgraph, ob, gpl, derived_gpf, stl->storage->is_render);
759 src_gps = src_gpf->strokes.first;
765 for (gps = derived_gpf->strokes.first; gps; gps = gps->next) {
766 MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
768 /* check if stroke can be drawn */
769 if (gpencil_can_draw_stroke(gp_style, gps, false, is_mat_preview) == false) {
770 GP_SET_SRC_GPS(src_gps);
774 /* be sure recalc all cache in source stroke to avoid recalculation when frame change
777 DRW_gpencil_recalc_geometry_caches(ob, gpl, gp_style, src_gps);
780 /* if the fill has any value, it's considered a fill and is not drawn if simplify fill is enabled */
781 if ((stl->storage->simplify_fill) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_REMOVE_FILL_LINE)) {
782 if ((gp_style->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) ||
783 (gp_style->fill_style > GP_STYLE_FILL_STYLE_SOLID) ||
784 (gpl->blend_mode != eGplBlendMode_Normal))
786 GP_SET_SRC_GPS(src_gps);
791 if ((gpl->actframe->framenum == derived_gpf->framenum) ||
792 (!is_multiedit) || (overlay_multiedit))
794 /* copy color to temp fields to apply temporal changes in the stroke */
795 copy_v4_v4(gps->runtime.tmp_stroke_rgba, gp_style->stroke_rgba);
796 copy_v4_v4(gps->runtime.tmp_fill_rgba, gp_style->fill_rgba);
798 /* apply modifiers (only modify geometry, but not create ) */
799 if ((cache->is_dirty) && (ob->greasepencil_modifiers.first) && (!is_multiedit)) {
800 if (!stl->storage->simplify_modif) {
801 BKE_gpencil_stroke_modifiers(depsgraph, ob, gpl, derived_gpf, gps, stl->storage->is_render);
805 /* hide any blend layer */
806 if ((!stl->storage->simplify_blend) ||
807 (gpl->blend_mode == eGplBlendMode_Normal))
810 if ((gp_style->flag & GP_STYLE_FILL_SHOW) &&
811 (!stl->storage->simplify_fill) &&
812 ((gps->flag & GP_STROKE_NOFILL) == 0))
814 gpencil_add_fill_vertexdata(
815 cache, ob, gpl, derived_gpf, gps,
816 opacity, tintcolor, false, custonion);
819 /* No fill strokes, must show stroke always */
820 if (((gp_style->flag & GP_STYLE_STROKE_SHOW) ||
821 (gps->flag & GP_STROKE_NOFILL)) &&
822 ((gp_style->stroke_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) ||
823 (gpl->blend_mode == eGplBlendMode_Normal)))
825 gpencil_add_stroke_vertexdata(
826 cache, ob, gpl, derived_gpf, gps,
827 opacity, tintcolor, false, custonion);
832 /* edit points (only in edit mode and not play animation not render) */
833 if ((draw_ctx->obact == ob) && (src_gps) &&
834 (!playing) && (!is_render) && (!cache_ob->is_dup_ob))
836 if ((gpl->flag & GP_LAYER_LOCKED) == 0) {
837 if (!stl->g_data->shgrps_edit_line) {
838 stl->g_data->shgrps_edit_line = DRW_shgroup_create(e_data->gpencil_line_sh, psl->edit_pass);
840 if (!stl->g_data->shgrps_edit_point) {
841 stl->g_data->shgrps_edit_point = DRW_shgroup_create(e_data->gpencil_edit_point_sh, psl->edit_pass);
842 const float *viewport_size = DRW_viewport_size_get();
843 DRW_shgroup_uniform_vec2(stl->g_data->shgrps_edit_point, "Viewport", viewport_size, 1);
846 gpencil_add_editpoints_vertexdata(stl, cache, ts, ob, gpd, gpl, derived_gpf, src_gps);
850 GP_SET_SRC_GPS(src_gps);
854 /* get alpha factor for onion strokes */
855 static void gpencil_get_onion_alpha(float color[4], bGPdata *gpd)
857 #define MIN_ALPHA_VALUE 0.01f
859 /* if fade is disabled, opacity is equal in all frames */
860 if ((gpd->onion_flag & GP_ONION_FADE) == 0) {
861 color[3] = gpd->onion_factor;
864 /* add override opacity factor */
865 color[3] += gpd->onion_factor - 0.5f;
868 CLAMP(color[3], MIN_ALPHA_VALUE, 1.0f);
871 /* function to draw strokes for onion only */
872 static void gpencil_draw_onion_strokes(
873 GpencilBatchCache *cache, GPENCIL_e_data *UNUSED(e_data), void *vedata, Object *ob,
874 bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf,
875 const float opacity, const float tintcolor[4], const bool custonion)
877 GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
878 Depsgraph *depsgraph = DRW_context_state_get()->depsgraph;
880 float viewmatrix[4][4];
882 /* get parent matrix and save as static data */
883 ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, viewmatrix);
884 copy_m4_m4(gpf->runtime.viewmatrix, viewmatrix);
886 for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
887 MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
888 if (gp_style == NULL) {
891 copy_v4_v4(gps->runtime.tmp_stroke_rgba, gp_style->stroke_rgba);
892 copy_v4_v4(gps->runtime.tmp_fill_rgba, gp_style->fill_rgba);
894 int id = stl->storage->shgroup_id;
895 /* check if stroke can be drawn */
896 if (gpencil_can_draw_stroke(gp_style, gps, true, false) == false) {
899 /* limit the number of shading groups */
900 if (id >= GPENCIL_MAX_SHGROUPS) {
905 gpencil_add_stroke_vertexdata(
906 cache, ob, gpl, gpf, gps, opacity, tintcolor, true, custonion);
908 stl->storage->shgroup_id++;
912 /* draw onion-skinning for a layer */
913 static void gpencil_draw_onionskins(
914 GpencilBatchCache *cache, GPENCIL_e_data *e_data, void *vedata,
915 Object *ob, bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf)
918 const float default_color[3] = { UNPACK3(U.gpencil_new_layer_col) };
919 const float alpha = 1.0f;
925 bool colflag = false;
926 bGPDframe *gpf_loop = NULL;
927 int last = gpf->framenum;
929 colflag = (bool)gpd->onion_flag & GP_ONION_GHOST_PREVCOL;
931 /* -------------------------------
932 * 1) Draw Previous Frames First
933 * ------------------------------- */
935 mode = gpd->onion_mode;
937 if (gpd->onion_flag & GP_ONION_GHOST_PREVCOL) {
938 copy_v3_v3(color, gpd->gcolor_prev);
941 copy_v3_v3(color, default_color);
945 for (bGPDframe *gf = gpf->prev; gf; gf = gf->prev) {
946 /* only selected frames */
947 if ((mode == GP_ONION_MODE_SELECTED) && ((gf->flag & GP_FRAME_SELECT) == 0)) {
951 if (mode == GP_ONION_MODE_ABSOLUTE) {
952 if ((gpf->framenum - gf->framenum) > step) {
957 if (mode == GP_ONION_MODE_RELATIVE) {
964 /* alpha decreases with distance from curframe index */
965 if (mode != GP_ONION_MODE_SELECTED) {
966 if (mode == GP_ONION_MODE_ABSOLUTE) {
967 fac = 1.0f - ((float)(gpf->framenum - gf->framenum) / (float)(step + 1));
970 fac = 1.0f - ((float)idx / (float)(step + 1));
972 color[3] = alpha * fac * 0.66f;
976 fac = alpha - ((1.1f - (1.0f / (float)idx)) * 0.66f);
980 /* if loop option, save the frame to use later */
981 if ((mode != GP_ONION_MODE_ABSOLUTE) && (gpd->onion_flag & GP_ONION_LOOP)) {
985 gpencil_get_onion_alpha(color, gpd);
986 gpencil_draw_onion_strokes(cache, e_data, vedata, ob, gpd, gpl, gf, color[3], color, colflag);
988 /* -------------------------------
989 * 2) Now draw next frames
990 * ------------------------------- */
991 step = gpd->gstep_next;
992 mode = gpd->onion_mode;
994 if (gpd->onion_flag & GP_ONION_GHOST_NEXTCOL) {
995 copy_v3_v3(color, gpd->gcolor_next);
998 copy_v3_v3(color, default_color);
1002 for (bGPDframe *gf = gpf->next; gf; gf = gf->next) {
1003 /* only selected frames */
1004 if ((mode == GP_ONION_MODE_SELECTED) && ((gf->flag & GP_FRAME_SELECT) == 0)) {
1007 /* absolute range */
1008 if (mode == GP_ONION_MODE_ABSOLUTE) {
1009 if ((gf->framenum - gpf->framenum) > step) {
1013 /* relative range */
1014 if (mode == GP_ONION_MODE_RELATIVE) {
1021 /* alpha decreases with distance from curframe index */
1022 if (mode != GP_ONION_MODE_SELECTED) {
1023 if (mode == GP_ONION_MODE_ABSOLUTE) {
1024 fac = 1.0f - ((float)(gf->framenum - gpf->framenum) / (float)(step + 1));
1027 fac = 1.0f - ((float)idx / (float)(step + 1));
1029 color[3] = alpha * fac * 0.66f;
1033 fac = alpha - ((1.1f - (1.0f / (float)idx)) * 0.66f);
1037 gpencil_get_onion_alpha(color, gpd);
1038 gpencil_draw_onion_strokes(cache, e_data, vedata, ob, gpd, gpl, gf, color[3], color, colflag);
1039 if (last < gf->framenum) {
1040 last = gf->framenum;
1044 /* Draw first frame in blue for loop mode */
1045 if ((gpd->onion_flag & GP_ONION_LOOP) && (gpf_loop != NULL)) {
1046 if ((last == gpf->framenum) || (gpf->next == NULL)) {
1047 gpencil_get_onion_alpha(color, gpd);
1048 gpencil_draw_onion_strokes(
1049 cache, e_data, vedata, ob, gpd, gpl,
1050 gpf_loop, color[3], color, colflag);
1055 static void gpencil_copy_frame(bGPDframe *gpf, bGPDframe *derived_gpf)
1057 derived_gpf->prev = gpf->prev;
1058 derived_gpf->next = gpf->next;
1059 derived_gpf->framenum = gpf->framenum;
1060 derived_gpf->flag = gpf->flag;
1061 derived_gpf->key_type = gpf->key_type;
1062 derived_gpf->runtime = gpf->runtime;
1063 copy_m4_m4(derived_gpf->runtime.viewmatrix, gpf->runtime.viewmatrix);
1066 BLI_listbase_clear(&derived_gpf->strokes);
1067 for (bGPDstroke *gps_src = gpf->strokes.first; gps_src; gps_src = gps_src->next) {
1068 /* make copy of source stroke */
1069 bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps_src);
1070 BLI_addtail(&derived_gpf->strokes, gps_dst);
1074 /* Triangulate stroke for high quality fill (this is done only if cache is null or stroke was modified) */
1075 void DRW_gpencil_triangulate_stroke_fill(Object *ob, bGPDstroke *gps)
1077 BLI_assert(gps->totpoints >= 3);
1079 bGPdata *gpd = (bGPdata *)ob->data;
1081 /* allocate memory for temporary areas */
1082 gps->tot_triangles = gps->totpoints - 2;
1083 uint(*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * gps->tot_triangles, "GP Stroke temp triangulation");
1084 float(*points2d)[2] = MEM_mallocN(sizeof(*points2d) * gps->totpoints, "GP Stroke temp 2d points");
1085 float(*uv)[2] = MEM_mallocN(sizeof(*uv) * gps->totpoints, "GP Stroke temp 2d uv data");
1089 /* convert to 2d and triangulate */
1090 BKE_gpencil_stroke_2d_flat(gps->points, gps->totpoints, points2d, &direction);
1091 BLI_polyfill_calc(points2d, (uint)gps->totpoints, direction, tmp_triangles);
1093 /* calc texture coordinates automatically */
1096 /* first needs bounding box data */
1097 if (gpd->flag & GP_DATA_UV_ADAPTIVE) {
1098 gpencil_calc_2d_bounding_box(points2d, gps->totpoints, minv, maxv);
1101 ARRAY_SET_ITEMS(minv, -1.0f, -1.0f);
1102 ARRAY_SET_ITEMS(maxv, 1.0f, 1.0f);
1106 gpencil_calc_stroke_fill_uv(points2d, gps->totpoints, minv, maxv, uv);
1108 /* Number of triangles */
1109 gps->tot_triangles = gps->totpoints - 2;
1110 /* save triangulation data in stroke cache */
1111 if (gps->tot_triangles > 0) {
1112 if (gps->triangles == NULL) {
1113 gps->triangles = MEM_callocN(sizeof(*gps->triangles) * gps->tot_triangles, "GP Stroke triangulation");
1116 gps->triangles = MEM_recallocN(gps->triangles, sizeof(*gps->triangles) * gps->tot_triangles);
1119 for (int i = 0; i < gps->tot_triangles; i++) {
1120 bGPDtriangle *stroke_triangle = &gps->triangles[i];
1121 memcpy(gps->triangles[i].verts, tmp_triangles[i], sizeof(uint[3]));
1122 /* copy texture coordinates */
1123 copy_v2_v2(stroke_triangle->uv[0], uv[tmp_triangles[i][0]]);
1124 copy_v2_v2(stroke_triangle->uv[1], uv[tmp_triangles[i][1]]);
1125 copy_v2_v2(stroke_triangle->uv[2], uv[tmp_triangles[i][2]]);
1129 /* No triangles needed - Free anything allocated previously */
1131 MEM_freeN(gps->triangles);
1133 gps->triangles = NULL;
1136 /* disable recalculation flag */
1137 if (gps->flag & GP_STROKE_RECALC_GEOMETRY) {
1138 gps->flag &= ~GP_STROKE_RECALC_GEOMETRY;
1142 MEM_SAFE_FREE(tmp_triangles);
1143 MEM_SAFE_FREE(points2d);
1147 /* draw stroke in drawing buffer */
1148 void DRW_gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, void *vedata, ToolSettings *ts, Object *ob)
1150 GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
1151 GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
1152 const DRWContextState *draw_ctx = DRW_context_state_get();
1153 View3D *v3d = draw_ctx->v3d;
1154 const bool overlay = v3d != NULL ? (bool)((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) : true;
1155 Brush *brush = BKE_paint_brush(&ts->gp_paint->paint);
1156 bGPdata *gpd_eval = ob->data;
1157 /* need the original to avoid cow overhead while drawing */
1158 bGPdata *gpd = (bGPdata *)DEG_get_original_id(&gpd_eval->id);
1160 MaterialGPencilStyle *gp_style = NULL;
1162 float obscale = mat4_to_scale(ob->obmat);
1164 /* use the brush material */
1165 Material *ma = BKE_gpencil_get_material_from_brush(brush);
1167 gp_style = ma->gp_style;
1169 /* this is not common, but avoid any special situations when brush could be without material */
1170 if (gp_style == NULL) {
1171 gp_style = BKE_material_gpencil_settings_get(ob, ob->actcol);
1174 /* drawing strokes */
1175 /* Check if may need to draw the active stroke cache, only if this layer is the active layer
1176 * that is being edited. (Stroke buffer is currently stored in gp-data)
1178 if (gpd->runtime.sbuffer_size > 0) {
1179 if ((gpd->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0) {
1180 /* It should also be noted that sbuffer contains temporary point types
1181 * i.e. tGPspoints NOT bGPDspoints
1183 short lthick = brush->size * obscale;
1184 /* if only one point, don't need to draw buffer because the user has no time to see it */
1185 if (gpd->runtime.sbuffer_size > 1) {
1186 if ((gp_style) && (gp_style->mode == GP_STYLE_MODE_LINE)) {
1187 stl->g_data->shgrps_drawing_stroke = DRW_gpencil_shgroup_stroke_create(
1188 e_data, vedata, psl->drawing_pass, e_data->gpencil_stroke_sh, NULL,
1189 gpd, NULL, gp_style, -1, false);
1192 stl->g_data->shgrps_drawing_stroke = DRW_gpencil_shgroup_point_create(
1193 e_data, vedata, psl->drawing_pass, e_data->gpencil_point_sh, NULL, gpd, gp_style, -1, false);
1196 /* clean previous version of the batch */
1197 if (stl->storage->buffer_stroke) {
1198 GPU_BATCH_DISCARD_SAFE(e_data->batch_buffer_stroke);
1199 MEM_SAFE_FREE(e_data->batch_buffer_stroke);
1200 stl->storage->buffer_stroke = false;
1203 /* use unit matrix because the buffer is in screen space and does not need conversion */
1204 if (gpd->runtime.mode == GP_STYLE_MODE_LINE) {
1205 e_data->batch_buffer_stroke = DRW_gpencil_get_buffer_stroke_geom(
1209 e_data->batch_buffer_stroke = DRW_gpencil_get_buffer_point_geom(
1213 /* No fill strokes, must show stroke always */
1214 if ((gp_style->flag & GP_STYLE_STROKE_SHOW) ||
1215 (gpd->runtime.sbuffer_sflag & GP_STROKE_NOFILL))
1217 DRW_shgroup_call_add(
1218 stl->g_data->shgrps_drawing_stroke,
1219 e_data->batch_buffer_stroke,
1220 stl->storage->unit_matrix);
1223 if ((gpd->runtime.sbuffer_size >= 3) &&
1224 (gpd->runtime.sfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) &&
1225 ((gpd->runtime.sbuffer_sflag & GP_STROKE_NOFILL) == 0) &&
1226 ((brush->gpencil_settings->flag & GP_BRUSH_DISSABLE_LASSO) == 0) &&
1227 (gp_style->flag & GP_STYLE_FILL_SHOW))
1229 /* if not solid, fill is simulated with solid color */
1230 if (gpd->runtime.bfill_style > 0) {
1231 gpd->runtime.sfill[3] = 0.5f;
1233 stl->g_data->shgrps_drawing_fill = DRW_shgroup_create(
1234 e_data->gpencil_drawing_fill_sh, psl->drawing_pass);
1236 /* clean previous version of the batch */
1237 if (stl->storage->buffer_fill) {
1238 GPU_BATCH_DISCARD_SAFE(e_data->batch_buffer_fill);
1239 MEM_SAFE_FREE(e_data->batch_buffer_fill);
1240 stl->storage->buffer_fill = false;
1243 e_data->batch_buffer_fill = DRW_gpencil_get_buffer_fill_geom(gpd);
1244 DRW_shgroup_call_add(
1245 stl->g_data->shgrps_drawing_fill,
1246 e_data->batch_buffer_fill,
1247 stl->storage->unit_matrix);
1248 stl->storage->buffer_fill = true;
1250 stl->storage->buffer_stroke = true;
1255 /* control points for primitives and speed guide */
1256 const bool is_cppoint = (gpd->runtime.tot_cp_points > 0);
1257 const bool is_speed_guide = (ts->gp_sculpt.guide.use_guide && (draw_ctx->object_mode == OB_MODE_PAINT_GPENCIL));
1258 const bool is_show_gizmo = (((v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0) && ((v3d->gizmo_flag & V3D_GIZMO_HIDE_TOOL) == 0));
1260 if ((overlay) && (is_cppoint || is_speed_guide) && (is_show_gizmo) &&
1261 ((gpd->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0))
1263 DRWShadingGroup *shgrp = DRW_shgroup_create(
1264 e_data->gpencil_edit_point_sh, psl->drawing_pass);
1265 const float *viewport_size = DRW_viewport_size_get();
1266 DRW_shgroup_uniform_vec2(shgrp, "Viewport", viewport_size, 1);
1268 /* clean previous version of the batch */
1269 if (stl->storage->buffer_ctrlpoint) {
1270 GPU_BATCH_DISCARD_SAFE(e_data->batch_buffer_ctrlpoint);
1271 MEM_SAFE_FREE(e_data->batch_buffer_ctrlpoint);
1272 stl->storage->buffer_ctrlpoint = false;
1275 e_data->batch_buffer_ctrlpoint = DRW_gpencil_get_buffer_ctrlpoint_geom(gpd);
1277 DRW_shgroup_call_add(
1279 e_data->batch_buffer_ctrlpoint,
1280 stl->storage->unit_matrix);
1282 stl->storage->buffer_ctrlpoint = true;
1286 /* create all missing batches */
1287 static void DRW_gpencil_create_batches(GpencilBatchCache *cache)
1289 if ((cache->b_point.vbo) && (cache->b_point.batch == NULL)) {
1290 cache->b_point.batch = GPU_batch_create_ex(GPU_PRIM_POINTS, cache->b_point.vbo, NULL, GPU_BATCH_OWNS_VBO);
1292 if ((cache->b_stroke.vbo) && (cache->b_stroke.batch == NULL)) {
1293 cache->b_stroke.batch = GPU_batch_create_ex(GPU_PRIM_LINE_STRIP_ADJ, cache->b_stroke.vbo, NULL, GPU_BATCH_OWNS_VBO);
1295 if ((cache->b_fill.vbo) && (cache->b_fill.batch == NULL)) {
1296 cache->b_fill.batch = GPU_batch_create_ex(GPU_PRIM_TRIS, cache->b_fill.vbo, NULL, GPU_BATCH_OWNS_VBO);
1298 if ((cache->b_edit.vbo) && (cache->b_edit.batch == NULL)) {
1299 cache->b_edit.batch = GPU_batch_create_ex(GPU_PRIM_POINTS, cache->b_edit.vbo, NULL, GPU_BATCH_OWNS_VBO);
1301 if ((cache->b_edlin.vbo) && (cache->b_edlin.batch == NULL)) {
1302 cache->b_edlin.batch = GPU_batch_create_ex(GPU_PRIM_LINE_STRIP, cache->b_edlin.vbo, NULL, GPU_BATCH_OWNS_VBO);
1306 /* create all shading groups */
1307 static void DRW_gpencil_shgroups_create(
1308 GPENCIL_e_data *e_data, void *vedata,
1310 GpencilBatchCache *cache, tGPencilObjectCache *cache_ob)
1312 GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
1313 GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
1314 bGPdata *gpd = (bGPdata *)ob->data;
1316 GpencilBatchGroup *elm = NULL;
1317 DRWShadingGroup *shgrp = NULL;
1318 tGPencilObjectCache_shgrp *array_elm = NULL;
1320 bGPDlayer *gpl = NULL;
1321 bGPDlayer *gpl_prev = NULL;
1323 bool tag_first = false;
1325 int start_stroke = 0;
1326 int start_point = 0;
1329 int start_edlin = 0;
1331 for (int i = 0; i < cache->grp_used; i++) {
1332 elm = &cache->grp_cache[i];
1333 array_elm = &cache_ob->shgrp_array[idx];
1335 /* save last group when change */
1336 if (gpl_prev == NULL) {
1337 gpl_prev = elm->gpl;
1341 if (elm->gpl != gpl_prev) {
1342 /* first layer is always blend Normal */
1343 array_elm->mode = idx == 0 ? eGplBlendMode_Normal: gpl->blend_mode;
1344 array_elm->end_shgrp = shgrp;
1345 gpl_prev = elm->gpl;
1352 bGPDframe *gpf = elm->gpf;
1353 bGPDstroke *gps = elm->gps;
1354 MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
1355 /* if the user switch used material from data to object,
1356 * the material could not be available */
1357 if (gp_style == NULL) {
1361 /* limit the number of shading groups */
1362 if (i >= GPENCIL_MAX_SHGROUPS) {
1366 switch (elm->type) {
1367 case eGpencilBatchGroupType_Stroke:
1369 const int len = elm->vertex_idx - start_stroke;
1371 shgrp = DRW_gpencil_shgroup_stroke_create(
1372 e_data, vedata, psl->stroke_pass, e_data->gpencil_stroke_sh,
1373 ob, gpd, gps, gp_style, stl->storage->shgroup_id, elm->onion);
1375 DRW_shgroup_call_range_add(
1376 shgrp, cache->b_stroke.batch,
1377 (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : cache_ob->obmat,
1380 stl->storage->shgroup_id++;
1381 start_stroke = elm->vertex_idx;
1384 case eGpencilBatchGroupType_Point:
1386 const int len = elm->vertex_idx - start_point;
1388 shgrp = DRW_gpencil_shgroup_point_create(
1389 e_data, vedata, psl->stroke_pass, e_data->gpencil_point_sh,
1390 ob, gpd, gp_style, stl->storage->shgroup_id, elm->onion);
1392 DRW_shgroup_call_range_add(
1393 shgrp, cache->b_point.batch,
1394 (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : cache_ob->obmat,
1397 stl->storage->shgroup_id++;
1398 start_point = elm->vertex_idx;
1401 case eGpencilBatchGroupType_Fill:
1403 const int len = elm->vertex_idx - start_fill;
1405 shgrp = DRW_gpencil_shgroup_fill_create(
1406 e_data, vedata, psl->stroke_pass, e_data->gpencil_fill_sh,
1407 gpd, gpl, gp_style, stl->storage->shgroup_id);
1409 DRW_shgroup_call_range_add(
1410 shgrp, cache->b_fill.batch,
1411 (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : cache_ob->obmat,
1414 stl->storage->shgroup_id++;
1415 start_fill = elm->vertex_idx;
1418 case eGpencilBatchGroupType_Edit:
1420 if (stl->g_data->shgrps_edit_point) {
1421 const int len = elm->vertex_idx - start_edit;
1422 /* use always the same group */
1423 DRW_shgroup_call_range_add(
1424 stl->g_data->shgrps_edit_point,
1425 cache->b_edit.batch,
1426 (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : cache_ob->obmat,
1429 start_edit = elm->vertex_idx;
1433 case eGpencilBatchGroupType_Edlin:
1435 if (stl->g_data->shgrps_edit_line) {
1436 const int len = elm->vertex_idx - start_edlin;
1437 /* use always the same group */
1438 DRW_shgroup_call_range_add(
1439 stl->g_data->shgrps_edit_line,
1440 cache->b_edlin.batch,
1441 (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : cache_ob->obmat,
1444 start_edlin = elm->vertex_idx;
1453 /* save first group */
1454 if ((shgrp != NULL) && (tag_first)) {
1455 array_elm = &cache_ob->shgrp_array[idx];
1456 array_elm->mode = idx == 0 ? eGplBlendMode_Normal: gpl->blend_mode;
1457 array_elm->clamp_layer = gpl->flag & GP_LAYER_USE_MASK;
1458 array_elm->blend_opacity = gpl->opacity;
1459 array_elm->init_shgrp = shgrp;
1460 cache_ob->tot_layers++;
1466 /* save last group */
1467 if (shgrp != NULL) {
1468 array_elm->mode = idx == 0 ? eGplBlendMode_Normal : gpl->blend_mode;
1469 array_elm->end_shgrp = shgrp;
1472 /* populate a datablock for multiedit (no onions, no modifiers) */
1473 void DRW_gpencil_populate_multiedit(
1474 GPENCIL_e_data *e_data, void *vedata, Object *ob,
1475 tGPencilObjectCache *cache_ob)
1477 bGPdata *gpd = (bGPdata *)ob->data;
1478 bGPDframe *gpf = NULL;
1480 GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
1481 const DRWContextState *draw_ctx = DRW_context_state_get();
1482 int cfra_eval = (int)DEG_get_ctime(draw_ctx->depsgraph);
1483 GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra_eval);
1484 Scene *scene = draw_ctx->scene;
1485 ToolSettings *ts = scene->toolsettings;
1487 /* check if playing animation */
1488 const bool playing = stl->storage->is_playing;
1490 /* calc max size of VBOs */
1491 gpencil_calc_vertex(stl, cache_ob, cache, gpd, cfra_eval);
1494 for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1495 /* don't draw layer if hidden */
1496 if (gpl->flag & GP_LAYER_HIDE)
1499 /* list of frames to draw */
1501 for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
1502 if ((gpf == gpl->actframe) || (gpf->flag & GP_FRAME_SELECT)) {
1503 gpencil_draw_strokes(
1504 cache, e_data, vedata, ts, ob, gpd, gpl, gpf, gpf,
1505 gpl->opacity, gpl->tintcolor, false, cache_ob);
1510 gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_USE_PREV);
1512 gpencil_draw_strokes(
1513 cache, e_data, vedata, ts, ob, gpd, gpl, gpf, gpf,
1514 gpl->opacity, gpl->tintcolor, false, cache_ob);
1520 /* create batchs and shading groups */
1521 DRW_gpencil_create_batches(cache);
1522 DRW_gpencil_shgroups_create(e_data, vedata, ob, cache, cache_ob);
1524 cache->is_dirty = false;
1527 /* helper for populate a complete grease pencil datablock */
1528 void DRW_gpencil_populate_datablock(
1529 GPENCIL_e_data *e_data, void *vedata,
1531 tGPencilObjectCache *cache_ob)
1533 GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
1534 const DRWContextState *draw_ctx = DRW_context_state_get();
1535 const ViewLayer *view_layer = DEG_get_evaluated_view_layer(draw_ctx->depsgraph);
1536 Scene *scene = draw_ctx->scene;
1538 bGPdata *gpd_eval = (bGPdata *)ob->data;
1539 bGPdata *gpd = (bGPdata *)DEG_get_original_id(&gpd_eval->id);
1541 View3D *v3d = draw_ctx->v3d;
1542 int cfra_eval = (int)DEG_get_ctime(draw_ctx->depsgraph);
1543 ToolSettings *ts = scene->toolsettings;
1545 bGPDframe *derived_gpf = NULL;
1546 const bool main_onion = v3d != NULL ? (v3d->gp_flag & V3D_GP_SHOW_ONION_SKIN) : true;
1547 const bool do_onion = (bool)((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0) &&
1548 main_onion && DRW_gpencil_onion_active(gpd);
1549 const bool overlay = v3d != NULL ? (bool)((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) : true;
1550 const bool time_remap = BKE_gpencil_has_time_modifiers(ob);
1553 bGPDframe *gpf = NULL;
1554 bGPDlayer *gpl_active = BKE_gpencil_layer_getactive(gpd);
1556 /* check if playing animation */
1557 const bool playing = stl->storage->is_playing;
1559 GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra_eval);
1561 /* if object is duplicate, only create shading groups */
1562 if (cache_ob->is_dup_ob) {
1563 DRW_gpencil_shgroups_create(e_data, vedata, ob, cache, cache_ob);
1567 /* calc max size of VBOs */
1568 gpencil_calc_vertex(stl, cache_ob, cache, gpd, cfra_eval);
1570 /* init general modifiers data */
1571 if (!stl->storage->simplify_modif) {
1572 if ((cache->is_dirty) && (ob->greasepencil_modifiers.first)) {
1573 BKE_gpencil_lattice_init(ob);
1576 /* draw normal strokes */
1577 for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1578 /* don't draw layer if hidden */
1579 if (gpl->flag & GP_LAYER_HIDE) {
1583 const bool is_solomode = GPENCIL_PAINT_MODE(gpd) &&
1584 (!playing) && (!stl->storage->is_render) &&
1585 (gpl->flag & GP_LAYER_SOLO_MODE);
1587 /* filter view layer to gp layers in the same view layer (for compo) */
1588 if ((stl->storage->is_render) && (gpl->viewlayername[0] != '\0')) {
1589 if (!STREQ(view_layer->name, gpl->viewlayername)) {
1595 int remap_cfra = cfra_eval;
1596 if ((time_remap) && (!stl->storage->simplify_modif)) {
1597 remap_cfra = BKE_gpencil_time_modifier(
1598 draw_ctx->depsgraph, scene, ob, gpl, cfra_eval,
1599 stl->storage->is_render);
1602 gpf = BKE_gpencil_layer_getframe(gpl, remap_cfra, GP_GETFRAME_USE_PREV);
1606 /* if solo mode, display only frames with keyframe in the current frame */
1607 if ((is_solomode) && (gpf->framenum != remap_cfra)) {
1611 opacity = gpl->opacity;
1612 /* if pose mode, maybe the overlay to fade geometry is enabled */
1613 if ((draw_ctx->obact) && (draw_ctx->object_mode == OB_MODE_POSE) &&
1614 (v3d->overlay.flag & V3D_OVERLAY_BONE_SELECT))
1616 opacity = opacity * v3d->overlay.xray_alpha_bone;
1618 /* fade no active layers */
1619 if ((overlay) && (draw_ctx->object_mode == OB_MODE_PAINT_GPENCIL) &&
1620 (v3d->gp_flag & V3D_GP_FADE_NOACTIVE_LAYERS) &&
1621 (draw_ctx->obact) && (draw_ctx->obact == ob) &&
1622 (gpl != gpl_active))
1624 opacity = opacity * v3d->overlay.gpencil_fade_layer;
1627 /* create derived frames array data or expand */
1628 int derived_idx = BLI_findindex(&gpd->layers, gpl);
1629 derived_gpf = &cache->derived_array[derived_idx];
1631 /* if no derived frame or dirty cache, create a new one */
1632 if ((derived_gpf == NULL) || (cache->is_dirty)) {
1633 if (derived_gpf != NULL) {
1634 /* first clear temp data */
1635 BKE_gpencil_free_frame_runtime_data(derived_gpf);
1637 /* create new data (do not assign new memory)*/
1638 gpencil_copy_frame(gpf, derived_gpf);
1641 /* draw onion skins */
1642 if (!ID_IS_LINKED(&gpd->id)) {
1643 if ((do_onion) && (gpl->onion_flag & GP_LAYER_ONIONSKIN) &&
1644 ((!playing) || (gpd->onion_flag & GP_ONION_GHOST_ALWAYS)) &&
1645 (!cache_ob->is_dup_ob) && (gpd->id.us <= 1))
1647 if (((!stl->storage->is_render) && (overlay)) ||
1648 ((stl->storage->is_render) && (gpd->onion_flag & GP_ONION_GHOST_ALWAYS)))
1650 gpencil_draw_onionskins(cache, e_data, vedata, ob, gpd, gpl, gpf);
1654 /* draw normal strokes */
1655 gpencil_draw_strokes(
1656 cache, e_data, vedata, ts, ob, gpd, gpl, gpf, derived_gpf,
1657 opacity, gpl->tintcolor, false, cache_ob);
1660 /* clear any lattice data */
1661 if ((cache->is_dirty) && (ob->greasepencil_modifiers.first)) {
1662 BKE_gpencil_lattice_clear(ob);
1665 /* create batchs and shading groups */
1666 DRW_gpencil_create_batches(cache);
1667 DRW_gpencil_shgroups_create(e_data, vedata, ob, cache, cache_ob);
1669 cache->is_dirty = false;
1672 void DRW_gpencil_populate_particles(GPENCIL_e_data *e_data, void *vedata)
1674 GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
1677 for (int i = 0; i < stl->g_data->gp_cache_used; i++) {
1678 tGPencilObjectCache *cache_ob = &stl->g_data->gp_object_cache[i];
1679 Object *ob = cache_ob->ob;
1680 if (cache_ob->is_dup_ob) {
1681 GpencilBatchCache *cache = ob->runtime.gpencil_cache;
1682 if (cache != NULL) {
1683 DRW_gpencil_shgroups_create(e_data, vedata, ob, cache, cache_ob);