Blender  V3.3
gpencil_shader_fx.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2017 Blender Foundation. */
3 
7 #include "DNA_camera_types.h"
8 #include "DNA_gpencil_types.h"
9 #include "DNA_shader_fx_types.h"
10 #include "DNA_view3d_types.h"
11 
12 #include "BKE_gpencil.h"
13 
14 #include "BLI_link_utils.h"
15 #include "BLI_memblock.h"
16 
17 #include "DRW_render.h"
18 
19 #include "BKE_camera.h"
20 
21 #include "gpencil_engine.h"
22 
23 /* verify if this fx is active */
24 static bool effect_is_active(bGPdata *gpd, ShaderFxData *fx, bool is_viewport)
25 {
26  if (fx == NULL) {
27  return false;
28  }
29 
30  if (gpd == NULL) {
31  return false;
32  }
33 
34  bool is_edit = GPENCIL_ANY_EDIT_MODE(gpd);
35  if (((fx->mode & eShaderFxMode_Editmode) == 0) && (is_edit) && (is_viewport)) {
36  return false;
37  }
38 
39  if (((fx->mode & eShaderFxMode_Realtime) && (is_viewport == true)) ||
40  ((fx->mode & eShaderFxMode_Render) && (is_viewport == false))) {
41  return true;
42  }
43 
44  return false;
45 }
46 
47 typedef struct gpIterVfxData {
57 
58 static DRWShadingGroup *gpencil_vfx_pass_create(const char *name,
60  gpIterVfxData *iter,
61  GPUShader *sh)
62 {
63  DRWPass *pass = DRW_pass_create(name, state);
65  DRW_shgroup_uniform_texture_ref(grp, "colorBuf", iter->source_color_tx);
66  DRW_shgroup_uniform_texture_ref(grp, "revealBuf", iter->source_reveal_tx);
67 
68  GPENCIL_tVfx *tgp_vfx = BLI_memblock_alloc(iter->pd->gp_vfx_pool);
69  tgp_vfx->target_fb = iter->target_fb;
70  tgp_vfx->vfx_ps = pass;
71 
72  SWAP(GPUFrameBuffer **, iter->target_fb, iter->source_fb);
75 
76  BLI_LINKS_APPEND(&iter->tgp_ob->vfx, tgp_vfx);
77 
78  return grp;
79 }
80 
82 {
83  if ((fx->samples == 0.0f) || (fx->radius[0] == 0.0f && fx->radius[1] == 0.0f)) {
84  return;
85  }
86 
87  if ((fx->flag & FX_BLUR_DOF_MODE) && iter->pd->camera == NULL) {
88  /* No blur outside camera view (or when DOF is disabled on the camera). */
89  return;
90  }
91 
92  DRWShadingGroup *grp;
93  const float s = sin(fx->rotation);
94  const float c = cos(fx->rotation);
95 
96  float winmat[4][4], persmat[4][4];
97  float blur_size[2] = {fx->radius[0], fx->radius[1]};
98  DRW_view_persmat_get(NULL, persmat, false);
99  const float w = fabsf(mul_project_m4_v3_zfac(persmat, ob->obmat[3]));
100 
101  if ((fx->flag & FX_BLUR_DOF_MODE)) {
102  /* Compute circle of confusion size. */
103  float coc = (iter->pd->dof_params[0] / -w) - iter->pd->dof_params[1];
104  copy_v2_fl(blur_size, fabsf(coc));
105  }
106  else {
107  /* Modify by distance to camera and object scale. */
108  DRW_view_winmat_get(NULL, winmat, false);
109  const float *vp_size = DRW_viewport_size_get();
110  float world_pixel_scale = 1.0f / GPENCIL_PIXEL_FACTOR;
111  float scale = mat4_to_scale(ob->obmat);
112  float distance_factor = world_pixel_scale * scale * winmat[1][1] * vp_size[1] / w;
113  mul_v2_fl(blur_size, distance_factor);
114  }
115 
117 
119  if (blur_size[0] > 0.0f) {
120  grp = gpencil_vfx_pass_create("Fx Blur H", state, iter, sh);
121  DRW_shgroup_uniform_vec2_copy(grp, "offset", (float[2]){blur_size[0] * c, blur_size[0] * s});
122  DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, blur_size[0])));
124  }
125  if (blur_size[1] > 0.0f) {
126  grp = gpencil_vfx_pass_create("Fx Blur V", state, iter, sh);
127  DRW_shgroup_uniform_vec2_copy(grp, "offset", (float[2]){-blur_size[1] * s, blur_size[1] * c});
128  DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, blur_size[1])));
130  }
131 }
132 
134 {
135  DRWShadingGroup *grp;
136 
138 
140  grp = gpencil_vfx_pass_create("Fx Colorize", state, iter, sh);
141  DRW_shgroup_uniform_vec3_copy(grp, "lowColor", fx->low_color);
142  DRW_shgroup_uniform_vec3_copy(grp, "highColor", fx->high_color);
143  DRW_shgroup_uniform_float_copy(grp, "factor", fx->factor);
144  DRW_shgroup_uniform_int_copy(grp, "mode", fx->mode);
146 }
147 
149 {
150  DRWShadingGroup *grp;
151 
152  float axis_flip[2];
153  axis_flip[0] = (fx->flag & FX_FLIP_HORIZONTAL) ? -1.0f : 1.0f;
154  axis_flip[1] = (fx->flag & FX_FLIP_VERTICAL) ? -1.0f : 1.0f;
155 
157 
159  grp = gpencil_vfx_pass_create("Fx Flip", state, iter, sh);
160  DRW_shgroup_uniform_vec2_copy(grp, "axisFlip", axis_flip);
161  DRW_shgroup_uniform_vec2_copy(grp, "waveOffset", (float[2]){0.0f, 0.0f});
162  DRW_shgroup_uniform_float_copy(grp, "swirlRadius", 0.0f);
164 }
165 
167 {
168  DRWShadingGroup *grp;
169 
170  float winmat[4][4], persmat[4][4];
171  float offset[2] = {fx->offset[0], fx->offset[1]};
172  float blur_size[2] = {fx->blur[0], fx->blur[1]};
173  DRW_view_winmat_get(NULL, winmat, false);
174  DRW_view_persmat_get(NULL, persmat, false);
175  const float *vp_size = DRW_viewport_size_get();
176  const float *vp_size_inv = DRW_viewport_invert_size_get();
177 
178  const float w = fabsf(mul_project_m4_v3_zfac(persmat, ob->obmat[3]));
179 
180  /* Modify by distance to camera and object scale. */
181  float world_pixel_scale = 1.0f / GPENCIL_PIXEL_FACTOR;
182  float scale = mat4_to_scale(ob->obmat);
183  float distance_factor = (world_pixel_scale * scale * winmat[1][1] * vp_size[1]) / w;
184  mul_v2_fl(offset, distance_factor);
185  mul_v2_v2(offset, vp_size_inv);
186  mul_v2_fl(blur_size, distance_factor);
187 
189 
191  grp = gpencil_vfx_pass_create("Fx Rim H", state, iter, sh);
192  DRW_shgroup_uniform_vec2_copy(grp, "blurDir", (float[2]){blur_size[0] * vp_size_inv[0], 0.0f});
193  DRW_shgroup_uniform_vec2_copy(grp, "uvOffset", offset);
194  DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, blur_size[0])));
195  DRW_shgroup_uniform_vec3_copy(grp, "maskColor", fx->mask_rgb);
196  DRW_shgroup_uniform_bool_copy(grp, "isFirstPass", true);
198 
199  switch (fx->mode) {
202  break;
205  break;
208  break;
213  break;
214  }
215 
216  zero_v2(offset);
217 
218  grp = gpencil_vfx_pass_create("Fx Rim V", state, iter, sh);
219  DRW_shgroup_uniform_vec2_copy(grp, "blurDir", (float[2]){0.0f, blur_size[1] * vp_size_inv[1]});
220  DRW_shgroup_uniform_vec2_copy(grp, "uvOffset", offset);
221  DRW_shgroup_uniform_vec3_copy(grp, "rimColor", fx->rim_rgb);
222  DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, blur_size[1])));
223  DRW_shgroup_uniform_int_copy(grp, "blendMode", fx->mode);
224  DRW_shgroup_uniform_bool_copy(grp, "isFirstPass", false);
226 
227  if (fx->mode == eShaderFxRimMode_Overlay) {
228  /* We cannot do custom blending on multi-target frame-buffers.
229  * Workaround by doing 2 passes. */
230  grp = DRW_shgroup_create_sub(grp);
233  DRW_shgroup_uniform_int_copy(grp, "blendMode", 999);
235  }
236 }
237 
239 {
240  DRWShadingGroup *grp;
241 
242  float persmat[4][4], winmat[4][4], ob_center[3], pixsize_uniform[2];
243  DRW_view_winmat_get(NULL, winmat, false);
244  DRW_view_persmat_get(NULL, persmat, false);
245  const float *vp_size = DRW_viewport_size_get();
246  const float *vp_size_inv = DRW_viewport_invert_size_get();
247  float pixel_size[2] = {fx->size[0], fx->size[1]};
248  mul_v2_v2(pixel_size, vp_size_inv);
249 
250  /* Fixed pixelisation center from object center. */
251  const float w = fabsf(mul_project_m4_v3_zfac(persmat, ob->obmat[3]));
252  mul_v3_m4v3(ob_center, persmat, ob->obmat[3]);
253  mul_v3_fl(ob_center, 1.0f / w);
254 
255  const bool use_antialiasing = ((fx->flag & FX_PIXEL_FILTER_NEAREST) == 0);
256 
257  /* Convert to uvs. */
258  mul_v2_fl(ob_center, 0.5f);
259  add_v2_fl(ob_center, 0.5f);
260 
261  /* Modify by distance to camera and object scale. */
262  float world_pixel_scale = 1.0f / GPENCIL_PIXEL_FACTOR;
263  float scale = mat4_to_scale(ob->obmat);
264  mul_v2_fl(pixel_size, (world_pixel_scale * scale * winmat[1][1] * vp_size[1]) / w);
265 
266  /* Center to texel */
267  madd_v2_v2fl(ob_center, pixel_size, -0.5f);
268 
270 
272 
273  /* Only if pixelated effect is bigger than 1px. */
274  if (pixel_size[0] > vp_size_inv[0]) {
275  copy_v2_fl2(pixsize_uniform, pixel_size[0], vp_size_inv[1]);
276  grp = gpencil_vfx_pass_create("Fx Pixelize X", state, iter, sh);
277  DRW_shgroup_uniform_vec2_copy(grp, "targetPixelSize", pixsize_uniform);
278  DRW_shgroup_uniform_vec2_copy(grp, "targetPixelOffset", ob_center);
279  DRW_shgroup_uniform_vec2_copy(grp, "accumOffset", (float[2]){pixel_size[0], 0.0f});
280  int samp_count = (pixel_size[0] / vp_size_inv[0] > 3.0) ? 2 : 1;
281  DRW_shgroup_uniform_int_copy(grp, "sampCount", use_antialiasing ? samp_count : 0);
283  }
284 
285  if (pixel_size[1] > vp_size_inv[1]) {
286  copy_v2_fl2(pixsize_uniform, vp_size_inv[0], pixel_size[1]);
287  grp = gpencil_vfx_pass_create("Fx Pixelize Y", state, iter, sh);
288  DRW_shgroup_uniform_vec2_copy(grp, "targetPixelSize", pixsize_uniform);
289  DRW_shgroup_uniform_vec2_copy(grp, "accumOffset", (float[2]){0.0f, pixel_size[1]});
290  int samp_count = (pixel_size[1] / vp_size_inv[1] > 3.0) ? 2 : 1;
291  DRW_shgroup_uniform_int_copy(grp, "sampCount", use_antialiasing ? samp_count : 0);
293  }
294 }
295 
297 {
298  DRWShadingGroup *grp;
299 
300  const bool use_obj_pivot = (fx->flag & FX_SHADOW_USE_OBJECT) != 0;
301  const bool use_wave = (fx->flag & FX_SHADOW_USE_WAVE) != 0;
302 
303  float uv_mat[4][4], winmat[4][4], persmat[4][4], rot_center[3];
304  float wave_ofs[3], wave_dir[3], wave_phase, blur_dir[2], tmp[2];
305  float offset[2] = {fx->offset[0], fx->offset[1]};
306  float blur_size[2] = {fx->blur[0], fx->blur[1]};
307  DRW_view_winmat_get(NULL, winmat, false);
308  DRW_view_persmat_get(NULL, persmat, false);
309  const float *vp_size = DRW_viewport_size_get();
310  const float *vp_size_inv = DRW_viewport_invert_size_get();
311  const float ratio = vp_size_inv[1] / vp_size_inv[0];
312 
313  copy_v3_v3(rot_center, (use_obj_pivot && fx->object) ? fx->object->obmat[3] : ob->obmat[3]);
314 
315  const float w = fabsf(mul_project_m4_v3_zfac(persmat, rot_center));
316  mul_v3_m4v3(rot_center, persmat, rot_center);
317  mul_v3_fl(rot_center, 1.0f / w);
318 
319  /* Modify by distance to camera and object scale. */
320  float world_pixel_scale = 1.0f / GPENCIL_PIXEL_FACTOR;
321  float scale = mat4_to_scale(ob->obmat);
322  float distance_factor = (world_pixel_scale * scale * winmat[1][1] * vp_size[1]) / w;
323  mul_v2_fl(offset, distance_factor);
324  mul_v2_v2(offset, vp_size_inv);
325  mul_v2_fl(blur_size, distance_factor);
326 
327  rot_center[0] = rot_center[0] * 0.5f + 0.5f;
328  rot_center[1] = rot_center[1] * 0.5f + 0.5f;
329 
330  /* UV transform matrix. (loc, rot, scale) Sent to shader as 2x3 matrix. */
331  unit_m4(uv_mat);
332  translate_m4(uv_mat, rot_center[0], rot_center[1], 0.0f);
333  rescale_m4(uv_mat, (float[3]){1.0f / fx->scale[0], 1.0f / fx->scale[1], 1.0f});
334  translate_m4(uv_mat, -offset[0], -offset[1], 0.0f);
335  rescale_m4(uv_mat, (float[3]){1.0f / ratio, 1.0f, 1.0f});
336  rotate_m4(uv_mat, 'Z', fx->rotation);
337  rescale_m4(uv_mat, (float[3]){ratio, 1.0f, 1.0f});
338  translate_m4(uv_mat, -rot_center[0], -rot_center[1], 0.0f);
339 
340  if (use_wave) {
341  float dir[2];
342  if (fx->orientation == 0) {
343  /* Horizontal */
344  copy_v2_fl2(dir, 1.0f, 0.0f);
345  }
346  else {
347  /* Vertical */
348  copy_v2_fl2(dir, 0.0f, 1.0f);
349  }
350  /* This is applied after rotation. Counter the rotation to keep aligned with global axis. */
351  rotate_v2_v2fl(wave_dir, dir, fx->rotation);
352  /* Rotate 90°. */
353  copy_v2_v2(wave_ofs, wave_dir);
354  SWAP(float, wave_ofs[0], wave_ofs[1]);
355  wave_ofs[1] *= -1.0f;
356  /* Keep world space scaling and aspect ratio. */
357  mul_v2_fl(wave_dir, 1.0f / (max_ff(1e-8f, fx->period) * distance_factor));
358  mul_v2_v2(wave_dir, vp_size);
359  mul_v2_fl(wave_ofs, fx->amplitude * distance_factor);
360  mul_v2_v2(wave_ofs, vp_size_inv);
361  /* Phase start at shadow center. */
362  wave_phase = fx->phase - dot_v2v2(rot_center, wave_dir);
363  }
364  else {
365  zero_v2(wave_dir);
366  zero_v2(wave_ofs);
367  wave_phase = 0.0f;
368  }
369 
371 
372  copy_v2_fl2(blur_dir, blur_size[0] * vp_size_inv[0], 0.0f);
373 
375  grp = gpencil_vfx_pass_create("Fx Shadow H", state, iter, sh);
376  DRW_shgroup_uniform_vec2_copy(grp, "blurDir", blur_dir);
377  DRW_shgroup_uniform_vec2_copy(grp, "waveDir", wave_dir);
378  DRW_shgroup_uniform_vec2_copy(grp, "waveOffset", wave_ofs);
379  DRW_shgroup_uniform_float_copy(grp, "wavePhase", wave_phase);
380  DRW_shgroup_uniform_vec2_copy(grp, "uvRotX", uv_mat[0]);
381  DRW_shgroup_uniform_vec2_copy(grp, "uvRotY", uv_mat[1]);
382  DRW_shgroup_uniform_vec2_copy(grp, "uvOffset", uv_mat[3]);
383  DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, blur_size[0])));
384  DRW_shgroup_uniform_bool_copy(grp, "isFirstPass", true);
386 
387  unit_m4(uv_mat);
388  zero_v2(wave_ofs);
389 
390  /* Reset the `uv_mat` to account for rotation in the Y-axis (Shadow-V parameter). */
391  copy_v2_fl2(tmp, 0.0f, blur_size[1]);
392  rotate_v2_v2fl(blur_dir, tmp, -fx->rotation);
393  mul_v2_v2(blur_dir, vp_size_inv);
394 
396  grp = gpencil_vfx_pass_create("Fx Shadow V", state, iter, sh);
397  DRW_shgroup_uniform_vec4_copy(grp, "shadowColor", fx->shadow_rgba);
398  DRW_shgroup_uniform_vec2_copy(grp, "blurDir", blur_dir);
399  DRW_shgroup_uniform_vec2_copy(grp, "waveOffset", wave_ofs);
400  DRW_shgroup_uniform_vec2_copy(grp, "uvRotX", uv_mat[0]);
401  DRW_shgroup_uniform_vec2_copy(grp, "uvRotY", uv_mat[1]);
402  DRW_shgroup_uniform_vec2_copy(grp, "uvOffset", uv_mat[3]);
403  DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, blur_size[1])));
404  DRW_shgroup_uniform_bool_copy(grp, "isFirstPass", false);
406 }
407 
409 {
410  const bool use_glow_under = (fx->flag & FX_GLOW_USE_ALPHA) != 0;
411  DRWShadingGroup *grp;
412  const float s = sin(fx->rotation);
413  const float c = cos(fx->rotation);
414 
416 
417  float ref_col[4];
418 
419  if (fx->mode == eShaderFxGlowMode_Luminance) {
420  /* Only pass in the first value for luminance. */
421  ref_col[0] = fx->threshold;
422  ref_col[1] = -1.0f;
423  ref_col[2] = -1.0f;
424  ref_col[3] = -1.0f;
425  }
426  else {
427  /* First three values are the RGB for the selected color, last value the threshold. */
428  copy_v3_v3(ref_col, fx->select_color);
429  ref_col[3] = fx->threshold;
430  }
431 
433  grp = gpencil_vfx_pass_create("Fx Glow H", state, iter, sh);
434  DRW_shgroup_uniform_vec2_copy(grp, "offset", (float[2]){fx->blur[0] * c, fx->blur[0] * s});
435  DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, fx->blur[0])));
436  DRW_shgroup_uniform_vec4_copy(grp, "threshold", ref_col);
437  DRW_shgroup_uniform_vec4_copy(grp, "glowColor", fx->glow_color);
438  DRW_shgroup_uniform_bool_copy(grp, "glowUnder", use_glow_under);
439  DRW_shgroup_uniform_bool_copy(grp, "firstPass", true);
441 
443  /* Blending: Force blending. */
444  switch (fx->blend_mode) {
447  break;
448  case eGplBlendMode_Add:
450  break;
453  break;
457  break;
458  }
459 
460  /* Small Hack: We ask for RGBA16F buffer if using use_glow_under to store original
461  * revealage in alpha channel. */
462  if (fx->blend_mode == eGplBlendMode_Subtract || use_glow_under) {
463  /* For this effect to propagate, we need a signed floating point buffer. */
464  iter->pd->use_signed_fb = true;
465  }
466 
467  grp = gpencil_vfx_pass_create("Fx Glow V", state, iter, sh);
468  DRW_shgroup_uniform_vec2_copy(grp, "offset", (float[2]){-fx->blur[1] * s, fx->blur[1] * c});
469  DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, fx->blur[0])));
470  DRW_shgroup_uniform_vec4_copy(grp, "threshold", (float[4]){-1.0f, -1.0f, -1.0f, -1.0});
471  DRW_shgroup_uniform_vec4_copy(grp, "glowColor", (float[4]){1.0f, 1.0f, 1.0f, fx->glow_color[3]});
472  DRW_shgroup_uniform_bool_copy(grp, "firstPass", false);
473  DRW_shgroup_uniform_int_copy(grp, "blendMode", fx->blend_mode);
475 }
476 
478 {
479  DRWShadingGroup *grp;
480 
481  float winmat[4][4], persmat[4][4], wave_center[3];
482  float wave_ofs[3], wave_dir[3], wave_phase;
483  DRW_view_winmat_get(NULL, winmat, false);
484  DRW_view_persmat_get(NULL, persmat, false);
485  const float *vp_size = DRW_viewport_size_get();
486  const float *vp_size_inv = DRW_viewport_invert_size_get();
487 
488  const float w = fabsf(mul_project_m4_v3_zfac(persmat, ob->obmat[3]));
489  mul_v3_m4v3(wave_center, persmat, ob->obmat[3]);
490  mul_v3_fl(wave_center, 1.0f / w);
491 
492  /* Modify by distance to camera and object scale. */
493  float world_pixel_scale = 1.0f / GPENCIL_PIXEL_FACTOR;
494  float scale = mat4_to_scale(ob->obmat);
495  float distance_factor = (world_pixel_scale * scale * winmat[1][1] * vp_size[1]) / w;
496 
497  wave_center[0] = wave_center[0] * 0.5f + 0.5f;
498  wave_center[1] = wave_center[1] * 0.5f + 0.5f;
499 
500  if (fx->orientation == 0) {
501  /* Horizontal */
502  copy_v2_fl2(wave_dir, 1.0f, 0.0f);
503  }
504  else {
505  /* Vertical */
506  copy_v2_fl2(wave_dir, 0.0f, 1.0f);
507  }
508  /* Rotate 90°. */
509  copy_v2_v2(wave_ofs, wave_dir);
510  SWAP(float, wave_ofs[0], wave_ofs[1]);
511  wave_ofs[1] *= -1.0f;
512  /* Keep world space scaling and aspect ratio. */
513  mul_v2_fl(wave_dir, 1.0f / (max_ff(1e-8f, fx->period) * distance_factor));
514  mul_v2_v2(wave_dir, vp_size);
515  mul_v2_fl(wave_ofs, fx->amplitude * distance_factor);
516  mul_v2_v2(wave_ofs, vp_size_inv);
517  /* Phase start at shadow center. */
518  wave_phase = fx->phase - dot_v2v2(wave_center, wave_dir);
519 
521 
523  grp = gpencil_vfx_pass_create("Fx Wave", state, iter, sh);
524  DRW_shgroup_uniform_vec2_copy(grp, "axisFlip", (float[2]){1.0f, 1.0f});
525  DRW_shgroup_uniform_vec2_copy(grp, "waveDir", wave_dir);
526  DRW_shgroup_uniform_vec2_copy(grp, "waveOffset", wave_ofs);
527  DRW_shgroup_uniform_float_copy(grp, "wavePhase", wave_phase);
528  DRW_shgroup_uniform_float_copy(grp, "swirlRadius", 0.0f);
530 }
531 
533 {
534  DRWShadingGroup *grp;
535 
536  if (fx->object == NULL) {
537  return;
538  }
539 
540  float winmat[4][4], persmat[4][4], swirl_center[3];
541  DRW_view_winmat_get(NULL, winmat, false);
542  DRW_view_persmat_get(NULL, persmat, false);
543  const float *vp_size = DRW_viewport_size_get();
544 
545  copy_v3_v3(swirl_center, fx->object->obmat[3]);
546 
547  const float w = fabsf(mul_project_m4_v3_zfac(persmat, swirl_center));
548  mul_v3_m4v3(swirl_center, persmat, swirl_center);
549  mul_v3_fl(swirl_center, 1.0f / w);
550 
551  /* Modify by distance to camera and object scale. */
552  float world_pixel_scale = 1.0f / GPENCIL_PIXEL_FACTOR;
553  float scale = mat4_to_scale(fx->object->obmat);
554  float distance_factor = (world_pixel_scale * scale * winmat[1][1] * vp_size[1]) / w;
555 
556  mul_v2_fl(swirl_center, 0.5f);
557  add_v2_fl(swirl_center, 0.5f);
558  mul_v2_v2(swirl_center, vp_size);
559 
560  float radius = fx->radius * distance_factor;
561  if (radius < 1.0f) {
562  return;
563  }
564 
566 
568  grp = gpencil_vfx_pass_create("Fx Flip", state, iter, sh);
569  DRW_shgroup_uniform_vec2_copy(grp, "axisFlip", (float[2]){1.0f, 1.0f});
570  DRW_shgroup_uniform_vec2_copy(grp, "waveOffset", (float[2]){0.0f, 0.0f});
571  DRW_shgroup_uniform_vec2_copy(grp, "swirlCenter", swirl_center);
572  DRW_shgroup_uniform_float_copy(grp, "swirlAngle", fx->angle);
573  DRW_shgroup_uniform_float_copy(grp, "swirlRadius", radius);
575 }
576 
578 {
579  bGPdata *gpd = (bGPdata *)ob->data;
580  GPENCIL_FramebufferList *fbl = vedata->fbl;
581  GPENCIL_PrivateData *pd = vedata->stl->pd;
582 
583  /* These may not be allocated yet, use address of future pointer. */
584  gpIterVfxData iter = {
585  .pd = pd,
586  .tgp_ob = tgp_ob,
587  .target_fb = &fbl->layer_fb,
588  .source_fb = &fbl->object_fb,
589  .target_color_tx = &pd->color_layer_tx,
590  .source_color_tx = &pd->color_object_tx,
591  .target_reveal_tx = &pd->reveal_layer_tx,
592  .source_reveal_tx = &pd->reveal_object_tx,
593  };
594  /* If simplify enabled, nothing more to do. */
595  if (!pd->simplify_fx) {
596  LISTBASE_FOREACH (ShaderFxData *, fx, &ob->shader_fx) {
597  if (effect_is_active(gpd, fx, pd->is_viewport)) {
598  switch (fx->type) {
599  case eShaderFxType_Blur:
600  gpencil_vfx_blur((BlurShaderFxData *)fx, ob, &iter);
601  break;
603  gpencil_vfx_colorize((ColorizeShaderFxData *)fx, ob, &iter);
604  break;
605  case eShaderFxType_Flip:
606  gpencil_vfx_flip((FlipShaderFxData *)fx, ob, &iter);
607  break;
608  case eShaderFxType_Pixel:
609  gpencil_vfx_pixelize((PixelShaderFxData *)fx, ob, &iter);
610  break;
611  case eShaderFxType_Rim:
612  gpencil_vfx_rim((RimShaderFxData *)fx, ob, &iter);
613  break;
615  gpencil_vfx_shadow((ShadowShaderFxData *)fx, ob, &iter);
616  break;
617  case eShaderFxType_Glow:
618  gpencil_vfx_glow((GlowShaderFxData *)fx, ob, &iter);
619  break;
620  case eShaderFxType_Swirl:
621  gpencil_vfx_swirl((SwirlShaderFxData *)fx, ob, &iter);
622  break;
623  case eShaderFxType_Wave:
624  gpencil_vfx_wave((WaveShaderFxData *)fx, ob, &iter);
625  break;
626  default:
627  break;
628  }
629  }
630  }
631  }
632 
633  if ((!pd->simplify_fx && tgp_ob->vfx.first != NULL) || tgp_ob->do_mat_holdout) {
634  /* We need an extra pass to combine result to main buffer. */
635  iter.target_fb = &fbl->gpencil_fb;
636 
638 
640  DRWShadingGroup *grp = gpencil_vfx_pass_create("GPencil Object Compose", state, &iter, sh);
641  DRW_shgroup_uniform_int_copy(grp, "isFirstPass", true);
643 
644  /* We cannot do custom blending on multi-target frame-buffers.
645  * Workaround by doing 2 passes. */
646  grp = DRW_shgroup_create_sub(grp);
649  DRW_shgroup_uniform_int_copy(grp, "isFirstPass", false);
651 
652  pd->use_object_fb = true;
653  pd->use_layer_fb = true;
654  }
655 }
Camera data-block and utility functions.
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
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:1090
void translate_m4(float mat[4][4], float tx, float ty, float tz)
Definition: math_matrix.c:2318
void rescale_m4(float mat[4][4], const float scale[3])
Definition: math_matrix.c:2362
float mat4_to_scale(const float M[4][4])
Definition: math_matrix.c:2185
void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:739
void rotate_m4(float mat[4][4], char axis, float angle)
Definition: math_matrix.c:2325
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
void rotate_v2_v2fl(float r[2], const float p[2], float angle)
Definition: math_vector.c:765
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:115
#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:298
@ DRW_STATE_BLEND_SUB
Definition: DRW_render.h:334
@ DRW_STATE_BLEND_ADD_FULL
Definition: DRW_render.h:326
@ DRW_STATE_WRITE_COLOR
Definition: DRW_render.h:303
@ DRW_STATE_BLEND_ALPHA_PREMUL
Definition: DRW_render.h:330
@ DRW_STATE_BLEND_MUL
Definition: DRW_render.h:333
struct GPUFrameBuffer GPUFrameBuffer
struct GPUShader GPUShader
Definition: GPU_shader.h:20
struct GPUTexture GPUTexture
Definition: GPU_texture.h:17
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:288
const float * DRW_viewport_invert_size_get(void)
Definition: draw_manager.c:293
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
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
const int state
ccl_gpu_kernel_postfix ccl_global float int int int int sh
#define fabsf(x)
Definition: metal/compat.h:219
static unsigned c
Definition: RandGen.cpp:83
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::@218 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