cba5cfccaf66a44f6fdc37bcdf21a6057785c253
[blender.git] / source / blender / draw / engines / gpencil / gpencil_draw_utils.c
1 /*
2  * Copyright 2017, Blender Foundation.
3  *
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.
8  *
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.
13  *
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.
17  *
18  * Contributor(s): Antonio Vazquez
19  *
20  */
21
22 /** \file blender/draw/engines/gpencil/gpencil_draw_utils.c
23  *  \ingroup draw
24  */
25
26 #include "BLI_polyfill_2d.h"
27
28 #include "DRW_engine.h"
29 #include "DRW_render.h"
30
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"
37
38 #include "ED_gpencil.h"
39 #include "ED_view3d.h"
40
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"
45
46  /* If builtin shaders are needed */
47 #include "GPU_shader.h"
48 #include "GPU_texture.h"
49
50 /* For EvaluationContext... */
51 #include "DEG_depsgraph.h"
52 #include "DEG_depsgraph_query.h"
53
54 #include "IMB_imbuf_types.h"
55
56 #include "gpencil_engine.h"
57
58 /* fill type to communicate to shader */
59 #define SOLID 0
60 #define GRADIENT 1
61 #define RADIAL 2
62 #define CHESS 3
63 #define TEXTURE 4
64 #define PATTERN 5
65
66 #define GP_SET_SRC_GPS(src_gps) if (src_gps) src_gps = src_gps->next
67
68 /* Helper for doing all the checks on whether a stroke can be drawn */
69 static bool gpencil_can_draw_stroke(
70         struct MaterialGPencilStyle *gp_style, const bGPDstroke *gps,
71         const bool onion, const bool is_mat_preview)
72 {
73         /* skip stroke if it doesn't have any valid data */
74         if ((gps->points == NULL) || (gps->totpoints < 1) || (gp_style == NULL))
75                 return false;
76
77         /* if mat preview render always visible */
78         if (is_mat_preview) {
79                 return true;
80         }
81
82         /* check if the color is visible */
83         if ((gp_style == NULL) ||
84             (gp_style->flag & GP_STYLE_COLOR_HIDE) ||
85             (onion && (gp_style->flag & GP_STYLE_COLOR_ONIONSKIN)))
86         {
87                 return false;
88         }
89
90         /* stroke can be drawn */
91         return true;
92 }
93
94 /* calc bounding box in 2d using flat projection data */
95 static void gpencil_calc_2d_bounding_box(
96         const float(*points2d)[2], int totpoints, float minv[2], float maxv[2])
97 {
98         minv[0] = points2d[0][0];
99         minv[1] = points2d[0][1];
100         maxv[0] = points2d[0][0];
101         maxv[1] = points2d[0][1];
102
103         for (int i = 1; i < totpoints; i++) {
104                 /* min */
105                 if (points2d[i][0] < minv[0]) {
106                         minv[0] = points2d[i][0];
107                 }
108                 if (points2d[i][1] < minv[1]) {
109                         minv[1] = points2d[i][1];
110                 }
111                 /* max */
112                 if (points2d[i][0] > maxv[0]) {
113                         maxv[0] = points2d[i][0];
114                 }
115                 if (points2d[i][1] > maxv[1]) {
116                         maxv[1] = points2d[i][1];
117                 }
118         }
119         /* use a perfect square */
120         if (maxv[0] > maxv[1]) {
121                 maxv[1] = maxv[0];
122         }
123         else {
124                 maxv[0] = maxv[1];
125         }
126 }
127
128 /* calc texture coordinates using flat projected points */
129 static void gpencil_calc_stroke_fill_uv(
130         const float(*points2d)[2], int totpoints, float minv[2], float maxv[2], float(*r_uv)[2])
131 {
132         float d[2];
133         d[0] = maxv[0] - minv[0];
134         d[1] = maxv[1] - minv[1];
135         for (int i = 0; i < totpoints; i++) {
136                 r_uv[i][0] = (points2d[i][0] - minv[0]) / d[0];
137                 r_uv[i][1] = (points2d[i][1] - minv[1]) / d[1];
138         }
139 }
140
141 /* Get points of stroke always flat to view not affected by camera view or view position */
142 static void gpencil_stroke_2d_flat(const bGPDspoint *points, int totpoints, float(*points2d)[2], int *r_direction)
143 {
144         const bGPDspoint *pt0 = &points[0];
145         const bGPDspoint *pt1 = &points[1];
146         const bGPDspoint *pt3 = &points[(int)(totpoints * 0.75)];
147
148         float locx[3];
149         float locy[3];
150         float loc3[3];
151         float normal[3];
152
153         /* local X axis (p0 -> p1) */
154         sub_v3_v3v3(locx, &pt1->x, &pt0->x);
155
156         /* point vector at 3/4 */
157         sub_v3_v3v3(loc3, &pt3->x, &pt0->x);
158
159         /* vector orthogonal to polygon plane */
160         cross_v3_v3v3(normal, locx, loc3);
161
162         /* local Y axis (cross to normal/x axis) */
163         cross_v3_v3v3(locy, normal, locx);
164
165         /* Normalize vectors */
166         normalize_v3(locx);
167         normalize_v3(locy);
168
169         /* Get all points in local space */
170         for (int i = 0; i < totpoints; i++) {
171                 const bGPDspoint *pt = &points[i];
172                 float loc[3];
173
174                 /* Get local space using first point as origin */
175                 sub_v3_v3v3(loc, &pt->x, &pt0->x);
176
177                 points2d[i][0] = dot_v3v3(loc, locx);
178                 points2d[i][1] = dot_v3v3(loc, locy);
179         }
180
181         /* Concave (-1), Convex (1), or Autodetect (0)? */
182         *r_direction = (int)locy[2];
183 }
184
185 /* Triangulate stroke for high quality fill (this is done only if cache is null or stroke was modified) */
186 void DRW_gpencil_triangulate_stroke_fill(Object *ob, bGPDstroke *gps)
187 {
188         BLI_assert(gps->totpoints >= 3);
189
190         bGPdata *gpd = (bGPdata *)ob->data;
191
192         /* allocate memory for temporary areas */
193         gps->tot_triangles = gps->totpoints - 2;
194         uint(*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * gps->tot_triangles, "GP Stroke temp triangulation");
195         float(*points2d)[2] = MEM_mallocN(sizeof(*points2d) * gps->totpoints, "GP Stroke temp 2d points");
196         float(*uv)[2] = MEM_mallocN(sizeof(*uv) * gps->totpoints, "GP Stroke temp 2d uv data");
197
198         int direction = 0;
199
200         /* convert to 2d and triangulate */
201         gpencil_stroke_2d_flat(gps->points, gps->totpoints, points2d, &direction);
202         BLI_polyfill_calc(points2d, (uint)gps->totpoints, direction, tmp_triangles);
203
204         /* calc texture coordinates automatically */
205         float minv[2];
206         float maxv[2];
207         /* first needs bounding box data */
208         if (gpd->flag & GP_DATA_UV_ADAPTATIVE) {
209                 gpencil_calc_2d_bounding_box(points2d, gps->totpoints, minv, maxv);
210         }
211         else {
212                 ARRAY_SET_ITEMS(minv, -1.0f, -1.0f);
213                 ARRAY_SET_ITEMS(maxv, 1.0f, 1.0f);
214         }
215
216         /* calc uv data */
217         gpencil_calc_stroke_fill_uv(points2d, gps->totpoints, minv, maxv, uv);
218
219         /* Number of triangles */
220         gps->tot_triangles = gps->totpoints - 2;
221         /* save triangulation data in stroke cache */
222         if (gps->tot_triangles > 0) {
223                 if (gps->triangles == NULL) {
224                         gps->triangles = MEM_callocN(sizeof(*gps->triangles) * gps->tot_triangles, "GP Stroke triangulation");
225                 }
226                 else {
227                         gps->triangles = MEM_recallocN(gps->triangles, sizeof(*gps->triangles) * gps->tot_triangles);
228                 }
229
230                 for (int i = 0; i < gps->tot_triangles; i++) {
231                         bGPDtriangle *stroke_triangle = &gps->triangles[i];
232                         memcpy(gps->triangles[i].verts, tmp_triangles[i], sizeof(uint[3]));
233                         /* copy texture coordinates */
234                         copy_v2_v2(stroke_triangle->uv[0], uv[tmp_triangles[i][0]]);
235                         copy_v2_v2(stroke_triangle->uv[1], uv[tmp_triangles[i][1]]);
236                         copy_v2_v2(stroke_triangle->uv[2], uv[tmp_triangles[i][2]]);
237                 }
238         }
239         else {
240                 /* No triangles needed - Free anything allocated previously */
241                 if (gps->triangles)
242                         MEM_freeN(gps->triangles);
243
244                 gps->triangles = NULL;
245         }
246
247         /* disable recalculation flag */
248         if (gps->flag & GP_STROKE_RECALC_CACHES) {
249                 gps->flag &= ~GP_STROKE_RECALC_CACHES;
250         }
251
252         /* clear memory */
253         MEM_SAFE_FREE(tmp_triangles);
254         MEM_SAFE_FREE(points2d);
255         MEM_SAFE_FREE(uv);
256 }
257
258 /* recalc the internal geometry caches for fill and uvs */
259 static void DRW_gpencil_recalc_geometry_caches(Object *ob, MaterialGPencilStyle *gp_style, bGPDstroke *gps)
260 {
261         if (gps->flag & GP_STROKE_RECALC_CACHES) {
262                 /* Calculate triangles cache for filling area (must be done only after changes) */
263                 if ((gps->tot_triangles == 0) || (gps->triangles == NULL)) {
264                         if ((gps->totpoints > 2) &&
265                             ((gp_style->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) || (gp_style->fill_style > 0)))
266                         {
267                                 DRW_gpencil_triangulate_stroke_fill(ob, gps);
268                         }
269                 }
270
271                 /* calc uv data along the stroke */
272                 ED_gpencil_calc_stroke_uv(ob, gps);
273
274                 /* clear flag */
275                 gps->flag &= ~GP_STROKE_RECALC_CACHES;
276         }
277 }
278
279 /* create shading group for filling */
280 static DRWShadingGroup *DRW_gpencil_shgroup_fill_create(
281         GPENCIL_e_data *e_data, GPENCIL_Data *vedata, DRWPass *pass,
282         GPUShader *shader, bGPdata *gpd, bGPDlayer *gpl,
283         MaterialGPencilStyle *gp_style, int id)
284 {
285         GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
286
287         /* e_data.gpencil_fill_sh */
288         DRWShadingGroup *grp = DRW_shgroup_create(shader, pass);
289
290         DRW_shgroup_uniform_vec4(grp, "color2", gp_style->mix_rgba, 1);
291
292         /* set style type */
293         switch (gp_style->fill_style) {
294                 case GP_STYLE_FILL_STYLE_SOLID:
295                         stl->shgroups[id].fill_style = SOLID;
296                         break;
297                 case GP_STYLE_FILL_STYLE_GRADIENT:
298                         if (gp_style->gradient_type == GP_STYLE_GRADIENT_LINEAR) {
299                                 stl->shgroups[id].fill_style = GRADIENT;
300                         }
301                         else {
302                                 stl->shgroups[id].fill_style = RADIAL;
303                         }
304                         break;
305                 case GP_STYLE_FILL_STYLE_CHESSBOARD:
306                         stl->shgroups[id].fill_style = CHESS;
307                         break;
308                 case GP_STYLE_FILL_STYLE_TEXTURE:
309                         if (gp_style->flag & GP_STYLE_FILL_PATTERN) {
310                                 stl->shgroups[id].fill_style = PATTERN;
311                         }
312                         else {
313                                 stl->shgroups[id].fill_style = TEXTURE;
314                         }
315                         break;
316                 default:
317                         stl->shgroups[id].fill_style = GP_STYLE_FILL_STYLE_SOLID;
318                         break;
319         }
320         DRW_shgroup_uniform_int(grp, "fill_type", &stl->shgroups[id].fill_style, 1);
321
322         DRW_shgroup_uniform_float(grp, "mix_factor", &gp_style->mix_factor, 1);
323
324         DRW_shgroup_uniform_float(grp, "gradient_angle", &gp_style->gradient_angle, 1);
325         DRW_shgroup_uniform_float(grp, "gradient_radius", &gp_style->gradient_radius, 1);
326         DRW_shgroup_uniform_float(grp, "pattern_gridsize", &gp_style->pattern_gridsize, 1);
327         DRW_shgroup_uniform_vec2(grp, "gradient_scale", gp_style->gradient_scale, 1);
328         DRW_shgroup_uniform_vec2(grp, "gradient_shift", gp_style->gradient_shift, 1);
329
330         DRW_shgroup_uniform_float(grp, "texture_angle", &gp_style->texture_angle, 1);
331         DRW_shgroup_uniform_vec2(grp, "texture_scale", gp_style->texture_scale, 1);
332         DRW_shgroup_uniform_vec2(grp, "texture_offset", gp_style->texture_offset, 1);
333         DRW_shgroup_uniform_float(grp, "texture_opacity", &gp_style->texture_opacity, 1);
334         DRW_shgroup_uniform_float(grp, "layer_opacity", &gpl->opacity, 1);
335
336         stl->shgroups[id].texture_mix = gp_style->flag & GP_STYLE_COLOR_TEX_MIX ? 1 : 0;
337         DRW_shgroup_uniform_int(grp, "texture_mix", &stl->shgroups[id].texture_mix, 1);
338
339         stl->shgroups[id].texture_flip = gp_style->flag & GP_STYLE_COLOR_FLIP_FILL ? 1 : 0;
340         DRW_shgroup_uniform_int(grp, "texture_flip", &stl->shgroups[id].texture_flip, 1);
341
342         DRW_shgroup_uniform_int(grp, "xraymode", (const int *) &gpd->xray_mode, 1);
343         /* image texture */
344         if ((gp_style->flag & GP_STYLE_COLOR_TEX_MIX) ||
345             (gp_style->fill_style & GP_STYLE_FILL_STYLE_TEXTURE))
346         {
347                 ImBuf *ibuf;
348                 Image *image = gp_style->ima;
349                 ImageUser iuser = { NULL };
350                 void *lock;
351
352                 iuser.ok = true;
353
354                 ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
355
356                 if (ibuf == NULL || ibuf->rect == NULL) {
357                         BKE_image_release_ibuf(image, ibuf, NULL);
358                 }
359                 else {
360                         GPUTexture *texture = GPU_texture_from_blender(gp_style->ima, &iuser, GL_TEXTURE_2D, true, 0.0);
361                         DRW_shgroup_uniform_texture(grp, "myTexture", texture);
362
363                         stl->shgroups[id].texture_clamp = gp_style->flag & GP_STYLE_COLOR_TEX_CLAMP ? 1 : 0;
364                         DRW_shgroup_uniform_int(grp, "texture_clamp", &stl->shgroups[id].texture_clamp, 1);
365
366                         BKE_image_release_ibuf(image, ibuf, NULL);
367                 }
368         }
369         else {
370                 /* if no texture defined, need a blank texture to avoid errors in draw manager */
371                 DRW_shgroup_uniform_texture(grp, "myTexture", e_data->gpencil_blank_texture);
372                 stl->shgroups[id].texture_clamp = 0;
373                 DRW_shgroup_uniform_int(grp, "texture_clamp", &stl->shgroups[id].texture_clamp, 1);
374         }
375
376         return grp;
377 }
378
379 /* create shading group for strokes */
380 DRWShadingGroup *DRW_gpencil_shgroup_stroke_create(
381         GPENCIL_e_data *e_data, GPENCIL_Data *vedata, DRWPass *pass, GPUShader *shader, Object *ob,
382         bGPdata *gpd, MaterialGPencilStyle *gp_style, int id, bool onion)
383 {
384         GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
385         const float *viewport_size = DRW_viewport_size_get();
386
387         /* e_data.gpencil_stroke_sh */
388         DRWShadingGroup *grp = DRW_shgroup_create(shader, pass);
389
390         DRW_shgroup_uniform_vec2(grp, "Viewport", viewport_size, 1);
391
392         DRW_shgroup_uniform_float(grp, "pixsize", stl->storage->pixsize, 1);
393
394         /* avoid wrong values */
395         if ((gpd) && (gpd->pixfactor == 0)) {
396                 gpd->pixfactor = GP_DEFAULT_PIX_FACTOR;
397         }
398
399         /* object scale and depth */
400         if ((ob) && (id > -1)) {
401                 stl->shgroups[id].obj_scale = mat4_to_scale(ob->obmat);
402                 DRW_shgroup_uniform_float(grp, "objscale", &stl->shgroups[id].obj_scale, 1);
403                 stl->shgroups[id].keep_size = (int)((gpd) && (gpd->flag & GP_DATA_STROKE_KEEPTHICKNESS));
404                 DRW_shgroup_uniform_int(grp, "keep_size", &stl->shgroups[id].keep_size, 1);
405
406                 stl->shgroups[id].stroke_style = gp_style->stroke_style;
407                 stl->shgroups[id].color_type = GPENCIL_COLOR_SOLID;
408                 if ((gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) && (!onion)) {
409                         stl->shgroups[id].color_type = GPENCIL_COLOR_TEXTURE;
410                         if (gp_style->flag & GP_STYLE_STROKE_PATTERN) {
411                                 stl->shgroups[id].color_type = GPENCIL_COLOR_PATTERN;
412                         }
413                 }
414                 DRW_shgroup_uniform_int(grp, "color_type", &stl->shgroups[id].color_type, 1);
415                 DRW_shgroup_uniform_float(grp, "pixfactor", &gpd->pixfactor, 1);
416         }
417         else {
418                 stl->storage->obj_scale = 1.0f;
419                 stl->storage->keep_size = 0;
420                 stl->storage->pixfactor = GP_DEFAULT_PIX_FACTOR;
421                 DRW_shgroup_uniform_float(grp, "objscale", &stl->storage->obj_scale, 1);
422                 DRW_shgroup_uniform_int(grp, "keep_size", &stl->storage->keep_size, 1);
423                 DRW_shgroup_uniform_int(grp, "color_type", &stl->storage->color_type, 1);
424                 if (gpd) {
425                         DRW_shgroup_uniform_float(grp, "pixfactor", &gpd->pixfactor, 1);
426                 }
427                 else {
428                         DRW_shgroup_uniform_float(grp, "pixfactor", &stl->storage->pixfactor, 1);
429                 }
430         }
431
432         if ((gpd) && (id > -1)) {
433                 DRW_shgroup_uniform_int(grp, "xraymode", (const int *) &gpd->xray_mode, 1);
434         }
435         else {
436                 /* for drawing always on front */
437                 DRW_shgroup_uniform_int(grp, "xraymode", &stl->storage->xray, 1);
438         }
439
440         /* image texture for pattern */
441         if ((gp_style) && (gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) && (!onion)) {
442                 ImBuf *ibuf;
443                 Image *image = gp_style->sima;
444                 ImageUser iuser = { NULL };
445                 void *lock;
446
447                 iuser.ok = true;
448
449                 ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
450
451                 if (ibuf == NULL || ibuf->rect == NULL) {
452                         BKE_image_release_ibuf(image, ibuf, NULL);
453                 }
454                 else {
455                         GPUTexture *texture = GPU_texture_from_blender(gp_style->sima, &iuser, GL_TEXTURE_2D, true, 0.0f);
456                         DRW_shgroup_uniform_texture(grp, "myTexture", texture);
457
458                         BKE_image_release_ibuf(image, ibuf, NULL);
459                 }
460         }
461         else {
462                 /* if no texture defined, need a blank texture to avoid errors in draw manager */
463                 DRW_shgroup_uniform_texture(grp, "myTexture", e_data->gpencil_blank_texture);
464         }
465
466         return grp;
467 }
468
469 /* create shading group for volumetrics */
470 static DRWShadingGroup *DRW_gpencil_shgroup_point_create(
471         GPENCIL_e_data *e_data, GPENCIL_Data *vedata, DRWPass *pass, GPUShader *shader, Object *ob,
472         bGPdata *gpd, MaterialGPencilStyle *gp_style, int id, bool onion)
473 {
474         GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
475         const float *viewport_size = DRW_viewport_size_get();
476
477         /* e_data.gpencil_stroke_sh */
478         DRWShadingGroup *grp = DRW_shgroup_create(shader, pass);
479
480         DRW_shgroup_uniform_vec2(grp, "Viewport", viewport_size, 1);
481         DRW_shgroup_uniform_float(grp, "pixsize", stl->storage->pixsize, 1);
482
483         /* avoid wrong values */
484         if ((gpd) && (gpd->pixfactor == 0)) {
485                 gpd->pixfactor = GP_DEFAULT_PIX_FACTOR;
486         }
487
488         /* object scale and depth */
489         if ((ob) && (id > -1)) {
490                 stl->shgroups[id].obj_scale = mat4_to_scale(ob->obmat);
491                 DRW_shgroup_uniform_float(grp, "objscale", &stl->shgroups[id].obj_scale, 1);
492                 stl->shgroups[id].keep_size = (int)((gpd) && (gpd->flag & GP_DATA_STROKE_KEEPTHICKNESS));
493                 DRW_shgroup_uniform_int(grp, "keep_size", &stl->shgroups[id].keep_size, 1);
494
495                 stl->shgroups[id].mode = gp_style->mode;
496                 stl->shgroups[id].stroke_style = gp_style->stroke_style;
497                 stl->shgroups[id].color_type = GPENCIL_COLOR_SOLID;
498                 if ((gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) && (!onion)) {
499                         stl->shgroups[id].color_type = GPENCIL_COLOR_TEXTURE;
500                         if (gp_style->flag & GP_STYLE_STROKE_PATTERN) {
501                                 stl->shgroups[id].color_type = GPENCIL_COLOR_PATTERN;
502                         }
503                 }
504                 DRW_shgroup_uniform_int(grp, "color_type", &stl->shgroups[id].color_type, 1);
505                 DRW_shgroup_uniform_int(grp, "mode", &stl->shgroups[id].mode, 1);
506                 DRW_shgroup_uniform_float(grp, "pixfactor", &gpd->pixfactor, 1);
507         }
508         else {
509                 stl->storage->obj_scale = 1.0f;
510                 stl->storage->keep_size = 0;
511                 stl->storage->pixfactor = GP_DEFAULT_PIX_FACTOR;
512                 stl->storage->mode = gp_style->mode;
513                 DRW_shgroup_uniform_float(grp, "objscale", &stl->storage->obj_scale, 1);
514                 DRW_shgroup_uniform_int(grp, "keep_size", &stl->storage->keep_size, 1);
515                 DRW_shgroup_uniform_int(grp, "color_type", &stl->storage->color_type, 1);
516                 DRW_shgroup_uniform_int(grp, "mode", &stl->storage->mode, 1);
517                 if (gpd) {
518                         DRW_shgroup_uniform_float(grp, "pixfactor", &gpd->pixfactor, 1);
519                 }
520                 else {
521                         DRW_shgroup_uniform_float(grp, "pixfactor", &stl->storage->pixfactor, 1);
522                 }
523         }
524
525         if (gpd) {
526                 DRW_shgroup_uniform_int(grp, "xraymode", (const int *)&gpd->xray_mode, 1);
527         }
528         else {
529                 /* for drawing always on front */
530                 DRW_shgroup_uniform_int(grp, "xraymode", &stl->storage->xray, 1);
531         }
532
533         /* image texture */
534         if ((gp_style) && (gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) && (!onion)) {
535                 ImBuf *ibuf;
536                 Image *image = gp_style->sima;
537                 ImageUser iuser = { NULL };
538                 void *lock;
539
540                 iuser.ok = true;
541
542                 ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
543
544                 if (ibuf == NULL || ibuf->rect == NULL) {
545                         BKE_image_release_ibuf(image, ibuf, NULL);
546                 }
547                 else {
548                         GPUTexture *texture = GPU_texture_from_blender(gp_style->sima, &iuser, GL_TEXTURE_2D, true, 0.0f);
549                         DRW_shgroup_uniform_texture(grp, "myTexture", texture);
550
551                         BKE_image_release_ibuf(image, ibuf, NULL);
552                 }
553         }
554         else {
555                 /* if no texture defined, need a blank texture to avoid errors in draw manager */
556                 DRW_shgroup_uniform_texture(grp, "myTexture", e_data->gpencil_blank_texture);
557         }
558
559         return grp;
560 }
561
562 /* add fill shading group to pass */
563 static void gpencil_add_fill_shgroup(
564         GpencilBatchCache *cache, DRWShadingGroup *fillgrp,
565         Object *ob, bGPDframe *gpf, bGPDstroke *gps,
566         float opacity, const float tintcolor[4], const bool onion, const bool custonion)
567 {
568         MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
569         if (gps->totpoints >= 3) {
570                 float tfill[4];
571                 /* set color using material, tint color and opacity */
572                 interp_v3_v3v3(tfill, gps->runtime.tmp_fill_rgba, tintcolor, tintcolor[3]);
573                 tfill[3] = gps->runtime.tmp_fill_rgba[3] * opacity;
574                 if ((tfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) || (gp_style->fill_style > 0)) {
575                         if (cache->is_dirty) {
576                                 const float *color;
577                                 if (!onion) {
578                                         color = tfill;
579                                 }
580                                 else {
581                                         if (custonion) {
582                                                 color = tintcolor;
583                                         }
584                                         else {
585                                                 ARRAY_SET_ITEMS(tfill, UNPACK3(gps->runtime.tmp_fill_rgba), tintcolor[3]);
586                                                 color = tfill;
587                                         }
588                                 }
589                                 gpencil_batch_cache_check_free_slots(ob);
590                                 cache->batch_fill[cache->cache_idx] = DRW_gpencil_get_fill_geom(ob, gps, color);
591                         }
592
593                         DRW_shgroup_call_add(fillgrp, cache->batch_fill[cache->cache_idx], gpf->runtime.viewmatrix);
594                 }
595         }
596 }
597
598 /* add stroke shading group to pass */
599 static void gpencil_add_stroke_shgroup(GpencilBatchCache *cache, DRWShadingGroup *strokegrp,
600         Object *ob, bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps,
601         const float opacity, const float tintcolor[4], const bool onion,
602         const bool custonion)
603 {
604         float tcolor[4];
605         float ink[4];
606         short sthickness;
607         MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
608
609         /* set color using base color, tint color and opacity */
610         if (cache->is_dirty) {
611                 if (!onion) {
612                         /* if special stroke, use fill color as stroke color */
613                         if (gps->flag & GP_STROKE_NOFILL) {
614                                 interp_v3_v3v3(tcolor, gps->runtime.tmp_fill_rgba, tintcolor, tintcolor[3]);
615                                 tcolor[3] = gps->runtime.tmp_fill_rgba[3] * opacity;
616                         }
617                         else {
618                                 interp_v3_v3v3(tcolor, gps->runtime.tmp_stroke_rgba, tintcolor, tintcolor[3]);
619                                 tcolor[3] = gps->runtime.tmp_stroke_rgba[3] * opacity;
620                         }
621                         copy_v4_v4(ink, tcolor);
622                 }
623                 else {
624                         if (custonion) {
625                                 copy_v4_v4(ink, tintcolor);
626                         }
627                         else {
628                                 ARRAY_SET_ITEMS(tcolor, UNPACK3(gps->runtime.tmp_stroke_rgba), opacity);
629                                 copy_v4_v4(ink, tcolor);
630                         }
631                 }
632
633                 sthickness = gps->thickness + gpl->line_change;
634                 CLAMP_MIN(sthickness, 1);
635                 gpencil_batch_cache_check_free_slots(ob);
636                 if ((gps->totpoints > 1) && (gp_style->mode == GP_STYLE_MODE_LINE)) {
637                         cache->batch_stroke[cache->cache_idx] = DRW_gpencil_get_stroke_geom(gps, sthickness, ink);
638                 }
639                 else {
640                         cache->batch_stroke[cache->cache_idx] = DRW_gpencil_get_point_geom(gps, sthickness, ink);
641                 }
642         }
643         DRW_shgroup_call_add(strokegrp, cache->batch_stroke[cache->cache_idx], gpf->runtime.viewmatrix);
644 }
645
646 /* add edit points shading group to pass */
647 static void gpencil_add_editpoints_shgroup(
648         GPENCIL_StorageList *stl, GpencilBatchCache *cache, ToolSettings *UNUSED(ts), Object *ob,
649         bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps)
650 {
651         const DRWContextState *draw_ctx = DRW_context_state_get();
652         View3D *v3d = draw_ctx->v3d;
653         MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
654
655         /* alpha factor for edit points/line to make them more subtle */
656         float edit_alpha = v3d->vertex_opacity;
657
658         if (GPENCIL_ANY_EDIT_MODE(gpd)) {
659                 Object *obact = DRW_context_state_get()->obact;
660                 if ((!obact) || (obact->type != OB_GPENCIL)) {
661                         return;
662                 }
663                 const bool is_weight_paint = (gpd) && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE);
664
665                 /* line of the original stroke */
666                 if (cache->is_dirty) {
667                         gpencil_batch_cache_check_free_slots(ob);
668                         cache->batch_edlin[cache->cache_idx] = DRW_gpencil_get_edlin_geom(gps, edit_alpha, gpd->flag);
669                 }
670                 if (cache->batch_edlin[cache->cache_idx]) {
671                         if ((obact) && (obact == ob) &&
672                             ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) &&
673                             (v3d->gp_flag & V3D_GP_SHOW_EDIT_LINES))
674                         {
675                                 DRW_shgroup_call_add(
676                                         stl->g_data->shgrps_edit_line,
677                                         cache->batch_edlin[cache->cache_idx],
678                                         gpf->runtime.viewmatrix);
679                         }
680                 }
681                 /* edit points */
682                 if ((gps->flag & GP_STROKE_SELECT) || (is_weight_paint)) {
683                         if ((gpl->flag & GP_LAYER_UNLOCK_COLOR) || ((gp_style->flag & GP_STYLE_COLOR_LOCKED) == 0)) {
684                                 if (cache->is_dirty) {
685                                         gpencil_batch_cache_check_free_slots(ob);
686                                         cache->batch_edit[cache->cache_idx] = DRW_gpencil_get_edit_geom(gps, edit_alpha, gpd->flag);
687                                 }
688                                 if (cache->batch_edit[cache->cache_idx]) {
689                                         if ((obact) && (obact == ob)) {
690                                                 /* edit pass */
691                                                 DRW_shgroup_call_add(
692                                                         stl->g_data->shgrps_edit_point,
693                                                         cache->batch_edit[cache->cache_idx],
694                                                         gpf->runtime.viewmatrix);
695                                         }
696                                 }
697                         }
698                 }
699         }
700 }
701
702 /* function to draw strokes for onion only */
703 static void gpencil_draw_onion_strokes(
704         GpencilBatchCache *cache, GPENCIL_e_data *e_data, void *vedata, Object *ob,
705         bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf,
706         const float opacity, const float tintcolor[4], const bool custonion)
707 {
708         GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
709         GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
710         Depsgraph *depsgraph = DRW_context_state_get()->depsgraph;
711
712         float viewmatrix[4][4];
713
714         /* get parent matrix and save as static data */
715         ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, viewmatrix);
716         copy_m4_m4(gpf->runtime.viewmatrix, viewmatrix);
717
718         for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
719                 MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
720                 copy_v4_v4(gps->runtime.tmp_stroke_rgba, gp_style->stroke_rgba);
721                 copy_v4_v4(gps->runtime.tmp_fill_rgba, gp_style->fill_rgba);
722
723                 int id = stl->storage->shgroup_id;
724                 /* check if stroke can be drawn */
725                 if (gpencil_can_draw_stroke(gp_style, gps, true, false) == false) {
726                         continue;
727                 }
728                 /* limit the number of shading groups */
729                 if (id >= GPENCIL_MAX_SHGROUPS) {
730                         continue;
731                 }
732
733                 stl->shgroups[id].shgrps_fill = NULL;
734                 if ((gps->totpoints > 1) && (gp_style->mode == GP_STYLE_MODE_LINE)) {
735                         stl->shgroups[id].shgrps_stroke = DRW_gpencil_shgroup_stroke_create(
736                                 e_data, vedata, psl->stroke_pass, e_data->gpencil_stroke_sh, ob, gpd, gp_style, id, true);
737                 }
738                 else {
739                         stl->shgroups[id].shgrps_stroke = DRW_gpencil_shgroup_point_create(
740                                 e_data, vedata, psl->stroke_pass, e_data->gpencil_point_sh, ob, gpd, gp_style, id, true);
741                 }
742
743                 /* stroke */
744                 gpencil_add_stroke_shgroup(
745                         cache, stl->shgroups[id].shgrps_stroke, ob, gpl, gpf, gps, opacity, tintcolor, true, custonion);
746
747                 stl->storage->shgroup_id++;
748                 cache->cache_idx++;
749         }
750 }
751
752
753 /* main function to draw strokes */
754 static void gpencil_draw_strokes(
755         GpencilBatchCache *cache, GPENCIL_e_data *e_data, void *vedata, ToolSettings *ts, Object *ob,
756         bGPdata *gpd, bGPDlayer *gpl, bGPDframe *src_gpf, bGPDframe *derived_gpf,
757         const float opacity, const float tintcolor[4],
758         const bool custonion, tGPencilObjectCache *cache_ob)
759 {
760         GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
761         GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
762         const DRWContextState *draw_ctx = DRW_context_state_get();
763         Scene *scene = draw_ctx->scene;
764         View3D *v3d = draw_ctx->v3d;
765         bGPDstroke *gps, *src_gps;
766         DRWShadingGroup *fillgrp;
767         DRWShadingGroup *strokegrp;
768         float viewmatrix[4][4];
769         const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
770         const bool playing = stl->storage->is_playing;
771         const bool is_render = (bool)stl->storage->is_render;
772         const bool is_mat_preview = (bool)stl->storage->is_mat_preview;
773         const bool overlay_multiedit = v3d != NULL ? (v3d->gp_flag & V3D_GP_SHOW_MULTIEDIT_LINES) : true;
774
775         /* Get evaluation context */
776         /* NOTE: We must check if C is valid, otherwise we get crashes when trying to save files
777          * (i.e. the thumbnail offscreen rendering fails)
778          */
779         Depsgraph *depsgraph = DRW_context_state_get()->depsgraph;
780
781         /* get parent matrix and save as static data */
782         ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, viewmatrix);
783         copy_m4_m4(derived_gpf->runtime.viewmatrix, viewmatrix);
784
785         if ((cache_ob != NULL) && (cache_ob->is_dup_ob)) {
786                 copy_m4_m4(derived_gpf->runtime.viewmatrix, cache_ob->obmat);
787         }
788
789         /* apply geometry modifiers */
790         if ((cache->is_dirty) && (ob->greasepencil_modifiers.first) && (!is_multiedit)) {
791                 if (!stl->storage->simplify_modif) {
792                         if (BKE_gpencil_has_geometry_modifiers(ob)) {
793                                 BKE_gpencil_geometry_modifiers(depsgraph, ob, gpl, derived_gpf, stl->storage->is_render);
794                         }
795                 }
796         }
797
798         if (src_gpf) {
799                 src_gps = src_gpf->strokes.first;
800         }
801         else {
802                 src_gps = NULL;
803         }
804
805         for (gps = derived_gpf->strokes.first; gps; gps = gps->next) {
806                 MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
807
808                 /* check if stroke can be drawn */
809                 if (gpencil_can_draw_stroke(gp_style, gps, false, is_mat_preview) == false) {
810                         GP_SET_SRC_GPS(src_gps);
811                         continue;
812                 }
813                 /* limit the number of shading groups */
814                 if (stl->storage->shgroup_id >= GPENCIL_MAX_SHGROUPS) {
815                         GP_SET_SRC_GPS(src_gps);
816                         continue;
817                 }
818
819                 /* be sure recalc all cache in source stroke to avoid recalculation when frame change
820                  * and improve fps */
821                 if (src_gps) {
822                         DRW_gpencil_recalc_geometry_caches(ob, gp_style, src_gps);
823                 }
824
825                 /* if the fill has any value, it's considered a fill and is not drawn if simplify fill is enabled */
826                 if ((stl->storage->simplify_fill) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_REMOVE_FILL_LINE)) {
827                         if ((gp_style->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) ||
828                             (gp_style->fill_style > GP_STYLE_FILL_STYLE_SOLID))
829                         {
830                                 GP_SET_SRC_GPS(src_gps);
831                                 continue;
832                         }
833                 }
834
835                 if ((gpl->actframe->framenum == derived_gpf->framenum) ||
836                     (!is_multiedit) || (overlay_multiedit))
837                 {
838                         int id = stl->storage->shgroup_id;
839                         if (gps->totpoints > 0) {
840                                 if ((gps->totpoints > 2) && (!stl->storage->simplify_fill) &&
841                                     ((gp_style->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) || (gp_style->fill_style > 0)) &&
842                                     ((gps->flag & GP_STROKE_NOFILL) == 0) &&
843                                     (gp_style->flag & GP_STYLE_FILL_SHOW))
844                                 {
845                                         stl->shgroups[id].shgrps_fill = DRW_gpencil_shgroup_fill_create(
846                                                 e_data, vedata, psl->stroke_pass, e_data->gpencil_fill_sh,
847                                                 gpd, gpl, gp_style, id);
848                                 }
849                                 else {
850                                         stl->shgroups[id].shgrps_fill = NULL;
851                                 }
852                                 if ((gp_style->mode == GP_STYLE_MODE_LINE) && (gps->totpoints > 1)) {
853                                         stl->shgroups[id].shgrps_stroke = DRW_gpencil_shgroup_stroke_create(
854                                                 e_data, vedata, psl->stroke_pass, e_data->gpencil_stroke_sh, ob, gpd, gp_style, id, false);
855                                 }
856                                 else {
857                                         stl->shgroups[id].shgrps_stroke = DRW_gpencil_shgroup_point_create(
858                                                 e_data, vedata, psl->stroke_pass, e_data->gpencil_point_sh, ob, gpd, gp_style, id, false);
859                                 }
860                         }
861                         else {
862                                 stl->shgroups[id].shgrps_fill = NULL;
863                                 stl->shgroups[id].shgrps_stroke = NULL;
864                         }
865                         stl->storage->shgroup_id++;
866
867                         fillgrp = stl->shgroups[id].shgrps_fill;
868                         strokegrp = stl->shgroups[id].shgrps_stroke;
869
870                         /* copy color to temp fields to apply temporal changes in the stroke */
871                         copy_v4_v4(gps->runtime.tmp_stroke_rgba, gp_style->stroke_rgba);
872                         copy_v4_v4(gps->runtime.tmp_fill_rgba, gp_style->fill_rgba);
873
874                         /* apply modifiers (only modify geometry, but not create ) */
875                         if ((cache->is_dirty) && (ob->greasepencil_modifiers.first) && (!is_multiedit)) {
876                                 if (!stl->storage->simplify_modif) {
877                                         BKE_gpencil_stroke_modifiers(depsgraph, ob, gpl, derived_gpf, gps, stl->storage->is_render);
878                                 }
879                         }
880
881                         /* fill */
882                         if ((fillgrp) && (!stl->storage->simplify_fill)) {
883                                 gpencil_add_fill_shgroup(
884                                         cache, fillgrp, ob, derived_gpf, gps,
885                                         opacity, tintcolor, false, custonion);
886                         }
887                         /* stroke */
888                         if (strokegrp) {
889                                 const float nop = ((gp_style->flag & GP_STYLE_STROKE_SHOW) == 0) || (gp_style->stroke_rgba[3] < GPENCIL_ALPHA_OPACITY_THRESH) ? 0.0f : opacity;
890                                 gpencil_add_stroke_shgroup(
891                                         cache, strokegrp, ob, gpl, derived_gpf, gps,
892                                         nop, tintcolor, false, custonion);
893                         }
894                 }
895
896                 /* edit points (only in edit mode and not play animation not render) */
897                 if ((draw_ctx->obact == ob) && (src_gps) &&
898                     (!playing) && (!is_render) && (!cache_ob->is_dup_ob))
899                 {
900                         if ((gpl->flag & GP_LAYER_LOCKED) == 0) {
901                                 if (!stl->g_data->shgrps_edit_line) {
902                                         stl->g_data->shgrps_edit_line = DRW_shgroup_create(e_data->gpencil_line_sh, psl->edit_pass);
903                                 }
904                                 if (!stl->g_data->shgrps_edit_point) {
905                                         stl->g_data->shgrps_edit_point = DRW_shgroup_create(e_data->gpencil_edit_point_sh, psl->edit_pass);
906                                         const float *viewport_size = DRW_viewport_size_get();
907                                         DRW_shgroup_uniform_vec2(stl->g_data->shgrps_edit_point, "Viewport", viewport_size, 1);
908                                 }
909
910                                 gpencil_add_editpoints_shgroup(stl, cache, ts, ob, gpd, gpl, derived_gpf, src_gps);
911                         }
912                         else {
913                                 gpencil_batch_cache_check_free_slots(ob);
914                         }
915                 }
916
917                 GP_SET_SRC_GPS(src_gps);
918
919                 cache->cache_idx++;
920         }
921 }
922
923  /* draw stroke in drawing buffer */
924 void DRW_gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, void *vedata, ToolSettings *ts, Object *ob)
925 {
926         GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
927         GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
928         Brush *brush = BKE_paint_brush(&ts->gp_paint->paint);
929         bGPdata *gpd_eval = ob->data;
930         /* need the original to avoid cow overhead while drawing */
931         bGPdata *gpd = (bGPdata *)DEG_get_original_id(&gpd_eval->id);
932
933         MaterialGPencilStyle *gp_style = NULL;
934
935         float obscale = mat4_to_scale(ob->obmat);
936
937         /* use the brush material */
938         Material *ma = BKE_gpencil_get_material_from_brush(brush);
939         if (ma != NULL) {
940                 gp_style = ma->gp_style;
941         }
942         /* this is not common, but avoid any special situations when brush could be without material */
943         if (gp_style == NULL) {
944                 gp_style = BKE_material_gpencil_settings_get(ob, ob->actcol);
945         }
946
947         /* drawing strokes */
948         /* Check if may need to draw the active stroke cache, only if this layer is the active layer
949          * that is being edited. (Stroke buffer is currently stored in gp-data)
950          */
951         if (ED_gpencil_session_active() && (gpd->runtime.sbuffer_size > 0)) {
952                 if ((gpd->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0) {
953                         /* It should also be noted that sbuffer contains temporary point types
954                          * i.e. tGPspoints NOT bGPDspoints
955                          */
956                         short lthick = brush->size * obscale;
957                         /* if only one point, don't need to draw buffer because the user has no time to see it */
958                         if (gpd->runtime.sbuffer_size > 1) {
959                                 if ((gp_style) && (gp_style->mode == GP_STYLE_MODE_LINE)) {
960                                         stl->g_data->shgrps_drawing_stroke = DRW_gpencil_shgroup_stroke_create(
961                                                 e_data, vedata, psl->drawing_pass, e_data->gpencil_stroke_sh, NULL, gpd, gp_style, -1, false);
962                                 }
963                                 else {
964                                         stl->g_data->shgrps_drawing_stroke = DRW_gpencil_shgroup_point_create(
965                                                 e_data, vedata, psl->drawing_pass, e_data->gpencil_point_sh, NULL, gpd, gp_style, -1, false);
966                                 }
967
968                                 /* clean previous version of the batch */
969                                 if (stl->storage->buffer_stroke) {
970                                         GPU_BATCH_DISCARD_SAFE(e_data->batch_buffer_stroke);
971                                         MEM_SAFE_FREE(e_data->batch_buffer_stroke);
972                                         stl->storage->buffer_stroke = false;
973                                 }
974
975                                 /* use unit matrix because the buffer is in screen space and does not need conversion */
976                                 if (gpd->runtime.mode == GP_STYLE_MODE_LINE) {
977                                         e_data->batch_buffer_stroke = DRW_gpencil_get_buffer_stroke_geom(
978                                                 gpd, lthick);
979                                 }
980                                 else {
981                                         e_data->batch_buffer_stroke = DRW_gpencil_get_buffer_point_geom(
982                                                 gpd, lthick);
983                                 }
984
985                                 if (gp_style->flag & GP_STYLE_STROKE_SHOW) {
986                                         DRW_shgroup_call_add(
987                                                 stl->g_data->shgrps_drawing_stroke,
988                                                 e_data->batch_buffer_stroke,
989                                                 stl->storage->unit_matrix);
990                                 }
991
992                                 if ((gpd->runtime.sbuffer_size >= 3) &&
993                                     (gpd->runtime.sfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) &&
994                                     ((gpd->runtime.sbuffer_sflag & GP_STROKE_NOFILL) == 0) &&
995                                     ((brush->gpencil_settings->flag & GP_BRUSH_DISSABLE_LASSO) == 0) &&
996                                     (gp_style->flag & GP_STYLE_FILL_SHOW))
997                                 {
998                                         /* if not solid, fill is simulated with solid color */
999                                         if (gpd->runtime.bfill_style > 0) {
1000                                                 gpd->runtime.sfill[3] = 0.5f;
1001                                         }
1002                                         stl->g_data->shgrps_drawing_fill = DRW_shgroup_create(
1003                                                 e_data->gpencil_drawing_fill_sh, psl->drawing_pass);
1004
1005                                         /* clean previous version of the batch */
1006                                         if (stl->storage->buffer_fill) {
1007                                                 GPU_BATCH_DISCARD_SAFE(e_data->batch_buffer_fill);
1008                                                 MEM_SAFE_FREE(e_data->batch_buffer_fill);
1009                                                 stl->storage->buffer_fill = false;
1010                                         }
1011
1012                                         e_data->batch_buffer_fill = DRW_gpencil_get_buffer_fill_geom(gpd);
1013                                         DRW_shgroup_call_add(
1014                                                 stl->g_data->shgrps_drawing_fill,
1015                                                 e_data->batch_buffer_fill,
1016                                                 stl->storage->unit_matrix);
1017                                         stl->storage->buffer_fill = true;
1018                                 }
1019                                 stl->storage->buffer_stroke = true;
1020                         }
1021                 }
1022         }
1023 }
1024
1025 /* get alpha factor for onion strokes */
1026 static void gpencil_get_onion_alpha(float color[4], bGPdata *gpd)
1027 {
1028 #define MIN_ALPHA_VALUE 0.01f
1029
1030         /* if fade is disabled, opacity is equal in all frames */
1031         if ((gpd->onion_flag & GP_ONION_FADE) == 0) {
1032                 color[3] = gpd->onion_factor;
1033         }
1034         else {
1035                 /* add override opacity factor */
1036                 color[3] += gpd->onion_factor - 0.5f;
1037         }
1038
1039         CLAMP(color[3], MIN_ALPHA_VALUE, 1.0f);
1040 }
1041
1042 /* draw onion-skinning for a layer */
1043 static void gpencil_draw_onionskins(
1044         GpencilBatchCache *cache, GPENCIL_e_data *e_data, void *vedata,
1045         Object *ob, bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf)
1046 {
1047
1048         const float default_color[3] = { UNPACK3(U.gpencil_new_layer_col) };
1049         const float alpha = 1.0f;
1050         float color[4];
1051         int idx;
1052         float fac = 1.0f;
1053         int step = 0;
1054         int mode = 0;
1055         bool colflag = false;
1056         bGPDframe *gpf_loop = NULL;
1057         int last = gpf->framenum;
1058
1059         colflag = (bool)gpd->onion_flag & GP_ONION_GHOST_PREVCOL;
1060
1061
1062         /* -------------------------------
1063          * 1) Draw Previous Frames First
1064          * ------------------------------- */
1065         step = gpd->gstep;
1066         mode = gpd->onion_mode;
1067
1068         if (gpd->onion_flag & GP_ONION_GHOST_PREVCOL) {
1069                 copy_v3_v3(color, gpd->gcolor_prev);
1070         }
1071         else {
1072                 copy_v3_v3(color, default_color);
1073         }
1074
1075         idx = 0;
1076         for (bGPDframe *gf = gpf->prev; gf; gf = gf->prev) {
1077                 /* only selected frames */
1078                 if ((mode == GP_ONION_MODE_SELECTED) && ((gf->flag & GP_FRAME_SELECT) == 0)) {
1079                         continue;
1080                 }
1081                 /* absolute range */
1082                 if (mode == GP_ONION_MODE_ABSOLUTE) {
1083                         if ((gpf->framenum - gf->framenum) > step) {
1084                                 break;
1085                         }
1086                 }
1087                 /* relative range */
1088                 if (mode == GP_ONION_MODE_RELATIVE) {
1089                         idx++;
1090                         if (idx > step) {
1091                                 break;
1092                         }
1093
1094                 }
1095                 /* alpha decreases with distance from curframe index */
1096                 if (mode != GP_ONION_MODE_SELECTED) {
1097                         if (mode == GP_ONION_MODE_ABSOLUTE) {
1098                                 fac = 1.0f - ((float)(gpf->framenum - gf->framenum) / (float)(step + 1));
1099                         }
1100                         else {
1101                                 fac = 1.0f - ((float)idx / (float)(step + 1));
1102                         }
1103                         color[3] = alpha * fac * 0.66f;
1104                 }
1105                 else {
1106                         idx++;
1107                         fac = alpha - ((1.1f - (1.0f / (float)idx)) * 0.66f);
1108                         color[3] = fac;
1109                 }
1110
1111                 /* if loop option, save the frame to use later */
1112                 if ((mode != GP_ONION_MODE_ABSOLUTE) && (gpd->onion_flag & GP_ONION_LOOP)) {
1113                         gpf_loop = gf;
1114                 }
1115
1116                 gpencil_get_onion_alpha(color, gpd);
1117                 gpencil_draw_onion_strokes(cache, e_data, vedata, ob, gpd, gpl, gf, color[3], color, colflag);
1118         }
1119         /* -------------------------------
1120          * 2) Now draw next frames
1121          * ------------------------------- */
1122         step = gpd->gstep_next;
1123         mode = gpd->onion_mode;
1124
1125         if (gpd->onion_flag & GP_ONION_GHOST_NEXTCOL) {
1126                 copy_v3_v3(color, gpd->gcolor_next);
1127         }
1128         else {
1129                 copy_v3_v3(color, default_color);
1130         }
1131
1132         idx = 0;
1133         for (bGPDframe *gf = gpf->next; gf; gf = gf->next) {
1134                 /* only selected frames */
1135                 if ((mode == GP_ONION_MODE_SELECTED) && ((gf->flag & GP_FRAME_SELECT) == 0)) {
1136                         continue;
1137                 }
1138                 /* absolute range */
1139                 if (mode == GP_ONION_MODE_ABSOLUTE) {
1140                         if ((gf->framenum - gpf->framenum) > step) {
1141                                 break;
1142                         }
1143                 }
1144                 /* relative range */
1145                 if (mode == GP_ONION_MODE_RELATIVE) {
1146                         idx++;
1147                         if (idx > step) {
1148                                 break;
1149                         }
1150
1151                 }
1152                 /* alpha decreases with distance from curframe index */
1153                 if (mode != GP_ONION_MODE_SELECTED) {
1154                         if (mode == GP_ONION_MODE_ABSOLUTE) {
1155                                 fac = 1.0f - ((float)(gf->framenum - gpf->framenum) / (float)(step + 1));
1156                         }
1157                         else {
1158                                 fac = 1.0f - ((float)idx / (float)(step + 1));
1159                         }
1160                         color[3] = alpha * fac * 0.66f;
1161                 }
1162                 else {
1163                         idx++;
1164                         fac = alpha - ((1.1f - (1.0f / (float)idx)) * 0.66f);
1165                         color[3] = fac;
1166                 }
1167
1168                 gpencil_get_onion_alpha(color, gpd);
1169                 gpencil_draw_onion_strokes(cache, e_data, vedata, ob, gpd, gpl, gf, color[3], color, colflag);
1170                 if (last < gf->framenum) {
1171                         last = gf->framenum;
1172                 }
1173         }
1174
1175         /* Draw first frame in blue for loop mode */
1176         if ((gpd->onion_flag & GP_ONION_LOOP) && (gpf_loop != NULL)) {
1177                 if ((last == gpf->framenum) || (gpf->next == NULL)) {
1178                         gpencil_get_onion_alpha(color, gpd);
1179                         gpencil_draw_onion_strokes(
1180                                 cache, e_data, vedata, ob, gpd, gpl,
1181                                 gpf_loop, color[3], color, colflag);
1182                 }
1183         }
1184 }
1185
1186 /* populate a datablock for multiedit (no onions, no modifiers) */
1187 void DRW_gpencil_populate_multiedit(
1188         GPENCIL_e_data *e_data, void *vedata, Scene *scene, Object *ob,
1189         tGPencilObjectCache *cache_ob)
1190 {
1191         bGPdata *gpd = (bGPdata *)ob->data;
1192         bGPDframe *gpf = NULL;
1193
1194         GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
1195         const DRWContextState *draw_ctx = DRW_context_state_get();
1196         int cfra_eval = (int)DEG_get_ctime(draw_ctx->depsgraph);
1197         GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra_eval);
1198         ToolSettings *ts = scene->toolsettings;
1199         cache->cache_idx = 0;
1200
1201         /* check if playing animation */
1202         bool playing = stl->storage->is_playing;
1203
1204         /* draw strokes */
1205         for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1206                 /* don't draw layer if hidden */
1207                 if (gpl->flag & GP_LAYER_HIDE)
1208                         continue;
1209
1210                 /* list of frames to draw */
1211                 if (!playing) {
1212                         for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
1213                                 if ((gpf == gpl->actframe) || (gpf->flag & GP_FRAME_SELECT)) {
1214                                         gpencil_draw_strokes(
1215                                                 cache, e_data, vedata, ts, ob, gpd, gpl, gpf, gpf,
1216                                                 gpl->opacity, gpl->tintcolor, false, cache_ob);
1217                                 }
1218                         }
1219                 }
1220                 else {
1221                         gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_USE_PREV);
1222                         if (gpf) {
1223                                 gpencil_draw_strokes(
1224                                         cache, e_data, vedata, ts, ob, gpd, gpl, gpf, gpf,
1225                                         gpl->opacity, gpl->tintcolor, false, cache_ob);
1226                         }
1227                 }
1228
1229         }
1230
1231         cache->is_dirty = false;
1232 }
1233
1234 static void gpencil_copy_frame(bGPDframe *gpf, bGPDframe *derived_gpf)
1235 {
1236         derived_gpf->prev = gpf->prev;
1237         derived_gpf->next = gpf->next;
1238         derived_gpf->framenum = gpf->framenum;
1239         derived_gpf->flag = gpf->flag;
1240         derived_gpf->key_type = gpf->key_type;
1241         derived_gpf->runtime = gpf->runtime;
1242
1243         /* copy strokes */
1244         BLI_listbase_clear(&derived_gpf->strokes);
1245         for (bGPDstroke *gps_src = gpf->strokes.first; gps_src; gps_src = gps_src->next) {
1246                 /* make copy of source stroke */
1247                 bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps_src);
1248                 BLI_addtail(&derived_gpf->strokes, gps_dst);
1249         }
1250 }
1251
1252 /* helper for populate a complete grease pencil datablock */
1253 void DRW_gpencil_populate_datablock(
1254         GPENCIL_e_data *e_data, void *vedata,
1255         Scene *scene, Object *ob,
1256         tGPencilObjectCache *cache_ob)
1257 {
1258         GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
1259         const DRWContextState *draw_ctx = DRW_context_state_get();
1260         const ViewLayer *view_layer = DEG_get_evaluated_view_layer(draw_ctx->depsgraph);
1261
1262         bGPdata *gpd_eval = (bGPdata *)ob->data;
1263         bGPdata *gpd = (bGPdata *)DEG_get_original_id(&gpd_eval->id);
1264
1265         View3D *v3d = draw_ctx->v3d;
1266         int cfra_eval = (int)DEG_get_ctime(draw_ctx->depsgraph);
1267         ToolSettings *ts = scene->toolsettings;
1268
1269         bGPDframe *derived_gpf = NULL;
1270         const bool main_onion = v3d != NULL ? (v3d->gp_flag & V3D_GP_SHOW_ONION_SKIN) : true;
1271         const bool do_onion = (bool)((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0) && main_onion;
1272         const bool overlay = v3d != NULL ? (bool)((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) : true;
1273         const bool time_remap = BKE_gpencil_has_time_modifiers(ob);
1274
1275         float opacity;
1276         bGPDframe *p = NULL;
1277         bGPDframe *gpf = NULL;
1278         bGPDlayer *gpl_active = BKE_gpencil_layer_getactive(gpd);
1279
1280         /* check if playing animation */
1281         bool playing = stl->storage->is_playing;
1282
1283         GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra_eval);
1284         cache->cache_idx = 0;
1285
1286         /* init general modifiers data */
1287         if (!stl->storage->simplify_modif) {
1288                 if ((cache->is_dirty) && (ob->greasepencil_modifiers.first)) {
1289                         BKE_gpencil_lattice_init(ob);
1290                 }
1291         }
1292         /* draw normal strokes */
1293         for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1294                 /* don't draw layer if hidden */
1295                 if (gpl->flag & GP_LAYER_HIDE)
1296                         continue;
1297
1298                 /* filter view layer to gp layers in the same view layer (for compo) */
1299                 if ((stl->storage->is_render) && (gpl->viewlayername[0] != '\0')) {
1300                         if (!STREQ(view_layer->name, gpl->viewlayername)) {
1301                                 continue;
1302                         }
1303                 }
1304
1305                 if ((!time_remap) || (stl->storage->simplify_modif)) {
1306                         gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_USE_PREV);
1307                 }
1308                 else {
1309                         int remap_cfra = BKE_gpencil_time_modifier(
1310                                 draw_ctx->depsgraph, scene, ob, gpl, cfra_eval,
1311                                 stl->storage->is_render);
1312
1313                         gpf = BKE_gpencil_layer_getframe(gpl, remap_cfra, GP_GETFRAME_USE_PREV);
1314                 }
1315                 if (gpf == NULL)
1316                         continue;
1317
1318                 opacity = gpl->opacity;
1319                 /* if pose mode, maybe the overlay to fade geometry is enabled */
1320                 if ((draw_ctx->obact) && (draw_ctx->object_mode == OB_MODE_POSE) &&
1321                     (v3d->overlay.flag & V3D_OVERLAY_BONE_SELECT))
1322                 {
1323                         opacity = opacity * v3d->overlay.bone_select_alpha;
1324                 }
1325                 /* fade no active layers */
1326                 if ((overlay) && (draw_ctx->object_mode == OB_MODE_GPENCIL_PAINT) &&
1327                     (v3d->gp_flag & V3D_GP_FADE_NOACTIVE_LAYERS) &&
1328                     (draw_ctx->obact) && (draw_ctx->obact == ob) &&
1329                     (gpl != gpl_active))
1330                 {
1331                         opacity = opacity * v3d->overlay.gpencil_fade_layer;
1332                 }
1333
1334                 /* create derived array data or expand */
1335                 if (cache_ob->data_idx + 1 > gpl->runtime.len_derived) {
1336                         if ((gpl->runtime.len_derived == 0) ||
1337                             (gpl->runtime.derived_array == NULL))
1338                         {
1339                                 p = MEM_callocN(sizeof(struct bGPDframe), "bGPDframe array");
1340                                 gpl->runtime.len_derived = 1;
1341                         }
1342                         else {
1343                                 gpl->runtime.len_derived++;
1344                                 p = MEM_recallocN(gpl->runtime.derived_array, sizeof(struct bGPDframe) * gpl->runtime.len_derived);
1345                         }
1346                         gpl->runtime.derived_array = p;
1347
1348                         derived_gpf = &gpl->runtime.derived_array[cache_ob->data_idx];
1349                 }
1350
1351                 derived_gpf = &gpl->runtime.derived_array[cache_ob->data_idx];
1352
1353                 /* if no derived frame or dirty cache, create a new one */
1354                 if ((derived_gpf == NULL) || (cache->is_dirty)) {
1355                         if (derived_gpf != NULL) {
1356                                 /* first clear temp data */
1357                                 BKE_gpencil_free_frame_runtime_data(derived_gpf);
1358                         }
1359                         /* create new data (do not assign new memory)*/
1360                         gpencil_copy_frame(gpf, derived_gpf);
1361                 }
1362
1363                 /* draw onion skins */
1364                 if (!ID_IS_LINKED(&gpd->id)) {
1365                         if ((!cache_ob->is_dup_data) &&
1366                             (gpd->flag & GP_DATA_SHOW_ONIONSKINS) &&
1367                             (do_onion) && (gpl->onion_flag & GP_LAYER_ONIONSKIN) &&
1368                             ((!playing) || (gpd->onion_flag & GP_ONION_GHOST_ALWAYS)) &&
1369                             (!cache_ob->is_dup_ob) && (gpd->id.us <= 1))
1370                         {
1371                                 if (((!stl->storage->is_render) && (overlay)) ||
1372                                     ((stl->storage->is_render) && (gpd->onion_flag & GP_ONION_GHOST_ALWAYS)))
1373                                 {
1374                                         gpencil_draw_onionskins(cache, e_data, vedata, ob, gpd, gpl, gpf);
1375                                 }
1376                         }
1377                 }
1378                 /* draw normal strokes */
1379                 if (!cache_ob->is_dup_ob) {
1380                         /* save batch index */
1381                         gpl->runtime.batch_index = cache->cache_idx;
1382                 }
1383                 else {
1384                         cache->cache_idx = gpl->runtime.batch_index;
1385                 }
1386
1387                 gpencil_draw_strokes(
1388                         cache, e_data, vedata, ts, ob, gpd, gpl, gpf, derived_gpf,
1389                         opacity, gpl->tintcolor, false, cache_ob);
1390
1391         }
1392
1393         /* clear any lattice data */
1394         if ((cache->is_dirty) && (ob->greasepencil_modifiers.first)) {
1395                 BKE_gpencil_lattice_clear(ob);
1396         }
1397
1398         cache->is_dirty = false;
1399 }