Blender  V2.93
gpencil_shader_fx.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * Copyright 2017, Blender Foundation.
17  */
18 
22 #include "DNA_camera_types.h"
23 #include "DNA_gpencil_types.h"
24 #include "DNA_shader_fx_types.h"
25 #include "DNA_view3d_types.h"
26 
27 #include "BKE_gpencil.h"
28 
29 #include "BLI_link_utils.h"
30 #include "BLI_memblock.h"
31 
32 #include "DRW_render.h"
33 
34 #include "BKE_camera.h"
35 
36 #include "gpencil_engine.h"
37 
38 /* verify if this fx is active */
39 static bool effect_is_active(bGPdata *gpd, ShaderFxData *fx, bool is_viewport)
40 {
41  if (fx == NULL) {
42  return false;
43  }
44 
45  if (gpd == NULL) {
46  return false;
47  }
48 
49  bool is_edit = GPENCIL_ANY_EDIT_MODE(gpd);
50  if (((fx->mode & eShaderFxMode_Editmode) == 0) && (is_edit) && (is_viewport)) {
51  return false;
52  }
53 
54  if (((fx->mode & eShaderFxMode_Realtime) && (is_viewport == true)) ||
55  ((fx->mode & eShaderFxMode_Render) && (is_viewport == false))) {
56  return true;
57  }
58 
59  return false;
60 }
61 
62 typedef struct gpIterVfxData {
72 
73 static DRWShadingGroup *gpencil_vfx_pass_create(const char *name,
75  gpIterVfxData *iter,
76  GPUShader *sh)
77 {
78  DRWPass *pass = DRW_pass_create(name, state);
79  DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
80  DRW_shgroup_uniform_texture_ref(grp, "colorBuf", iter->source_color_tx);
81  DRW_shgroup_uniform_texture_ref(grp, "revealBuf", iter->source_reveal_tx);
82 
83  GPENCIL_tVfx *tgp_vfx = BLI_memblock_alloc(iter->pd->gp_vfx_pool);
84  tgp_vfx->target_fb = iter->target_fb;
85  tgp_vfx->vfx_ps = pass;
86 
87  SWAP(GPUFrameBuffer **, iter->target_fb, iter->source_fb);
90 
91  BLI_LINKS_APPEND(&iter->tgp_ob->vfx, tgp_vfx);
92 
93  return grp;
94 }
95 
97 {
98  if ((fx->samples == 0.0f) || (fx->radius[0] == 0.0f && fx->radius[1] == 0.0f)) {
99  return;
100  }
101 
102  if ((fx->flag & FX_BLUR_DOF_MODE) && iter->pd->camera == NULL) {
103  /* No blur outside camera view (or when DOF is disabled on the camera). */
104  return;
105  }
106 
107  DRWShadingGroup *grp;
108  const float s = sin(fx->rotation);
109  const float c = cos(fx->rotation);
110 
111  float winmat[4][4], persmat[4][4];
112  float blur_size[2] = {fx->radius[0], fx->radius[1]};
113  DRW_view_persmat_get(NULL, persmat, false);
114  const float w = fabsf(mul_project_m4_v3_zfac(persmat, ob->obmat[3]));
115 
116  if ((fx->flag & FX_BLUR_DOF_MODE)) {
117  /* Compute circle of confusion size. */
118  float coc = (iter->pd->dof_params[0] / -w) - iter->pd->dof_params[1];
119  copy_v2_fl(blur_size, fabsf(coc));
120  }
121  else {
122  /* Modify by distance to camera and object scale. */
123  DRW_view_winmat_get(NULL, winmat, false);
124  const float *vp_size = DRW_viewport_size_get();
125  float world_pixel_scale = 1.0f / GPENCIL_PIXEL_FACTOR;
126  float scale = mat4_to_scale(ob->obmat);
127  float distance_factor = world_pixel_scale * scale * winmat[1][1] * vp_size[1] / w;
128  mul_v2_fl(blur_size, distance_factor);
129  }
130 
132 
134  if (blur_size[0] > 0.0f) {
135  grp = gpencil_vfx_pass_create("Fx Blur H", state, iter, sh);
136  DRW_shgroup_uniform_vec2_copy(grp, "offset", (float[2]){blur_size[0] * c, blur_size[0] * s});
137  DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, blur_size[0])));
139  }
140  if (blur_size[1] > 0.0f) {
141  grp = gpencil_vfx_pass_create("Fx Blur V", state, iter, sh);
142  DRW_shgroup_uniform_vec2_copy(grp, "offset", (float[2]){-blur_size[1] * s, blur_size[1] * c});
143  DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, blur_size[1])));
145  }
146 }
147 
149 {
150  DRWShadingGroup *grp;
151 
153 
155  grp = gpencil_vfx_pass_create("Fx Colorize", state, iter, sh);
156  DRW_shgroup_uniform_vec3_copy(grp, "lowColor", fx->low_color);
157  DRW_shgroup_uniform_vec3_copy(grp, "highColor", fx->high_color);
158  DRW_shgroup_uniform_float_copy(grp, "factor", fx->factor);
159  DRW_shgroup_uniform_int_copy(grp, "mode", fx->mode);
161 }
162 
164 {
165  DRWShadingGroup *grp;
166 
167  float axis_flip[2];
168  axis_flip[0] = (fx->flag & FX_FLIP_HORIZONTAL) ? -1.0f : 1.0f;
169  axis_flip[1] = (fx->flag & FX_FLIP_VERTICAL) ? -1.0f : 1.0f;
170 
172 
174  grp = gpencil_vfx_pass_create("Fx Flip", state, iter, sh);
175  DRW_shgroup_uniform_vec2_copy(grp, "axisFlip", axis_flip);
176  DRW_shgroup_uniform_vec2_copy(grp, "waveOffset", (float[2]){0.0f, 0.0f});
177  DRW_shgroup_uniform_float_copy(grp, "swirlRadius", 0.0f);
179 }
180 
182 {
183  DRWShadingGroup *grp;
184 
185  float winmat[4][4], persmat[4][4];
186  float offset[2] = {fx->offset[0], fx->offset[1]};
187  float blur_size[2] = {fx->blur[0], fx->blur[1]};
188  DRW_view_winmat_get(NULL, winmat, false);
189  DRW_view_persmat_get(NULL, persmat, false);
190  const float *vp_size = DRW_viewport_size_get();
191  const float *vp_size_inv = DRW_viewport_invert_size_get();
192 
193  const float w = fabsf(mul_project_m4_v3_zfac(persmat, ob->obmat[3]));
194 
195  /* Modify by distance to camera and object scale. */
196  float world_pixel_scale = 1.0f / GPENCIL_PIXEL_FACTOR;
197  float scale = mat4_to_scale(ob->obmat);
198  float distance_factor = (world_pixel_scale * scale * winmat[1][1] * vp_size[1]) / w;
199  mul_v2_fl(offset, distance_factor);
200  mul_v2_v2(offset, vp_size_inv);
201  mul_v2_fl(blur_size, distance_factor);
202 
204 
206  grp = gpencil_vfx_pass_create("Fx Rim H", state, iter, sh);
207  DRW_shgroup_uniform_vec2_copy(grp, "blurDir", (float[2]){blur_size[0] * vp_size_inv[0], 0.0f});
208  DRW_shgroup_uniform_vec2_copy(grp, "uvOffset", offset);
209  DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, blur_size[0])));
210  DRW_shgroup_uniform_vec3_copy(grp, "maskColor", fx->mask_rgb);
211  DRW_shgroup_uniform_bool_copy(grp, "isFirstPass", true);
213 
214  switch (fx->mode) {
217  break;
220  break;
223  break;
228  break;
229  }
230 
231  zero_v2(offset);
232 
233  grp = gpencil_vfx_pass_create("Fx Rim V", state, iter, sh);
234  DRW_shgroup_uniform_vec2_copy(grp, "blurDir", (float[2]){0.0f, blur_size[1] * vp_size_inv[1]});
235  DRW_shgroup_uniform_vec2_copy(grp, "uvOffset", offset);
236  DRW_shgroup_uniform_vec3_copy(grp, "rimColor", fx->rim_rgb);
237  DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, blur_size[1])));
238  DRW_shgroup_uniform_int_copy(grp, "blendMode", fx->mode);
239  DRW_shgroup_uniform_bool_copy(grp, "isFirstPass", false);
241 
242  if (fx->mode == eShaderFxRimMode_Overlay) {
243  /* We cannot do custom blending on multi-target frame-buffers.
244  * Workaround by doing 2 passes. */
245  grp = DRW_shgroup_create_sub(grp);
248  DRW_shgroup_uniform_int_copy(grp, "blendMode", 999);
250  }
251 }
252 
254 {
255  DRWShadingGroup *grp;
256 
257  float persmat[4][4], winmat[4][4], ob_center[3], pixsize_uniform[2];
258  DRW_view_winmat_get(NULL, winmat, false);
259  DRW_view_persmat_get(NULL, persmat, false);
260  const float *vp_size = DRW_viewport_size_get();
261  const float *vp_size_inv = DRW_viewport_invert_size_get();
262  float pixel_size[2] = {fx->size[0], fx->size[1]};
263  mul_v2_v2(pixel_size, vp_size_inv);
264 
265  /* Fixed pixelisation center from object center. */
266  const float w = fabsf(mul_project_m4_v3_zfac(persmat, ob->obmat[3]));
267  mul_v3_m4v3(ob_center, persmat, ob->obmat[3]);
268  mul_v3_fl(ob_center, 1.0f / w);
269 
270  const bool use_antialiasing = ((fx->flag & FX_PIXEL_FILTER_NEAREST) == 0);
271 
272  /* Convert to uvs. */
273  mul_v2_fl(ob_center, 0.5f);
274  add_v2_fl(ob_center, 0.5f);
275 
276  /* Modify by distance to camera and object scale. */
277  float world_pixel_scale = 1.0f / GPENCIL_PIXEL_FACTOR;
278  float scale = mat4_to_scale(ob->obmat);
279  mul_v2_fl(pixel_size, (world_pixel_scale * scale * winmat[1][1] * vp_size[1]) / w);
280 
281  /* Center to texel */
282  madd_v2_v2fl(ob_center, pixel_size, -0.5f);
283 
285 
287 
288  /* Only if pixelated effect is bigger than 1px. */
289  if (pixel_size[0] > vp_size_inv[0]) {
290  copy_v2_fl2(pixsize_uniform, pixel_size[0], vp_size_inv[1]);
291  grp = gpencil_vfx_pass_create("Fx Pixelize X", state, iter, sh);
292  DRW_shgroup_uniform_vec2_copy(grp, "targetPixelSize", pixsize_uniform);
293  DRW_shgroup_uniform_vec2_copy(grp, "targetPixelOffset", ob_center);
294  DRW_shgroup_uniform_vec2_copy(grp, "accumOffset", (float[2]){pixel_size[0], 0.0f});
295  int samp_count = (pixel_size[0] / vp_size_inv[0] > 3.0) ? 2 : 1;
296  DRW_shgroup_uniform_int_copy(grp, "sampCount", use_antialiasing ? samp_count : 0);
298  }
299 
300  if (pixel_size[1] > vp_size_inv[1]) {
301  copy_v2_fl2(pixsize_uniform, vp_size_inv[0], pixel_size[1]);
302  grp = gpencil_vfx_pass_create("Fx Pixelize Y", state, iter, sh);
303  DRW_shgroup_uniform_vec2_copy(grp, "targetPixelSize", pixsize_uniform);
304  DRW_shgroup_uniform_vec2_copy(grp, "accumOffset", (float[2]){0.0f, pixel_size[1]});
305  int samp_count = (pixel_size[1] / vp_size_inv[1] > 3.0) ? 2 : 1;
306  DRW_shgroup_uniform_int_copy(grp, "sampCount", use_antialiasing ? samp_count : 0);
308  }
309 }
310 
312 {
313  DRWShadingGroup *grp;
314 
315  const bool use_obj_pivot = (fx->flag & FX_SHADOW_USE_OBJECT) != 0;
316  const bool use_wave = (fx->flag & FX_SHADOW_USE_WAVE) != 0;
317 
318  float uv_mat[4][4], winmat[4][4], persmat[4][4], rot_center[3];
319  float wave_ofs[3], wave_dir[3], wave_phase, blur_dir[2], tmp[2];
320  float offset[2] = {fx->offset[0], fx->offset[1]};
321  float blur_size[2] = {fx->blur[0], fx->blur[1]};
322  DRW_view_winmat_get(NULL, winmat, false);
323  DRW_view_persmat_get(NULL, persmat, false);
324  const float *vp_size = DRW_viewport_size_get();
325  const float *vp_size_inv = DRW_viewport_invert_size_get();
326  const float ratio = vp_size_inv[1] / vp_size_inv[0];
327 
328  copy_v3_v3(rot_center, (use_obj_pivot && fx->object) ? fx->object->obmat[3] : ob->obmat[3]);
329 
330  const float w = fabsf(mul_project_m4_v3_zfac(persmat, rot_center));
331  mul_v3_m4v3(rot_center, persmat, rot_center);
332  mul_v3_fl(rot_center, 1.0f / w);
333 
334  /* Modify by distance to camera and object scale. */
335  float world_pixel_scale = 1.0f / GPENCIL_PIXEL_FACTOR;
336  float scale = mat4_to_scale(ob->obmat);
337  float distance_factor = (world_pixel_scale * scale * winmat[1][1] * vp_size[1]) / w;
338  mul_v2_fl(offset, distance_factor);
339  mul_v2_v2(offset, vp_size_inv);
340  mul_v2_fl(blur_size, distance_factor);
341 
342  rot_center[0] = rot_center[0] * 0.5f + 0.5f;
343  rot_center[1] = rot_center[1] * 0.5f + 0.5f;
344 
345  /* UV transform matrix. (loc, rot, scale) Sent to shader as 2x3 matrix. */
346  unit_m4(uv_mat);
347  translate_m4(uv_mat, rot_center[0], rot_center[1], 0.0f);
348  rescale_m4(uv_mat, (float[3]){1.0f / fx->scale[0], 1.0f / fx->scale[1], 1.0f});
349  translate_m4(uv_mat, -offset[0], -offset[1], 0.0f);
350  rescale_m4(uv_mat, (float[3]){1.0f / ratio, 1.0f, 1.0f});
351  rotate_m4(uv_mat, 'Z', fx->rotation);
352  rescale_m4(uv_mat, (float[3]){ratio, 1.0f, 1.0f});
353  translate_m4(uv_mat, -rot_center[0], -rot_center[1], 0.0f);
354 
355  if (use_wave) {
356  float dir[2];
357  if (fx->orientation == 0) {
358  /* Horizontal */
359  copy_v2_fl2(dir, 1.0f, 0.0f);
360  }
361  else {
362  /* Vertical */
363  copy_v2_fl2(dir, 0.0f, 1.0f);
364  }
365  /* This is applied after rotation. Counter the rotation to keep aligned with global axis. */
366  rotate_v2_v2fl(wave_dir, dir, fx->rotation);
367  /* Rotate 90°. */
368  copy_v2_v2(wave_ofs, wave_dir);
369  SWAP(float, wave_ofs[0], wave_ofs[1]);
370  wave_ofs[1] *= -1.0f;
371  /* Keep world space scaling and aspect ratio. */
372  mul_v2_fl(wave_dir, 1.0f / (max_ff(1e-8f, fx->period) * distance_factor));
373  mul_v2_v2(wave_dir, vp_size);
374  mul_v2_fl(wave_ofs, fx->amplitude * distance_factor);
375  mul_v2_v2(wave_ofs, vp_size_inv);
376  /* Phase start at shadow center. */
377  wave_phase = fx->phase - dot_v2v2(rot_center, wave_dir);
378  }
379  else {
380  zero_v2(wave_dir);
381  zero_v2(wave_ofs);
382  wave_phase = 0.0f;
383  }
384 
386 
387  copy_v2_fl2(blur_dir, blur_size[0] * vp_size_inv[0], 0.0f);
388 
390  grp = gpencil_vfx_pass_create("Fx Shadow H", state, iter, sh);
391  DRW_shgroup_uniform_vec2_copy(grp, "blurDir", blur_dir);
392  DRW_shgroup_uniform_vec2_copy(grp, "waveDir", wave_dir);
393  DRW_shgroup_uniform_vec2_copy(grp, "waveOffset", wave_ofs);
394  DRW_shgroup_uniform_float_copy(grp, "wavePhase", wave_phase);
395  DRW_shgroup_uniform_vec2_copy(grp, "uvRotX", uv_mat[0]);
396  DRW_shgroup_uniform_vec2_copy(grp, "uvRotY", uv_mat[1]);
397  DRW_shgroup_uniform_vec2_copy(grp, "uvOffset", uv_mat[3]);
398  DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, blur_size[0])));
399  DRW_shgroup_uniform_bool_copy(grp, "isFirstPass", true);
401 
402  unit_m4(uv_mat);
403  zero_v2(wave_ofs);
404 
405  /* We reset the uv_mat so we need to account for the rotation in the */
406  copy_v2_fl2(tmp, 0.0f, blur_size[1]);
407  rotate_v2_v2fl(blur_dir, tmp, -fx->rotation);
408  mul_v2_v2(blur_dir, vp_size_inv);
409 
411  grp = gpencil_vfx_pass_create("Fx Shadow V", state, iter, sh);
412  DRW_shgroup_uniform_vec4_copy(grp, "shadowColor", fx->shadow_rgba);
413  DRW_shgroup_uniform_vec2_copy(grp, "blurDir", blur_dir);
414  DRW_shgroup_uniform_vec2_copy(grp, "waveOffset", wave_ofs);
415  DRW_shgroup_uniform_vec2_copy(grp, "uvRotX", uv_mat[0]);
416  DRW_shgroup_uniform_vec2_copy(grp, "uvRotY", uv_mat[1]);
417  DRW_shgroup_uniform_vec2_copy(grp, "uvOffset", uv_mat[3]);
418  DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, blur_size[1])));
419  DRW_shgroup_uniform_bool_copy(grp, "isFirstPass", false);
421 }
422 
424 {
425  const bool use_glow_under = (fx->flag & FX_GLOW_USE_ALPHA) != 0;
426  DRWShadingGroup *grp;
427  const float s = sin(fx->rotation);
428  const float c = cos(fx->rotation);
429 
431 
432  float ref_col[3];
433 
434  if (fx->mode == eShaderFxGlowMode_Luminance) {
435  ref_col[0] = fx->threshold;
436  ref_col[1] = -1.0f;
437  ref_col[2] = -1.0f;
438  }
439  else {
440  copy_v3_v3(ref_col, fx->select_color);
441  }
442 
444  grp = gpencil_vfx_pass_create("Fx Glow H", state, iter, sh);
445  DRW_shgroup_uniform_vec2_copy(grp, "offset", (float[2]){fx->blur[0] * c, fx->blur[0] * s});
446  DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, fx->blur[0])));
447  DRW_shgroup_uniform_vec3_copy(grp, "threshold", ref_col);
448  DRW_shgroup_uniform_vec4_copy(grp, "glowColor", fx->glow_color);
449  DRW_shgroup_uniform_bool_copy(grp, "glowUnder", use_glow_under);
450  DRW_shgroup_uniform_bool_copy(grp, "firstPass", true);
452 
454  /* Blending: Force blending. */
455  switch (fx->blend_mode) {
458  break;
459  case eGplBlendMode_Add:
461  break;
464  break;
468  break;
469  }
470 
471  /* Small Hack: We ask for RGBA16F buffer if using use_glow_under to store original
472  * revealage in alpha channel. */
473  if (fx->blend_mode == eGplBlendMode_Subtract || use_glow_under) {
474  /* For this effect to propagate, we need a signed floating point buffer. */
475  iter->pd->use_signed_fb = true;
476  }
477 
478  grp = gpencil_vfx_pass_create("Fx Glow V", state, iter, sh);
479  DRW_shgroup_uniform_vec2_copy(grp, "offset", (float[2]){-fx->blur[1] * s, fx->blur[1] * c});
480  DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, fx->blur[0])));
481  DRW_shgroup_uniform_vec3_copy(grp, "threshold", (float[3]){-1.0f, -1.0f, -1.0f});
482  DRW_shgroup_uniform_vec4_copy(grp, "glowColor", (float[4]){1.0f, 1.0f, 1.0f, fx->glow_color[3]});
483  DRW_shgroup_uniform_bool_copy(grp, "firstPass", false);
484  DRW_shgroup_uniform_int_copy(grp, "blendMode", fx->blend_mode);
486 }
487 
489 {
490  DRWShadingGroup *grp;
491 
492  float winmat[4][4], persmat[4][4], wave_center[3];
493  float wave_ofs[3], wave_dir[3], wave_phase;
494  DRW_view_winmat_get(NULL, winmat, false);
495  DRW_view_persmat_get(NULL, persmat, false);
496  const float *vp_size = DRW_viewport_size_get();
497  const float *vp_size_inv = DRW_viewport_invert_size_get();
498 
499  const float w = fabsf(mul_project_m4_v3_zfac(persmat, ob->obmat[3]));
500  mul_v3_m4v3(wave_center, persmat, ob->obmat[3]);
501  mul_v3_fl(wave_center, 1.0f / w);
502 
503  /* Modify by distance to camera and object scale. */
504  float world_pixel_scale = 1.0f / GPENCIL_PIXEL_FACTOR;
505  float scale = mat4_to_scale(ob->obmat);
506  float distance_factor = (world_pixel_scale * scale * winmat[1][1] * vp_size[1]) / w;
507 
508  wave_center[0] = wave_center[0] * 0.5f + 0.5f;
509  wave_center[1] = wave_center[1] * 0.5f + 0.5f;
510 
511  if (fx->orientation == 0) {
512  /* Horizontal */
513  copy_v2_fl2(wave_dir, 1.0f, 0.0f);
514  }
515  else {
516  /* Vertical */
517  copy_v2_fl2(wave_dir, 0.0f, 1.0f);
518  }
519  /* Rotate 90°. */
520  copy_v2_v2(wave_ofs, wave_dir);
521  SWAP(float, wave_ofs[0], wave_ofs[1]);
522  wave_ofs[1] *= -1.0f;
523  /* Keep world space scaling and aspect ratio. */
524  mul_v2_fl(wave_dir, 1.0f / (max_ff(1e-8f, fx->period) * distance_factor));
525  mul_v2_v2(wave_dir, vp_size);
526  mul_v2_fl(wave_ofs, fx->amplitude * distance_factor);
527  mul_v2_v2(wave_ofs, vp_size_inv);
528  /* Phase start at shadow center. */
529  wave_phase = fx->phase - dot_v2v2(wave_center, wave_dir);
530 
532 
534  grp = gpencil_vfx_pass_create("Fx Wave", state, iter, sh);
535  DRW_shgroup_uniform_vec2_copy(grp, "axisFlip", (float[2]){1.0f, 1.0f});
536  DRW_shgroup_uniform_vec2_copy(grp, "waveDir", wave_dir);
537  DRW_shgroup_uniform_vec2_copy(grp, "waveOffset", wave_ofs);
538  DRW_shgroup_uniform_float_copy(grp, "wavePhase", wave_phase);
539  DRW_shgroup_uniform_float_copy(grp, "swirlRadius", 0.0f);
541 }
542 
544 {
545  DRWShadingGroup *grp;
546 
547  if (fx->object == NULL) {
548  return;
549  }
550 
551  float winmat[4][4], persmat[4][4], swirl_center[3];
552  DRW_view_winmat_get(NULL, winmat, false);
553  DRW_view_persmat_get(NULL, persmat, false);
554  const float *vp_size = DRW_viewport_size_get();
555 
556  copy_v3_v3(swirl_center, fx->object->obmat[3]);
557 
558  const float w = fabsf(mul_project_m4_v3_zfac(persmat, swirl_center));
559  mul_v3_m4v3(swirl_center, persmat, swirl_center);
560  mul_v3_fl(swirl_center, 1.0f / w);
561 
562  /* Modify by distance to camera and object scale. */
563  float world_pixel_scale = 1.0f / GPENCIL_PIXEL_FACTOR;
564  float scale = mat4_to_scale(fx->object->obmat);
565  float distance_factor = (world_pixel_scale * scale * winmat[1][1] * vp_size[1]) / w;
566 
567  mul_v2_fl(swirl_center, 0.5f);
568  add_v2_fl(swirl_center, 0.5f);
569  mul_v2_v2(swirl_center, vp_size);
570 
571  float radius = fx->radius * distance_factor;
572  if (radius < 1.0f) {
573  return;
574  }
575 
577 
579  grp = gpencil_vfx_pass_create("Fx Flip", state, iter, sh);
580  DRW_shgroup_uniform_vec2_copy(grp, "axisFlip", (float[2]){1.0f, 1.0f});
581  DRW_shgroup_uniform_vec2_copy(grp, "waveOffset", (float[2]){0.0f, 0.0f});
582  DRW_shgroup_uniform_vec2_copy(grp, "swirlCenter", swirl_center);
583  DRW_shgroup_uniform_float_copy(grp, "swirlAngle", fx->angle);
584  DRW_shgroup_uniform_float_copy(grp, "swirlRadius", radius);
586 }
587 
589 {
590  bGPdata *gpd = (bGPdata *)ob->data;
591  GPENCIL_FramebufferList *fbl = vedata->fbl;
592  GPENCIL_PrivateData *pd = vedata->stl->pd;
593 
594  /* These may not be allocated yet, use address of future pointer. */
595  gpIterVfxData iter = {
596  .pd = pd,
597  .tgp_ob = tgp_ob,
598  .target_fb = &fbl->layer_fb,
599  .source_fb = &fbl->object_fb,
600  .target_color_tx = &pd->color_layer_tx,
601  .source_color_tx = &pd->color_object_tx,
602  .target_reveal_tx = &pd->reveal_layer_tx,
603  .source_reveal_tx = &pd->reveal_object_tx,
604  };
605  /* If simplify enabled, nothing more to do. */
606  if (!pd->simplify_fx) {
607  LISTBASE_FOREACH (ShaderFxData *, fx, &ob->shader_fx) {
608  if (effect_is_active(gpd, fx, pd->is_viewport)) {
609  switch (fx->type) {
610  case eShaderFxType_Blur:
611  gpencil_vfx_blur((BlurShaderFxData *)fx, ob, &iter);
612  break;
614  gpencil_vfx_colorize((ColorizeShaderFxData *)fx, ob, &iter);
615  break;
616  case eShaderFxType_Flip:
617  gpencil_vfx_flip((FlipShaderFxData *)fx, ob, &iter);
618  break;
619  case eShaderFxType_Pixel:
620  gpencil_vfx_pixelize((PixelShaderFxData *)fx, ob, &iter);
621  break;
622  case eShaderFxType_Rim:
623  gpencil_vfx_rim((RimShaderFxData *)fx, ob, &iter);
624  break;
626  gpencil_vfx_shadow((ShadowShaderFxData *)fx, ob, &iter);
627  break;
628  case eShaderFxType_Glow:
629  gpencil_vfx_glow((GlowShaderFxData *)fx, ob, &iter);
630  break;
631  case eShaderFxType_Swirl:
632  gpencil_vfx_swirl((SwirlShaderFxData *)fx, ob, &iter);
633  break;
634  case eShaderFxType_Wave:
635  gpencil_vfx_wave((WaveShaderFxData *)fx, ob, &iter);
636  break;
637  default:
638  break;
639  }
640  }
641  }
642  }
643 
644  if ((!pd->simplify_fx && tgp_ob->vfx.first != NULL) || tgp_ob->do_mat_holdout) {
645  /* We need an extra pass to combine result to main buffer. */
646  iter.target_fb = &fbl->gpencil_fb;
647 
649 
651  DRWShadingGroup *grp = gpencil_vfx_pass_create("GPencil Object Compose", state, &iter, sh);
652  DRW_shgroup_uniform_int_copy(grp, "isFirstPass", true);
654 
655  /* We cannot do custom blending on multi-target frame-buffers.
656  * Workaround by doing 2 passes. */
657  grp = DRW_shgroup_create_sub(grp);
660  DRW_shgroup_uniform_int_copy(grp, "isFirstPass", false);
662 
663  pd->use_object_fb = true;
664  pd->use_layer_fb = true;
665  }
666 }
Camera data-block and utility functions.
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
MINLINE float max_ff(float a, float b)
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
void unit_m4(float m[4][4])
Definition: rct.c:1140
void translate_m4(float mat[4][4], float tx, float ty, float tz)
Definition: math_matrix.c:2325
void rescale_m4(float mat[4][4], const float scale[3])
Definition: math_matrix.c:2396
float mat4_to_scale(const float M[4][4])
Definition: math_matrix.c:2196
void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:742
void rotate_m4(float mat[4][4], const char axis, const float angle)
Definition: math_matrix.c:2352
void rotate_v2_v2fl(float r[2], const float p[2], const float angle)
Definition: math_vector.c:914
MINLINE void copy_v2_fl2(float v[2], float x, float y)
MINLINE void madd_v2_v2fl(float r[2], const float a[2], float f)
MINLINE void mul_v2_v2(float r[2], const float a[2])
MINLINE void mul_v2_fl(float r[2], float f)
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void add_v2_fl(float r[2], float f)
MINLINE void zero_v2(float r[2])
MINLINE float mul_project_m4_v3_zfac(const float mat[4][4], const float co[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float dot_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v2_fl(float r[2], float f)
void * BLI_memblock_alloc(BLI_memblock *mblk) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition: BLI_memblock.c:133
#define SWAP(type, a, b)
#define UNUSED(x)
#define GPENCIL_ANY_EDIT_MODE(gpd)
@ eGplBlendMode_Regular
@ eGplBlendMode_Add
@ eGplBlendMode_Multiply
@ eGplBlendMode_Divide
@ eGplBlendMode_Subtract
@ FX_BLUR_DOF_MODE
@ FX_SHADOW_USE_OBJECT
@ FX_SHADOW_USE_WAVE
@ eShaderFxMode_Realtime
@ eShaderFxMode_Editmode
@ eShaderFxMode_Render
@ eShaderFxGlowMode_Luminance
@ eShaderFxRimMode_Multiply
@ eShaderFxRimMode_Add
@ eShaderFxRimMode_Normal
@ eShaderFxRimMode_Overlay
@ eShaderFxRimMode_Subtract
@ eShaderFxRimMode_Divide
@ FX_PIXEL_FILTER_NEAREST
@ FX_FLIP_HORIZONTAL
@ FX_FLIP_VERTICAL
@ FX_GLOW_USE_ALPHA
@ eShaderFxType_Pixel
@ eShaderFxType_Rim
@ eShaderFxType_Swirl
@ eShaderFxType_Glow
@ eShaderFxType_Flip
@ eShaderFxType_Blur
@ eShaderFxType_Shadow
@ eShaderFxType_Colorize
@ eShaderFxType_Wave
DRWState
Definition: DRW_render.h:312
@ DRW_STATE_BLEND_SUB
Definition: DRW_render.h:346
@ DRW_STATE_BLEND_ADD_FULL
Definition: DRW_render.h:338
@ DRW_STATE_WRITE_COLOR
Definition: DRW_render.h:315
@ DRW_STATE_BLEND_ALPHA_PREMUL
Definition: DRW_render.h:342
@ DRW_STATE_BLEND_MUL
Definition: DRW_render.h:345
struct GPUFrameBuffer GPUFrameBuffer
struct GPUShader GPUShader
Definition: GPU_shader.h:33
struct GPUTexture GPUTexture
Definition: GPU_texture.h:33
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
const float * DRW_viewport_size_get(void)
Definition: draw_manager.c:439
const float * DRW_viewport_invert_size_get(void)
Definition: draw_manager.c:444
void DRW_shgroup_uniform_float_copy(DRWShadingGroup *shgroup, const char *name, const float value)
void DRW_view_persmat_get(const DRWView *view, float mat[4][4], bool inverse)
void DRW_shgroup_state_disable(DRWShadingGroup *shgroup, DRWState state)
void DRW_shgroup_state_enable(DRWShadingGroup *shgroup, DRWState state)
void DRW_shgroup_uniform_vec3_copy(DRWShadingGroup *shgroup, const char *name, const float *value)
void DRW_shgroup_call_procedural_triangles(DRWShadingGroup *shgroup, Object *ob, uint tri_count)
void DRW_view_winmat_get(const DRWView *view, float mat[4][4], bool inverse)
void DRW_shgroup_uniform_int_copy(DRWShadingGroup *shgroup, const char *name, const int value)
DRWShadingGroup * DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass)
DRWShadingGroup * DRW_shgroup_create_sub(DRWShadingGroup *shgroup)
void DRW_shgroup_uniform_vec4_copy(DRWShadingGroup *shgroup, const char *name, const float *value)
void DRW_shgroup_uniform_texture_ref(DRWShadingGroup *shgroup, const char *name, GPUTexture **tex)
DRWPass * DRW_pass_create(const char *name, DRWState state)
void DRW_shgroup_uniform_bool_copy(DRWShadingGroup *shgroup, const char *name, const bool value)
void DRW_shgroup_uniform_vec2_copy(DRWShadingGroup *shgroup, const char *name, const float *value)
struct GPUShader * GPENCIL_shader_fx_colorize_get(void)
struct GPUShader * GPENCIL_shader_fx_composite_get(void)
#define GPENCIL_PIXEL_FACTOR
struct GPUShader * GPENCIL_shader_fx_shadow_get(void)
struct GPUShader * GPENCIL_shader_fx_transform_get(void)
struct GPUShader * GPENCIL_shader_fx_rim_get(void)
struct GPUShader * GPENCIL_shader_fx_pixelize_get(void)
struct GPUShader * GPENCIL_shader_fx_blur_get(void)
struct GPUShader * GPENCIL_shader_fx_glow_get(void)
void gpencil_vfx_cache_populate(GPENCIL_Data *vedata, Object *ob, GPENCIL_tObject *tgp_ob)
static void gpencil_vfx_pixelize(PixelShaderFxData *fx, Object *ob, gpIterVfxData *iter)
static void gpencil_vfx_flip(FlipShaderFxData *fx, Object *UNUSED(ob), gpIterVfxData *iter)
static bool effect_is_active(bGPdata *gpd, ShaderFxData *fx, bool is_viewport)
static void gpencil_vfx_shadow(ShadowShaderFxData *fx, Object *ob, gpIterVfxData *iter)
static void gpencil_vfx_rim(RimShaderFxData *fx, Object *ob, gpIterVfxData *iter)
static DRWShadingGroup * gpencil_vfx_pass_create(const char *name, DRWState state, gpIterVfxData *iter, GPUShader *sh)
static void gpencil_vfx_wave(WaveShaderFxData *fx, Object *ob, gpIterVfxData *iter)
static void gpencil_vfx_blur(BlurShaderFxData *fx, Object *ob, gpIterVfxData *iter)
static void gpencil_vfx_glow(GlowShaderFxData *fx, Object *UNUSED(ob), gpIterVfxData *iter)
static void gpencil_vfx_swirl(SwirlShaderFxData *fx, Object *UNUSED(ob), gpIterVfxData *iter)
static void gpencil_vfx_colorize(ColorizeShaderFxData *fx, Object *UNUSED(ob), gpIterVfxData *iter)
struct gpIterVfxData gpIterVfxData
#define fabsf(x)
static ulong state[N]
static unsigned c
Definition: RandGen.cpp:97
INLINE Rall1d< T, V, S > cos(const Rall1d< T, V, S > &arg)
Definition: rall1d.h:319
INLINE Rall1d< T, V, S > sin(const Rall1d< T, V, S > &arg)
Definition: rall1d.h:311
struct GPENCIL_StorageList * stl
struct GPENCIL_FramebufferList * fbl
struct BLI_memblock * gp_vfx_pool
struct GPENCIL_PrivateData * pd
struct GPENCIL_tObject::@210 vfx
GPUFrameBuffer ** target_fb
DRWPass * vfx_ps
float obmat[4][4]
void * data
struct Object * object
struct Object * object
GPUFrameBuffer ** source_fb
GPUTexture ** target_reveal_tx
GPUFrameBuffer ** target_fb
GPUTexture ** source_reveal_tx
GPENCIL_PrivateData * pd
GPUTexture ** source_color_tx
GPUTexture ** target_color_tx
GPENCIL_tObject * tgp_ob