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