[Bf-blender-cvs] [4f08463279a] greasepencil-refactor: GPencil: Refactor: Add Shadow Effect
Clément Foucault
noreply at git.blender.org
Wed Dec 18 03:14:35 CET 2019
Commit: 4f08463279aa0245e46301ba05719222040205d3
Author: Clément Foucault
Date: Wed Dec 18 03:13:23 2019 +0100
Branches: greasepencil-refactor
https://developer.blender.org/rB4f08463279aa0245e46301ba05719222040205d3
GPencil: Refactor: Add Shadow Effect
All the parameters are now locked in world space following the object
center.
===================================================================
M source/blender/draw/engines/gpencil/gpencil_engine.c
M source/blender/draw/engines/gpencil/gpencil_engine.h
M source/blender/draw/engines/gpencil/gpencil_shader.c
M source/blender/draw/engines/gpencil/gpencil_shader_fx.c
M source/blender/draw/engines/gpencil/shaders/gpencil_vfx_frag.glsl
===================================================================
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index 75514d07351..fe62d9ac824 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -363,6 +363,7 @@ static void GPENCIL_engine_free(void)
DRW_SHADER_FREE_SAFE(e_data.fx_composite_sh);
DRW_SHADER_FREE_SAFE(e_data.fx_glow_sh);
DRW_SHADER_FREE_SAFE(e_data.fx_pixel_sh);
+ DRW_SHADER_FREE_SAFE(e_data.fx_shadow_sh);
DRW_TEXTURE_FREE_SAFE(e_data.gpencil_blank_texture);
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h
index 35d23652bc1..a88181a32b7 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.h
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.h
@@ -467,10 +467,11 @@ typedef struct GPENCIL_e_data {
/* Merge the final object depth to the depth buffer. */
struct GPUShader *depth_merge_sh;
/* Effects. */
+ struct GPUShader *fx_composite_sh;
struct GPUShader *fx_blur_sh;
- struct GPUShader *fx_pixel_sh;
struct GPUShader *fx_glow_sh;
- struct GPUShader *fx_composite_sh;
+ struct GPUShader *fx_pixel_sh;
+ struct GPUShader *fx_shadow_sh;
/* general drawing shaders */
struct GPUShader *gpencil_fill_sh;
@@ -712,6 +713,7 @@ struct GPUShader *GPENCIL_shader_fx_blur_get(GPENCIL_e_data *e_data);
struct GPUShader *GPENCIL_shader_fx_composite_get(GPENCIL_e_data *e_data);
struct GPUShader *GPENCIL_shader_fx_glow_get(GPENCIL_e_data *e_data);
struct GPUShader *GPENCIL_shader_fx_pixelize_get(GPENCIL_e_data *e_data);
+struct GPUShader *GPENCIL_shader_fx_shadow_get(GPENCIL_e_data *e_data);
/* main functions */
void GPENCIL_engine_init(void *vedata);
diff --git a/source/blender/draw/engines/gpencil/gpencil_shader.c b/source/blender/draw/engines/gpencil/gpencil_shader.c
index f61ee80c39f..0590ea2824f 100644
--- a/source/blender/draw/engines/gpencil/gpencil_shader.c
+++ b/source/blender/draw/engines/gpencil/gpencil_shader.c
@@ -147,3 +147,12 @@ struct GPUShader *GPENCIL_shader_fx_pixelize_get(GPENCIL_e_data *e_data)
}
return e_data->fx_pixel_sh;
}
+
+struct GPUShader *GPENCIL_shader_fx_shadow_get(GPENCIL_e_data *e_data)
+{
+ if (!e_data->fx_shadow_sh) {
+ e_data->fx_shadow_sh = DRW_shader_create_fullscreen(datatoc_gpencil_vfx_frag_glsl,
+ "#define SHADOW\n");
+ }
+ return e_data->fx_shadow_sh;
+}
diff --git a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c
index 34661da2b1c..e11549c7968 100644
--- a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c
+++ b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c
@@ -1174,13 +1174,125 @@ static void gpencil_vfx_pixelize(PixelShaderFxData *fx, Object *ob, gpIterVfxDat
}
}
+static void gpencil_vfx_shadow(ShadowShaderFxData *fx, Object *ob, gpIterVfxData *iter)
+{
+ DRWShadingGroup *grp;
+
+ const bool use_obj_pivot = (fx->flag & FX_SHADOW_USE_OBJECT) != 0;
+ const bool use_wave = (fx->flag & FX_SHADOW_USE_WAVE) != 0;
+
+ float uv_mat[4][4], winmat[4][4], persmat[4][4], rot_center[3];
+ float wave_ofs[3], wave_dir[3], wave_phase, blur_dir[2], tmp[2];
+ float offset[2] = {fx->offset[0], fx->offset[1]};
+ float blur_size[2] = {fx->blur[0], fx->blur[1]};
+ DRW_view_winmat_get(NULL, winmat, false);
+ DRW_view_persmat_get(NULL, persmat, false);
+ const float *vp_size = DRW_viewport_size_get();
+ const float *vp_size_inv = DRW_viewport_invert_size_get();
+ const float ratio = vp_size_inv[1] / vp_size_inv[0];
+
+ copy_v3_v3(rot_center, (use_obj_pivot && fx->object) ? fx->object->obmat[3] : ob->obmat[3]);
+
+ const float w = fabsf(mul_project_m4_v3_zfac(persmat, rot_center));
+ mul_v3_m4v3(rot_center, persmat, rot_center);
+ mul_v3_fl(rot_center, 1.0f / w);
+
+ /* Modify by distance to camera and object scale. */
+ float world_pixel_scale = 1.0f / 2000.0f;
+ float scale = mat4_to_scale(ob->obmat);
+ float distance_factor = (world_pixel_scale * scale * winmat[1][1] * vp_size[1]) / w;
+ mul_v2_fl(offset, distance_factor);
+ mul_v2_v2(offset, vp_size_inv);
+ mul_v2_fl(blur_size, distance_factor);
+
+ rot_center[0] = rot_center[0] * 0.5f + 0.5f;
+ rot_center[1] = rot_center[1] * 0.5f + 0.5f;
+
+ /* UV transform matrix. (loc, rot, scale) Sent to shader as 2x3 matrix. */
+ unit_m4(uv_mat);
+ translate_m4(uv_mat, rot_center[0], rot_center[1], 0.0f);
+ rescale_m4(uv_mat, (float[3]){1.0f / fx->scale[0], 1.0f / fx->scale[1], 1.0f});
+ translate_m4(uv_mat, -offset[0], -offset[1], 0.0f);
+ rescale_m4(uv_mat, (float[3]){1.0f / ratio, 1.0f, 1.0f});
+ rotate_m4(uv_mat, 'Z', fx->rotation);
+ rescale_m4(uv_mat, (float[3]){ratio, 1.0f, 1.0f});
+ translate_m4(uv_mat, -rot_center[0], -rot_center[1], 0.0f);
+
+ if (use_wave) {
+ float dir[2];
+ if (fx->orientation == 0) {
+ /* Horizontal */
+ copy_v2_fl2(dir, 1.0f, 0.0f);
+ }
+ else {
+ /* Vertical */
+ copy_v2_fl2(dir, 0.0f, 1.0f);
+ }
+ /* This is applied after rotation. Counter the rotation to keep aligned with global axis. */
+ rotate_v2_v2fl(wave_dir, dir, fx->rotation);
+ /* Rotate 90°. */
+ copy_v2_v2(wave_ofs, wave_dir);
+ SWAP(float, wave_ofs[0], wave_ofs[1]);
+ wave_ofs[1] *= -1.0f;
+ /* Keep world space scalling and aspect ratio. */
+ mul_v2_fl(wave_dir, 1.0f / (max_ff(1e-8f, fx->period) * distance_factor));
+ mul_v2_v2(wave_dir, vp_size);
+ mul_v2_fl(wave_ofs, fx->amplitude * distance_factor);
+ mul_v2_v2(wave_ofs, vp_size_inv);
+ /* Phase start at shadow center. */
+ wave_phase = fx->phase - dot_v2v2(rot_center, wave_dir);
+ }
+ else {
+ zero_v2(wave_dir);
+ zero_v2(wave_ofs);
+ wave_phase = 0.0f;
+ }
+
+ GPUShader *sh = GPENCIL_shader_fx_shadow_get(&en_data);
+
+ copy_v2_fl2(blur_dir, blur_size[0] * vp_size_inv[0], 0.0f);
+
+ DRWState state = DRW_STATE_WRITE_COLOR;
+ grp = gpencil_vfx_pass_create("Fx Shadow H", state, iter, sh);
+ DRW_shgroup_uniform_vec2_copy(grp, "blurDir", blur_dir);
+ DRW_shgroup_uniform_vec2_copy(grp, "waveDir", wave_dir);
+ DRW_shgroup_uniform_vec2_copy(grp, "waveOffset", wave_ofs);
+ DRW_shgroup_uniform_float_copy(grp, "wavePhase", wave_phase);
+ DRW_shgroup_uniform_vec2_copy(grp, "uvRotX", uv_mat[0]);
+ DRW_shgroup_uniform_vec2_copy(grp, "uvRotY", uv_mat[1]);
+ DRW_shgroup_uniform_vec2_copy(grp, "uvOffset", uv_mat[3]);
+ DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, blur_size[0])));
+ DRW_shgroup_uniform_bool_copy(grp, "isFirstPass", true);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+
+ unit_m4(uv_mat);
+ zero_v2(wave_ofs);
+
+ /* We reseted the uv_mat so we need to accound for the rotation in the */
+ copy_v2_fl2(tmp, 0.0f, blur_size[1]);
+ rotate_v2_v2fl(blur_dir, tmp, -fx->rotation);
+ mul_v2_v2(blur_dir, vp_size_inv);
+
+ state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA_PREMUL;
+ grp = gpencil_vfx_pass_create("Fx Shadow V", state, iter, sh);
+ DRW_shgroup_uniform_vec4_copy(grp, "shadowColor", fx->shadow_rgba);
+ DRW_shgroup_uniform_vec2_copy(grp, "blurDir", blur_dir);
+ DRW_shgroup_uniform_vec2_copy(grp, "waveOffset", wave_ofs);
+ DRW_shgroup_uniform_vec2_copy(grp, "uvRotX", uv_mat[0]);
+ DRW_shgroup_uniform_vec2_copy(grp, "uvRotY", uv_mat[1]);
+ DRW_shgroup_uniform_vec2_copy(grp, "uvOffset", uv_mat[3]);
+ DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, blur_size[1])));
+ DRW_shgroup_uniform_bool_copy(grp, "isFirstPass", false);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+}
+
static void gpencil_vfx_glow(GlowShaderFxData *fx, Object *UNUSED(ob), gpIterVfxData *iter)
{
DRWShadingGroup *grp;
GPUShader *sh = GPENCIL_shader_fx_glow_get(&en_data);
- float ref_col[3], threshold_min, threshold_max;
+ float ref_col[3];
if (fx->mode == eShaderFxGlowMode_Luminance) {
ref_col[0] = fx->threshold;
@@ -1246,6 +1358,7 @@ void gpencil_vfx_cache_populate(GPENCIL_Data *vedata, Object *ob, GPENCIL_tObjec
case eShaderFxType_Rim:
break;
case eShaderFxType_Shadow:
+ gpencil_vfx_shadow((ShadowShaderFxData *)fx, ob, &iter);
break;
case eShaderFxType_Glow:
gpencil_vfx_glow((GlowShaderFxData *)fx, ob, &iter);
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_vfx_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_vfx_frag.glsl
index e483812b292..b0046d4e4c8 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_vfx_frag.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_vfx_frag.glsl
@@ -114,6 +114,73 @@ void main()
}
}
+#elif defined(SHADOW)
+
+uniform vec4 shadowColor;
+uniform vec2 uvRotX;
+uniform vec2 uvRotY;
+uniform vec2 uvOffset;
+uniform vec2 blurDir;
+uniform vec2 waveDir;
+uniform vec2 waveOffset;
+uniform float wavePhase;
+uniform int sampCount;
+uniform bool isFirstPass;
+
+vec2 compute_uvs(float x)
+{
+ vec2 uv = uvcoordsvar.xy;
+ /* Tranform UV (loc, rot, scale) */
+ uv = uv.x * uvRotX + uv.y * uvRotY + uvOffset;
+ uv += blurDir * x;
+ /* Wave deform. */
+ float wave_time = dot(uv, waveDir.xy);
+ uv += sin(wave_time + wavePhase) * waveOffset;
+ return uv;
+}
+
+void main()
+{
+ /* Blur revealage buffer. */
+ fragRevealage = vec4(0.0);
+ float weight_accum = 0.0;
+ for (int i = -sampCount; i <= sampCount; i++) {
+ float x = float(i) / float(sampCount);
+ float weight = gaussian_weight(x);
+ weight_accum += weight;
+ vec2 uv = compute_uvs(x);
+ vec3 col = texture(revealBuf, uv).rgb;
+ if (any(not(equal(vec2(0.0), floor(uv))))) {
+ col = vec3(1.0);
+ }
+ fragRevealage.rgb += col * weight;
+ }
+ fragRevealage /= weight_accum;
+
+ /* No blending in first pass, alpha over premult in second pass. */
+ if (isFirstPass) {
+ /* In first pass we copy the reveal buffer. This let us do alpha under in second pass. */
+ fragColor = texture(revealBuf, uvcoordsvar.xy);
+ }
+ else {
+ /* fragRevealage is blurred shadow. */
+ float shadow_fac = 1.0 - clamp(dot(vec3(0.333334
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list