Blender V4.3
gpencil_shader_fx.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2017 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8#include "DNA_camera_types.h"
10#include "DNA_shader_fx_types.h"
11#include "DNA_view3d_types.h"
12
13#include "BKE_gpencil_legacy.h"
14
15#include "BLI_link_utils.h"
16#include "BLI_memblock.h"
17
18#include "DRW_render.hh"
19
20#include "BKE_camera.h"
21
22#include "gpencil_engine.h"
23
24/* verify if this fx is active */
25static bool effect_is_active(ShaderFxData *fx, bool is_edit, bool is_viewport)
26{
27 if (fx == nullptr) {
28 return false;
29 }
30
31 if (((fx->mode & eShaderFxMode_Editmode) == 0) && (is_edit) && (is_viewport)) {
32 return false;
33 }
34
35 if (((fx->mode & eShaderFxMode_Realtime) && (is_viewport == true)) ||
36 ((fx->mode & eShaderFxMode_Render) && (is_viewport == false)))
37 {
38 return true;
39 }
40
41 return false;
42}
43
47 GPUFrameBuffer **target_fb;
48 GPUFrameBuffer **source_fb;
49 GPUTexture **target_color_tx;
50 GPUTexture **source_color_tx;
51 GPUTexture **target_reveal_tx;
52 GPUTexture **source_reveal_tx;
53};
54
56 const char *name,
58 gpIterVfxData *iter,
59 GPUShader *sh,
61{
62 DRWPass *pass = DRW_pass_create(name, state);
63 DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
66
67 GPENCIL_tVfx *tgp_vfx = static_cast<GPENCIL_tVfx *>(BLI_memblock_alloc(iter->pd->gp_vfx_pool));
68 tgp_vfx->target_fb = iter->target_fb;
69 tgp_vfx->vfx_ps = pass;
70
71 std::swap(iter->target_fb, iter->source_fb);
72 std::swap(iter->target_color_tx, iter->source_color_tx);
73 std::swap(iter->target_reveal_tx, iter->source_reveal_tx);
74
75 BLI_LINKS_APPEND(&iter->tgp_ob->vfx, tgp_vfx);
76
77 return grp;
78}
79
81{
82 if ((fx->samples == 0.0f) || (fx->radius[0] == 0.0f && fx->radius[1] == 0.0f)) {
83 return;
84 }
85
86 if ((fx->flag & FX_BLUR_DOF_MODE) && iter->pd->camera == nullptr) {
87 /* No blur outside camera view (or when DOF is disabled on the camera). */
88 return;
89 }
90
91 DRWShadingGroup *grp;
92 const float s = sin(fx->rotation);
93 const float c = cos(fx->rotation);
94
95 float winmat[4][4], persmat[4][4];
96 float blur_size[2] = {fx->radius[0], fx->radius[1]};
97 DRW_view_persmat_get(nullptr, persmat, false);
98 const float w = fabsf(mul_project_m4_v3_zfac(persmat, ob->object_to_world().location()));
99
100 if (fx->flag & FX_BLUR_DOF_MODE) {
101 /* Compute circle of confusion size. */
102 float coc = (iter->pd->dof_params[0] / -w) - iter->pd->dof_params[1];
103 copy_v2_fl(blur_size, fabsf(coc));
104 }
105 else {
106 /* Modify by distance to camera and object scale. */
107 DRW_view_winmat_get(nullptr, winmat, false);
108 const float *vp_size = DRW_viewport_size_get();
109 float world_pixel_scale = 1.0f / GPENCIL_PIXEL_FACTOR;
110 float scale = mat4_to_scale(ob->object_to_world().ptr());
111 float distance_factor = world_pixel_scale * scale * winmat[1][1] * vp_size[1] / w;
112 mul_v2_fl(blur_size, distance_factor);
113 }
114
116
118 if (blur_size[0] > 0.0f) {
119 grp = gpencil_vfx_pass_create("Fx Blur H", state, iter, sh);
121 grp, "offset", blender::float2{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);
128 grp, "offset", blender::float2{-blur_size[1] * s, blur_size[1] * c});
129 DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, blur_size[1])));
131 }
132}
133
135{
136 DRWShadingGroup *grp;
137
139
141 grp = gpencil_vfx_pass_create("Fx Colorize", state, iter, sh);
142 DRW_shgroup_uniform_vec3_copy(grp, "lowColor", fx->low_color);
143 DRW_shgroup_uniform_vec3_copy(grp, "highColor", fx->high_color);
144 DRW_shgroup_uniform_float_copy(grp, "factor", fx->factor);
145 DRW_shgroup_uniform_int_copy(grp, "mode", fx->mode);
147}
148
149static void gpencil_vfx_flip(FlipShaderFxData *fx, Object * /*ob*/, gpIterVfxData *iter)
150{
151 DRWShadingGroup *grp;
152
153 float axis_flip[2];
154 axis_flip[0] = (fx->flag & FX_FLIP_HORIZONTAL) ? -1.0f : 1.0f;
155 axis_flip[1] = (fx->flag & FX_FLIP_VERTICAL) ? -1.0f : 1.0f;
156
158
160 grp = gpencil_vfx_pass_create("Fx Flip", state, iter, sh);
161 DRW_shgroup_uniform_vec2_copy(grp, "axisFlip", axis_flip);
162 DRW_shgroup_uniform_vec2_copy(grp, "waveOffset", blender::float2{0.0f, 0.0f});
163 DRW_shgroup_uniform_float_copy(grp, "swirlRadius", 0.0f);
165}
166
168{
169 DRWShadingGroup *grp;
170
171 float winmat[4][4], persmat[4][4];
172 float offset[2] = {float(fx->offset[0]), float(fx->offset[1])};
173 float blur_size[2] = {float(fx->blur[0]), float(fx->blur[1])};
174 DRW_view_winmat_get(nullptr, winmat, false);
175 DRW_view_persmat_get(nullptr, persmat, false);
176 const float *vp_size = DRW_viewport_size_get();
177 const float *vp_size_inv = DRW_viewport_invert_size_get();
178
179 const float w = fabsf(mul_project_m4_v3_zfac(persmat, ob->object_to_world().location()));
180
181 /* Modify by distance to camera and object scale. */
182 float world_pixel_scale = 1.0f / GPENCIL_PIXEL_FACTOR;
183 float scale = mat4_to_scale(ob->object_to_world().ptr());
184 float distance_factor = (world_pixel_scale * scale * winmat[1][1] * vp_size[1]) / w;
185 mul_v2_fl(offset, distance_factor);
186 mul_v2_v2(offset, vp_size_inv);
187 mul_v2_fl(blur_size, distance_factor);
188
190
192 grp = gpencil_vfx_pass_create("Fx Rim H", state, iter, sh);
194 grp, "blurDir", blender::float2{blur_size[0] * vp_size_inv[0], 0.0f});
195 DRW_shgroup_uniform_vec2_copy(grp, "uvOffset", offset);
196 DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, blur_size[0])));
197 DRW_shgroup_uniform_vec3_copy(grp, "maskColor", fx->mask_rgb);
198 DRW_shgroup_uniform_bool_copy(grp, "isFirstPass", true);
200
201 switch (fx->mode) {
204 break;
207 break;
210 break;
215 break;
216 }
217
218 zero_v2(offset);
219
220 grp = gpencil_vfx_pass_create("Fx Rim V", state, iter, sh);
222 grp, "blurDir", blender::float2{0.0f, blur_size[1] * vp_size_inv[1]});
223 DRW_shgroup_uniform_vec2_copy(grp, "uvOffset", offset);
224 DRW_shgroup_uniform_vec3_copy(grp, "rimColor", fx->rim_rgb);
225 DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, blur_size[1])));
226 DRW_shgroup_uniform_int_copy(grp, "blendMode", fx->mode);
227 DRW_shgroup_uniform_bool_copy(grp, "isFirstPass", false);
229
230 if (fx->mode == eShaderFxRimMode_Overlay) {
231 /* We cannot do custom blending on multi-target frame-buffers.
232 * Workaround by doing 2 passes. */
233 grp = DRW_shgroup_create_sub(grp);
236 DRW_shgroup_uniform_int_copy(grp, "blendMode", 999);
238 }
239}
240
242{
243 DRWShadingGroup *grp;
244
245 float persmat[4][4], winmat[4][4], ob_center[3], pixsize_uniform[2];
246 DRW_view_winmat_get(nullptr, winmat, false);
247 DRW_view_persmat_get(nullptr, persmat, false);
248 const float *vp_size = DRW_viewport_size_get();
249 const float *vp_size_inv = DRW_viewport_invert_size_get();
250 float pixel_size[2] = {float(fx->size[0]), float(fx->size[1])};
251 mul_v2_v2(pixel_size, vp_size_inv);
252
253 /* Fixed pixelisation center from object center. */
254 const float w = fabsf(mul_project_m4_v3_zfac(persmat, ob->object_to_world().location()));
255 mul_v3_m4v3(ob_center, persmat, ob->object_to_world().location());
256 mul_v3_fl(ob_center, 1.0f / w);
257
258 const bool use_antialiasing = ((fx->flag & FX_PIXEL_FILTER_NEAREST) == 0);
259
260 /* Convert to uvs. */
261 mul_v2_fl(ob_center, 0.5f);
262 add_v2_fl(ob_center, 0.5f);
263
264 /* Modify by distance to camera and object scale. */
265 float world_pixel_scale = 1.0f / GPENCIL_PIXEL_FACTOR;
266 float scale = mat4_to_scale(ob->object_to_world().ptr());
267 mul_v2_fl(pixel_size, (world_pixel_scale * scale * winmat[1][1] * vp_size[1]) / w);
268
269 /* Center to texel */
270 madd_v2_v2fl(ob_center, pixel_size, -0.5f);
271
273
275
276 /* Only if pixelated effect is bigger than 1px. */
277 if (pixel_size[0] > vp_size_inv[0]) {
278 copy_v2_fl2(pixsize_uniform, pixel_size[0], vp_size_inv[1]);
281
282 grp = gpencil_vfx_pass_create("Fx Pixelize X", state, iter, sh, sampler);
283 DRW_shgroup_uniform_vec2_copy(grp, "targetPixelSize", pixsize_uniform);
284 DRW_shgroup_uniform_vec2_copy(grp, "targetPixelOffset", ob_center);
285 DRW_shgroup_uniform_vec2_copy(grp, "accumOffset", blender::float2{pixel_size[0], 0.0f});
286 int samp_count = (pixel_size[0] / vp_size_inv[0] > 3.0) ? 2 : 1;
287 DRW_shgroup_uniform_int_copy(grp, "sampCount", use_antialiasing ? samp_count : 0);
289 }
290
291 if (pixel_size[1] > vp_size_inv[1]) {
294 copy_v2_fl2(pixsize_uniform, vp_size_inv[0], pixel_size[1]);
295 grp = gpencil_vfx_pass_create("Fx Pixelize Y", state, iter, sh, sampler);
296 DRW_shgroup_uniform_vec2_copy(grp, "targetPixelSize", pixsize_uniform);
297 DRW_shgroup_uniform_vec2_copy(grp, "accumOffset", blender::float2{0.0f, pixel_size[1]});
298 int samp_count = (pixel_size[1] / vp_size_inv[1] > 3.0) ? 2 : 1;
299 DRW_shgroup_uniform_int_copy(grp, "sampCount", use_antialiasing ? samp_count : 0);
301 }
302}
303
305{
306 DRWShadingGroup *grp;
307
308 const bool use_obj_pivot = (fx->flag & FX_SHADOW_USE_OBJECT) != 0;
309 const bool use_wave = (fx->flag & FX_SHADOW_USE_WAVE) != 0;
310
311 float uv_mat[4][4], winmat[4][4], persmat[4][4], rot_center[3];
312 float wave_ofs[3], wave_dir[3], wave_phase, blur_dir[2], tmp[2];
313 float offset[2] = {float(fx->offset[0]), float(fx->offset[1])};
314 float blur_size[2] = {float(fx->blur[0]), float(fx->blur[1])};
315 DRW_view_winmat_get(nullptr, winmat, false);
316 DRW_view_persmat_get(nullptr, persmat, false);
317 const float *vp_size = DRW_viewport_size_get();
318 const float *vp_size_inv = DRW_viewport_invert_size_get();
319 const float ratio = vp_size_inv[1] / vp_size_inv[0];
320
321 copy_v3_v3(rot_center,
322 (use_obj_pivot && fx->object) ? fx->object->object_to_world().location() :
323 ob->object_to_world().location());
324
325 const float w = fabsf(mul_project_m4_v3_zfac(persmat, rot_center));
326 mul_v3_m4v3(rot_center, persmat, rot_center);
327 mul_v3_fl(rot_center, 1.0f / w);
328
329 /* Modify by distance to camera and object scale. */
330 float world_pixel_scale = 1.0f / GPENCIL_PIXEL_FACTOR;
331 float scale = mat4_to_scale(ob->object_to_world().ptr());
332 float distance_factor = (world_pixel_scale * scale * winmat[1][1] * vp_size[1]) / w;
333 mul_v2_fl(offset, distance_factor);
334 mul_v2_v2(offset, vp_size_inv);
335 mul_v2_fl(blur_size, distance_factor);
336
337 rot_center[0] = rot_center[0] * 0.5f + 0.5f;
338 rot_center[1] = rot_center[1] * 0.5f + 0.5f;
339
340 /* UV transform matrix. (loc, rot, scale) Sent to shader as 2x3 matrix. */
341 unit_m4(uv_mat);
342 translate_m4(uv_mat, rot_center[0], rot_center[1], 0.0f);
343 rescale_m4(uv_mat, blender::float3{1.0f / fx->scale[0], 1.0f / fx->scale[1], 1.0f});
344 translate_m4(uv_mat, -offset[0], -offset[1], 0.0f);
345 rescale_m4(uv_mat, blender::float3{1.0f / ratio, 1.0f, 1.0f});
346 rotate_m4(uv_mat, 'Z', fx->rotation);
347 rescale_m4(uv_mat, blender::float3{ratio, 1.0f, 1.0f});
348 translate_m4(uv_mat, -rot_center[0], -rot_center[1], 0.0f);
349
350 if (use_wave) {
351 float dir[2];
352 if (fx->orientation == 0) {
353 /* Horizontal */
354 copy_v2_fl2(dir, 1.0f, 0.0f);
355 }
356 else {
357 /* Vertical */
358 copy_v2_fl2(dir, 0.0f, 1.0f);
359 }
360 /* This is applied after rotation. Counter the rotation to keep aligned with global axis. */
361 rotate_v2_v2fl(wave_dir, dir, fx->rotation);
362 /* Rotate 90 degrees. */
363 copy_v2_v2(wave_ofs, wave_dir);
364 std::swap(wave_ofs[0], wave_ofs[1]);
365 wave_ofs[1] *= -1.0f;
366 /* Keep world space scaling and aspect ratio. */
367 mul_v2_fl(wave_dir, 1.0f / (max_ff(1e-8f, fx->period) * distance_factor));
368 mul_v2_v2(wave_dir, vp_size);
369 mul_v2_fl(wave_ofs, fx->amplitude * distance_factor);
370 mul_v2_v2(wave_ofs, vp_size_inv);
371 /* Phase start at shadow center. */
372 wave_phase = fx->phase - dot_v2v2(rot_center, wave_dir);
373 }
374 else {
375 zero_v2(wave_dir);
376 zero_v2(wave_ofs);
377 wave_phase = 0.0f;
378 }
379
381
382 copy_v2_fl2(blur_dir, blur_size[0] * vp_size_inv[0], 0.0f);
383
385 grp = gpencil_vfx_pass_create("Fx Shadow H", state, iter, sh);
386 DRW_shgroup_uniform_vec2_copy(grp, "blurDir", blur_dir);
387 DRW_shgroup_uniform_vec2_copy(grp, "waveDir", wave_dir);
388 DRW_shgroup_uniform_vec2_copy(grp, "waveOffset", wave_ofs);
389 DRW_shgroup_uniform_float_copy(grp, "wavePhase", wave_phase);
390 DRW_shgroup_uniform_vec2_copy(grp, "uvRotX", uv_mat[0]);
391 DRW_shgroup_uniform_vec2_copy(grp, "uvRotY", uv_mat[1]);
392 DRW_shgroup_uniform_vec2_copy(grp, "uvOffset", uv_mat[3]);
393 DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, blur_size[0])));
394 DRW_shgroup_uniform_bool_copy(grp, "isFirstPass", true);
396
397 unit_m4(uv_mat);
398 zero_v2(wave_ofs);
399
400 /* Reset the `uv_mat` to account for rotation in the Y-axis (Shadow-V parameter). */
401 copy_v2_fl2(tmp, 0.0f, blur_size[1]);
402 rotate_v2_v2fl(blur_dir, tmp, -fx->rotation);
403 mul_v2_v2(blur_dir, vp_size_inv);
404
406 grp = gpencil_vfx_pass_create("Fx Shadow V", state, iter, sh);
407 DRW_shgroup_uniform_vec4_copy(grp, "shadowColor", fx->shadow_rgba);
408 DRW_shgroup_uniform_vec2_copy(grp, "blurDir", blur_dir);
409 DRW_shgroup_uniform_vec2_copy(grp, "waveOffset", wave_ofs);
410 DRW_shgroup_uniform_vec2_copy(grp, "uvRotX", uv_mat[0]);
411 DRW_shgroup_uniform_vec2_copy(grp, "uvRotY", uv_mat[1]);
412 DRW_shgroup_uniform_vec2_copy(grp, "uvOffset", uv_mat[3]);
413 DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, blur_size[1])));
414 DRW_shgroup_uniform_bool_copy(grp, "isFirstPass", false);
416}
417
418static void gpencil_vfx_glow(GlowShaderFxData *fx, Object * /*ob*/, gpIterVfxData *iter)
419{
420 const bool use_glow_under = (fx->flag & FX_GLOW_USE_ALPHA) != 0;
421 DRWShadingGroup *grp;
422 const float s = sin(fx->rotation);
423 const float c = cos(fx->rotation);
424
426
427 float ref_col[4];
428
430 /* Only pass in the first value for luminance. */
431 ref_col[0] = fx->threshold;
432 ref_col[1] = -1.0f;
433 ref_col[2] = -1.0f;
434 ref_col[3] = -1.0f;
435 }
436 else {
437 /* First three values are the RGB for the selected color, last value the threshold. */
438 copy_v3_v3(ref_col, fx->select_color);
439 ref_col[3] = fx->threshold;
440 }
441
443 grp = gpencil_vfx_pass_create("Fx Glow H", state, iter, sh);
444 DRW_shgroup_uniform_vec2_copy(grp, "offset", blender::float2{fx->blur[0] * c, fx->blur[0] * s});
445 DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, fx->blur[0])));
446 DRW_shgroup_uniform_vec4_copy(grp, "threshold", ref_col);
447 DRW_shgroup_uniform_vec4_copy(grp, "glowColor", fx->glow_color);
448 DRW_shgroup_uniform_bool_copy(grp, "glowUnder", use_glow_under);
449 DRW_shgroup_uniform_bool_copy(grp, "firstPass", true);
451
453 /* Blending: Force blending. */
454 switch (fx->blend_mode) {
457 break;
460 break;
463 break;
467 break;
468 }
469
470 /* Small Hack: We ask for RGBA16F buffer if using use_glow_under to store original
471 * revealage in alpha channel. */
472 if (fx->blend_mode == eGplBlendMode_Subtract || use_glow_under) {
473 /* For this effect to propagate, we need a signed floating point buffer. */
474 iter->pd->use_signed_fb = true;
475 }
476
477 grp = gpencil_vfx_pass_create("Fx Glow V", state, iter, sh);
478 DRW_shgroup_uniform_vec2_copy(grp, "offset", blender::float2{-fx->blur[1] * s, fx->blur[1] * c});
479 DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, fx->blur[0])));
480 DRW_shgroup_uniform_vec4_copy(grp, "threshold", blender::float4{-1.0f, -1.0f, -1.0f, -1.0});
482 grp, "glowColor", blender::float4{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(nullptr, winmat, false);
495 DRW_view_persmat_get(nullptr, 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->object_to_world().location()));
500 mul_v3_m4v3(wave_center, persmat, ob->object_to_world().location());
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->object_to_world().ptr());
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 degrees. */
520 copy_v2_v2(wave_ofs, wave_dir);
521 std::swap(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", blender::float2{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 == nullptr) {
548 return;
549 }
550
551 float winmat[4][4], persmat[4][4], swirl_center[3];
552 DRW_view_winmat_get(nullptr, winmat, false);
553 DRW_view_persmat_get(nullptr, persmat, false);
554 const float *vp_size = DRW_viewport_size_get();
555
556 copy_v3_v3(swirl_center, fx->object->object_to_world().location());
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->object_to_world().ptr());
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", blender::float2{1.0f, 1.0f});
581 DRW_shgroup_uniform_vec2_copy(grp, "waveOffset", blender::float2{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 Object *ob,
590 GPENCIL_tObject *tgp_ob,
591 const bool is_edit_mode)
592{
593 GPENCIL_FramebufferList *fbl = vedata->fbl;
594 GPENCIL_PrivateData *pd = vedata->stl->pd;
595
596 /* These may not be allocated yet, use address of future pointer. */
597 gpIterVfxData iter{};
598 iter.pd = pd;
599 iter.tgp_ob = tgp_ob;
600 iter.target_fb = &fbl->layer_fb;
601 iter.source_fb = &fbl->object_fb;
606
607 /* If simplify enabled, nothing more to do. */
608 if (!pd->simplify_fx) {
610 if (effect_is_active(fx, is_edit_mode, pd->is_viewport)) {
611 switch (fx->type) {
613 gpencil_vfx_blur((BlurShaderFxData *)fx, ob, &iter);
614 break;
617 break;
619 gpencil_vfx_flip((FlipShaderFxData *)fx, ob, &iter);
620 break;
622 gpencil_vfx_pixelize((PixelShaderFxData *)fx, ob, &iter);
623 break;
625 gpencil_vfx_rim((RimShaderFxData *)fx, ob, &iter);
626 break;
628 gpencil_vfx_shadow((ShadowShaderFxData *)fx, ob, &iter);
629 break;
631 gpencil_vfx_glow((GlowShaderFxData *)fx, ob, &iter);
632 break;
634 gpencil_vfx_swirl((SwirlShaderFxData *)fx, ob, &iter);
635 break;
637 gpencil_vfx_wave((WaveShaderFxData *)fx, ob, &iter);
638 break;
639 default:
640 break;
641 }
642 }
643 }
644 }
645
646 if ((!pd->simplify_fx && tgp_ob->vfx.first != nullptr) || tgp_ob->do_mat_holdout) {
647 /* We need an extra pass to combine result to main buffer. */
648 iter.target_fb = &fbl->gpencil_fb;
649
651
653 DRWShadingGroup *grp = gpencil_vfx_pass_create("GPencil Object Compose", state, &iter, sh);
654 DRW_shgroup_uniform_int_copy(grp, "isFirstPass", true);
656
657 /* We cannot do custom blending on multi-target frame-buffers.
658 * Workaround by doing 2 passes. */
659 grp = DRW_shgroup_create_sub(grp);
662 DRW_shgroup_uniform_int_copy(grp, "isFirstPass", false);
664
665 pd->use_object_fb = true;
666 pd->use_layer_fb = true;
667 }
668}
Camera data-block and utility functions.
#define LISTBASE_FOREACH(type, var, list)
MINLINE float max_ff(float a, float b)
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
float mat4_to_scale(const float mat[4][4])
void unit_m4(float m[4][4])
Definition rct.c:1127
void translate_m4(float mat[4][4], float Tx, float Ty, float Tz)
void rescale_m4(float mat[4][4], const float scale[3])
void mul_v3_m4v3(float r[3], const float mat[4][4], const float vec[3])
void rotate_m4(float mat[4][4], char axis, float angle)
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)
MINLINE void copy_v2_fl(float r[2], float f)
void * BLI_memblock_alloc(BLI_memblock *mblk) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
@ eGplBlendMode_Regular
@ eGplBlendMode_Multiply
@ 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
struct GPUShader GPUShader
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
local_group_size(16, 16) .push_constant(Type local_group_size(16, 16) .push_constant(Type input_tx sampler(1, ImageType::FLOAT_2D, "matte_tx") .image(0
#define fabsf(x)
const float * DRW_viewport_invert_size_get()
const float * DRW_viewport_size_get()
DRWShadingGroup * DRW_shgroup_create(GPUShader *shader, DRWPass *pass)
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)
DRWPass * DRW_pass_create(const char *name, 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)
DRWShadingGroup * DRW_shgroup_create_sub(DRWShadingGroup *shgroup)
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)
void DRW_shgroup_call_procedural_triangles(DRWShadingGroup *shgroup, const Object *ob, uint tri_count)
void DRW_shgroup_uniform_vec4_copy(DRWShadingGroup *shgroup, const char *name, const float *value)
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)
void DRW_shgroup_uniform_texture_ref_ex(DRWShadingGroup *shgroup, const char *name, GPUTexture **tex, GPUSamplerState sampler_state)
DRWState
Definition draw_state.hh:25
@ DRW_STATE_BLEND_SUB
Definition draw_state.hh:61
@ DRW_STATE_BLEND_ADD_FULL
Definition draw_state.hh:53
@ DRW_STATE_WRITE_COLOR
Definition draw_state.hh:30
@ DRW_STATE_BLEND_ALPHA_PREMUL
Definition draw_state.hh:57
@ DRW_STATE_BLEND_MUL
Definition draw_state.hh:60
draw_view in_light_buf[] float
struct GPUShader * GPENCIL_shader_fx_composite_get(void)
struct GPUShader * GPENCIL_shader_fx_transform_get(void)
struct GPUShader * GPENCIL_shader_fx_shadow_get(void)
struct GPUShader * GPENCIL_shader_fx_blur_get(void)
struct GPUShader * GPENCIL_shader_fx_glow_get(void)
#define GPENCIL_PIXEL_FACTOR
struct GPUShader * GPENCIL_shader_fx_rim_get(void)
struct GPUShader * GPENCIL_shader_fx_colorize_get(void)
struct GPUShader * GPENCIL_shader_fx_pixelize_get(void)
static void gpencil_vfx_flip(FlipShaderFxData *fx, Object *, gpIterVfxData *iter)
void gpencil_vfx_cache_populate(GPENCIL_Data *vedata, Object *ob, GPENCIL_tObject *tgp_ob, const bool is_edit_mode)
static void gpencil_vfx_pixelize(PixelShaderFxData *fx, Object *ob, gpIterVfxData *iter)
static void gpencil_vfx_glow(GlowShaderFxData *fx, Object *, gpIterVfxData *iter)
static void gpencil_vfx_shadow(ShadowShaderFxData *fx, Object *ob, gpIterVfxData *iter)
static void gpencil_vfx_rim(RimShaderFxData *fx, Object *ob, gpIterVfxData *iter)
static void gpencil_vfx_colorize(ColorizeShaderFxData *fx, Object *, gpIterVfxData *iter)
static void gpencil_vfx_wave(WaveShaderFxData *fx, Object *ob, gpIterVfxData *iter)
static void gpencil_vfx_blur(BlurShaderFxData *fx, Object *ob, gpIterVfxData *iter)
static DRWShadingGroup * gpencil_vfx_pass_create(const char *name, DRWState state, gpIterVfxData *iter, GPUShader *sh, GPUSamplerState sampler=GPUSamplerState::internal_sampler())
static bool effect_is_active(ShaderFxData *fx, bool is_edit, bool is_viewport)
static void gpencil_vfx_swirl(SwirlShaderFxData *fx, Object *, gpIterVfxData *iter)
ccl_device_inline float3 cos(float3 v)
static ulong state[N]
struct GPENCIL_StorageList * stl
struct GPENCIL_FramebufferList * fbl
struct GPUFrameBuffer * gpencil_fb
struct GPUFrameBuffer * object_fb
struct GPUFrameBuffer * layer_fb
struct BLI_memblock * gp_vfx_pool
GPUTexture * color_object_tx
GPUTexture * reveal_layer_tx
GPUTexture * color_layer_tx
GPUTexture * reveal_object_tx
struct GPENCIL_PrivateData * pd
struct GPENCIL_tObject::@201 vfx
GPENCIL_tLayer * first
GPUFrameBuffer ** target_fb
DRWPass * vfx_ps
static constexpr GPUSamplerState internal_sampler()
static constexpr GPUSamplerState default_sampler()
ListBase shader_fx
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