Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntonioya <blendergit@gmail.com>2018-09-30 12:19:04 +0300
committerAntonioya <blendergit@gmail.com>2018-09-30 12:49:02 +0300
commitf1afa6f6a71220fefcd3d967f261edd6ad93a43a (patch)
tree0e8fc19a9089a0434fdad495613a5075e92ea315 /source/blender
parentd9f6fdae4b5ae0475f0cbc8114a87b3be21739db (diff)
GP: implement Shadow FX (wip)
Initial implementation of effect to create a drop shadow of the strokes
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/draw/CMakeLists.txt2
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.c12
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.h9
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_shader_fx.c141
-rw-r--r--source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_shadow_prepare_frag.glsl122
-rw-r--r--source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_shadow_resolve_frag.glsl32
-rw-r--r--source/blender/makesdna/DNA_shader_fx_types.h21
-rw-r--r--source/blender/makesrna/RNA_access.h1
-rw-r--r--source/blender/makesrna/intern/rna_shader_fx.c88
-rw-r--r--source/blender/shader_fx/CMakeLists.txt1
-rw-r--r--source/blender/shader_fx/FX_shader_types.h1
-rw-r--r--source/blender/shader_fx/intern/FX_shader_shadow.c110
-rw-r--r--source/blender/shader_fx/intern/FX_shader_util.c1
13 files changed, 525 insertions, 16 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 06752e41092..a2ab6383828 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -340,6 +340,8 @@ data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_light_frag.glsl SRC)
data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_pixel_frag.glsl SRC)
data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_rim_prepare_frag.glsl SRC)
data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_rim_resolve_frag.glsl SRC)
+data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_shadow_prepare_frag.glsl SRC)
+data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_shadow_resolve_frag.glsl SRC)
data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_swirl_frag.glsl SRC)
data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_wave_frag.glsl SRC)
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index 657c7665312..bc545a1db80 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -141,17 +141,17 @@ static void GPENCIL_create_framebuffers(void *vedata)
GPU_ATTACHMENT_TEXTURE(e_data.temp_color_tx_b)
});
- /* used for rim FX effect */
- e_data.temp_depth_tx_rim = DRW_texture_pool_query_2D(
+ /* used for rim and shadow FX effects */
+ e_data.temp_depth_tx_fx = DRW_texture_pool_query_2D(
size[0], size[1], GPU_DEPTH24_STENCIL8,
&draw_engine_gpencil_type);
- e_data.temp_color_tx_rim = DRW_texture_pool_query_2D(
+ e_data.temp_color_tx_fx = DRW_texture_pool_query_2D(
size[0], size[1], fb_format,
&draw_engine_gpencil_type);
GPU_framebuffer_ensure_config(
- &fbl->temp_fb_rim, {
- GPU_ATTACHMENT_TEXTURE(e_data.temp_depth_tx_rim),
- GPU_ATTACHMENT_TEXTURE(e_data.temp_color_tx_rim),
+ &fbl->temp_fb_fx, {
+ GPU_ATTACHMENT_TEXTURE(e_data.temp_depth_tx_fx),
+ GPU_ATTACHMENT_TEXTURE(e_data.temp_color_tx_fx),
});
/* background framebuffer to speed up drawing process (always 16 bits) */
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h
index be883360959..89a50170eb6 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.h
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.h
@@ -72,6 +72,7 @@ typedef struct tGPencilObjectCache {
DRWShadingGroup *fx_colorize_sh;
DRWShadingGroup *fx_pixel_sh;
DRWShadingGroup *fx_rim_sh;
+ DRWShadingGroup *fx_shadow_sh;
DRWShadingGroup *fx_swirl_sh;
DRWShadingGroup *fx_flip_sh;
DRWShadingGroup *fx_light_sh;
@@ -160,7 +161,7 @@ typedef struct GPENCIL_FramebufferList {
struct GPUFrameBuffer *main;
struct GPUFrameBuffer *temp_fb_a;
struct GPUFrameBuffer *temp_fb_b;
- struct GPUFrameBuffer *temp_fb_rim;
+ struct GPUFrameBuffer *temp_fb_fx;
struct GPUFrameBuffer *background_fb;
struct GPUFrameBuffer *multisample_fb;
@@ -234,6 +235,8 @@ typedef struct GPENCIL_e_data {
struct GPUShader *gpencil_fx_pixel_sh;
struct GPUShader *gpencil_fx_rim_prepare_sh;
struct GPUShader *gpencil_fx_rim_resolve_sh;
+ struct GPUShader *gpencil_fx_shadow_prepare_sh;
+ struct GPUShader *gpencil_fx_shadow_resolve_sh;
struct GPUShader *gpencil_fx_swirl_sh;
struct GPUShader *gpencil_fx_wave_sh;
@@ -254,8 +257,8 @@ typedef struct GPENCIL_e_data {
struct GPUTexture *temp_color_tx_b;
struct GPUTexture *temp_depth_tx_b;
- struct GPUTexture *temp_color_tx_rim;
- struct GPUTexture *temp_depth_tx_rim;
+ struct GPUTexture *temp_color_tx_fx;
+ struct GPUTexture *temp_depth_tx_fx;
/* for buffer only one batch is nedeed because the drawing is only of one stroke */
GPUBatch *batch_buffer_stroke;
diff --git a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c
index 7d6a8691b87..5a96d6d1275 100644
--- a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c
+++ b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c
@@ -48,6 +48,8 @@ extern char datatoc_gpencil_fx_light_frag_glsl[];
extern char datatoc_gpencil_fx_pixel_frag_glsl[];
extern char datatoc_gpencil_fx_rim_prepare_frag_glsl[];
extern char datatoc_gpencil_fx_rim_resolve_frag_glsl[];
+extern char datatoc_gpencil_fx_shadow_prepare_frag_glsl[];
+extern char datatoc_gpencil_fx_shadow_resolve_frag_glsl[];
extern char datatoc_gpencil_fx_swirl_frag_glsl[];
extern char datatoc_gpencil_fx_wave_frag_glsl[];
@@ -407,8 +409,8 @@ static void DRW_gpencil_fx_rim(
e_data->gpencil_fx_blur_sh,
psl->fx_shader_pass_blend);
DRW_shgroup_call_add(fx_shgrp, fxquad, NULL);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_rim);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_rim);
+ DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_fx);
+ DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_fx);
DRW_shgroup_uniform_int(fx_shgrp, "blur", &fxd->blur[0], 2);
DRW_shgroup_uniform_vec3(fx_shgrp, "loc", &cache->loc[0], 1);
@@ -425,13 +427,82 @@ static void DRW_gpencil_fx_rim(
DRW_shgroup_call_add(fx_shgrp, fxquad, NULL);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeRim", &e_data->temp_color_tx_rim);
+ DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeRim", &e_data->temp_color_tx_fx);
DRW_shgroup_uniform_vec3(fx_shgrp, "mask_color", &fxd->mask_rgb[0], 1);
DRW_shgroup_uniform_int(fx_shgrp, "mode", &fxd->mode, 1);
fxd->runtime.fx_sh_c = fx_shgrp;
}
+/* Shadow FX */
+static void DRW_gpencil_fx_shadow(
+ ShaderFxData *fx, GPENCIL_e_data *e_data, GPENCIL_Data *vedata,
+ tGPencilObjectCache *cache)
+{
+ if (fx == NULL) {
+ return;
+ }
+ ShadowShaderFxData *fxd = (ShadowShaderFxData *)fx;
+ if ((!fxd->object) && (fxd->flag & FX_SHADOW_USE_OBJECT)) {
+ return;
+ }
+
+ GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+ GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
+ DRWShadingGroup *fx_shgrp;
+
+ struct GPUBatch *fxquad = DRW_cache_fullscreen_quad_get();
+ /* prepare pass */
+ fx_shgrp = DRW_shgroup_create(
+ e_data->gpencil_fx_shadow_prepare_sh,
+ psl->fx_shader_pass_blend);
+ DRW_shgroup_call_add(fx_shgrp, fxquad, NULL);
+ DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a);
+ DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a);
+ DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1);
+
+ DRW_shgroup_uniform_int(fx_shgrp, "offset", &fxd->offset[0], 2);
+ DRW_shgroup_uniform_float(fx_shgrp, "scale", &fxd->scale[0], 2);
+ DRW_shgroup_uniform_float(fx_shgrp, "rotation", &fxd->rotation, 1);
+ DRW_shgroup_uniform_vec4(fx_shgrp, "shadow_color", &fxd->shadow_rgba[0], 1);
+
+ if ((fxd->object) && (fxd->flag & FX_SHADOW_USE_OBJECT)) {
+ DRW_shgroup_uniform_vec3(fx_shgrp, "loc", &fxd->object->loc[0], 1);
+ }
+ else {
+ DRW_shgroup_uniform_vec3(fx_shgrp, "loc", &cache->loc[0], 1);
+ }
+
+ const int nowave = -1;
+ if (fxd->flag & FX_SHADOW_USE_WAVE) {
+ DRW_shgroup_uniform_int(fx_shgrp, "orientation", &fxd->orientation, 1);
+ }
+ else {
+ DRW_shgroup_uniform_int(fx_shgrp, "orientation", &nowave, 1);
+ }
+ DRW_shgroup_uniform_float(fx_shgrp, "amplitude", &fxd->amplitude, 1);
+ DRW_shgroup_uniform_float(fx_shgrp, "period", &fxd->period, 1);
+ DRW_shgroup_uniform_float(fx_shgrp, "phase", &fxd->phase, 1);
+
+ DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1);
+ DRW_shgroup_uniform_float(fx_shgrp, "pixelsize", &U.pixelsize, 1);
+ DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &cache->pixfactor, 1);
+
+ fxd->runtime.fx_sh = fx_shgrp;
+
+ /* resolve pass */
+ fx_shgrp = DRW_shgroup_create(
+ e_data->gpencil_fx_shadow_resolve_sh,
+ psl->fx_shader_pass_blend);
+ DRW_shgroup_call_add(fx_shgrp, fxquad, NULL);
+ DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a);
+ DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a);
+ DRW_shgroup_uniform_texture_ref(fx_shgrp, "shadowColor", &e_data->temp_color_tx_fx);
+ DRW_shgroup_uniform_texture_ref(fx_shgrp, "shadowDepth", &e_data->temp_depth_tx_fx);
+
+ fxd->runtime.fx_sh_b = fx_shgrp;
+}
+
/* Swirl FX */
static void DRW_gpencil_fx_swirl(
ShaderFxData *fx, GPENCIL_e_data *e_data, GPENCIL_Data *vedata,
@@ -531,6 +602,13 @@ void GPENCIL_create_fx_shaders(GPENCIL_e_data *e_data)
e_data->gpencil_fx_rim_resolve_sh = DRW_shader_create_fullscreen(
datatoc_gpencil_fx_rim_resolve_frag_glsl, NULL);
}
+ if (!e_data->gpencil_fx_shadow_prepare_sh) {
+ e_data->gpencil_fx_shadow_prepare_sh = DRW_shader_create_fullscreen(
+ datatoc_gpencil_fx_shadow_prepare_frag_glsl, NULL);
+
+ e_data->gpencil_fx_shadow_resolve_sh = DRW_shader_create_fullscreen(
+ datatoc_gpencil_fx_shadow_resolve_frag_glsl, NULL);
+ }
if (!e_data->gpencil_fx_swirl_sh) {
e_data->gpencil_fx_swirl_sh = DRW_shader_create_fullscreen(
datatoc_gpencil_fx_swirl_frag_glsl, NULL);
@@ -551,6 +629,8 @@ void GPENCIL_delete_fx_shaders(GPENCIL_e_data *e_data)
DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_pixel_sh);
DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_rim_prepare_sh);
DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_rim_resolve_sh);
+ DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_shadow_prepare_sh);
+ DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_shadow_resolve_sh);
DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_swirl_sh);
DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_wave_sh);
}
@@ -602,6 +682,9 @@ void DRW_gpencil_fx_prepare(
case eShaderFxType_Rim:
DRW_gpencil_fx_rim(fx, e_data, vedata, cache);
break;
+ case eShaderFxType_Shadow:
+ DRW_gpencil_fx_shadow(fx, e_data, vedata, cache);
+ break;
case eShaderFxType_Swirl:
DRW_gpencil_fx_swirl(fx, e_data, vedata, cache);
break;
@@ -706,8 +789,8 @@ static void draw_gpencil_rim_blur(
fxd->runtime.fx_sh_b, fxd->runtime.fx_sh_b);
/* copy pass from b for ping-pong frame buffers */
- GPU_framebuffer_bind(fbl->temp_fb_rim);
- GPU_framebuffer_clear_color_depth(fbl->temp_fb_rim, clearcol, 1.0f);
+ GPU_framebuffer_bind(fbl->temp_fb_fx);
+ GPU_framebuffer_clear_color_depth(fbl->temp_fb_fx, clearcol, 1.0f);
DRW_draw_pass(psl->mix_pass_noblend);
}
@@ -729,8 +812,8 @@ static void draw_gpencil_rim_passes(
int by = fxd->blur[1];
/* prepare mask */
- GPU_framebuffer_bind(fbl->temp_fb_rim);
- GPU_framebuffer_clear_color_depth(fbl->temp_fb_rim, clearcol, 1.0f);
+ GPU_framebuffer_bind(fbl->temp_fb_fx);
+ GPU_framebuffer_clear_color_depth(fbl->temp_fb_fx, clearcol, 1.0f);
DRW_draw_pass_subset(
psl->fx_shader_pass_blend,
fxd->runtime.fx_sh, fxd->runtime.fx_sh);
@@ -772,6 +855,44 @@ static void draw_gpencil_rim_passes(
DRW_draw_pass(psl->mix_pass_noblend);
}
+/* helper to draw SHADOW passes */
+static void draw_gpencil_shadow_passes(
+ struct GPENCIL_e_data *e_data,
+ struct GPENCIL_Data *vedata,
+ struct ShadowShaderFxData *fxd)
+{
+ if (fxd->runtime.fx_sh_b == NULL) {
+ return;
+ }
+
+ GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
+ GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl;
+
+ static float clearcol[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+
+ /* prepare shadow */
+ GPU_framebuffer_bind(fbl->temp_fb_fx);
+ GPU_framebuffer_clear_color_depth(fbl->temp_fb_fx, clearcol, 1.0f);
+ DRW_draw_pass_subset(
+ psl->fx_shader_pass_blend,
+ fxd->runtime.fx_sh, fxd->runtime.fx_sh);
+
+ /* resolve */
+ GPU_framebuffer_bind(fbl->temp_fb_b);
+ GPU_framebuffer_clear_color_depth(fbl->temp_fb_b, clearcol, 1.0f);
+ DRW_draw_pass_subset(
+ psl->fx_shader_pass_blend,
+ fxd->runtime.fx_sh_b, fxd->runtime.fx_sh_b);
+
+ /* copy pass from b to a for ping-pong frame buffers */
+ e_data->input_depth_tx = e_data->temp_depth_tx_b;
+ e_data->input_color_tx = e_data->temp_color_tx_b;
+
+ GPU_framebuffer_bind(fbl->temp_fb_a);
+ GPU_framebuffer_clear_color_depth(fbl->temp_fb_a, clearcol, 1.0f);
+ DRW_draw_pass(psl->mix_pass_noblend);
+}
+
/* apply all object fx effects */
void DRW_gpencil_fx_draw(
struct GPENCIL_e_data *e_data,
@@ -822,6 +943,12 @@ void DRW_gpencil_fx_draw(
draw_gpencil_rim_passes(e_data, vedata, fxd);
break;
}
+ case eShaderFxType_Shadow:
+ {
+ ShadowShaderFxData *fxd = (ShadowShaderFxData *)fx;
+ draw_gpencil_shadow_passes(e_data, vedata, fxd);
+ break;
+ }
case eShaderFxType_Swirl:
{
SwirlShaderFxData *fxd = (SwirlShaderFxData *)fx;
diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_shadow_prepare_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_shadow_prepare_frag.glsl
new file mode 100644
index 00000000000..941b746d494
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_shadow_prepare_frag.glsl
@@ -0,0 +1,122 @@
+uniform mat4 ProjectionMatrix;
+uniform mat4 ViewMatrix;
+
+/* ******************************************************************* */
+/* create shadow */
+/* ******************************************************************* */
+uniform sampler2D strokeColor;
+uniform sampler2D strokeDepth;
+uniform vec2 Viewport;
+
+uniform int offset[2];
+uniform float scale[2];
+uniform float rotation;
+uniform vec4 shadow_color;
+
+uniform float amplitude;
+uniform float period;
+uniform float phase;
+uniform int orientation;
+
+uniform vec3 loc;
+uniform float pixsize; /* rv3d->pixsize */
+uniform float pixelsize; /* U.pixelsize */
+uniform float pixfactor;
+
+#define M_PI 3.1415926535897932384626433832795
+
+#define HORIZONTAL 0
+#define VERTICAL 1
+
+float defaultpixsize = pixsize * pixelsize * (1000.0 / pixfactor);
+vec2 noffset = vec2(offset[0], offset[1]);
+
+out vec4 FragColor;
+
+/* project 3d point to 2d on screen space */
+vec2 toScreenSpace(vec4 vertex)
+{
+ /* need to calculate ndc because this is not done by vertex shader */
+ vec3 ndc = vec3(vertex).xyz / vertex.w;
+
+ vec2 sc;
+ sc.x = ((ndc.x + 1.0) / 2.0) * Viewport.x;
+ sc.y = ((ndc.y + 1.0) / 2.0) * Viewport.y;
+
+ return sc;
+}
+
+void main()
+{
+ vec2 uv = vec2(gl_FragCoord.xy);
+ vec4 nloc = ProjectionMatrix * ViewMatrix * vec4(loc.xyz, 1.0);
+ vec2 loc2d = toScreenSpace(nloc);
+
+ float dx = (ProjectionMatrix[3][3] == 0.0) ? (noffset[0] / (nloc.z * defaultpixsize)) : (noffset[0] / defaultpixsize);
+ float dy = (ProjectionMatrix[3][3] == 0.0) ? (noffset[1] / (nloc.z * defaultpixsize)) : (noffset[1] / defaultpixsize);
+
+ /* move point to new coords system */
+ vec2 tpos = vec2(uv.x, uv.y) - loc2d;
+
+ /* apply offset */
+ tpos = vec2(tpos.x - dx, tpos.y - dy);
+
+ /* apply scale */
+ tpos.x *= 1.0 / scale[0];
+ tpos.y *= 1.0 / scale[1];
+
+ /* rotation */
+ tpos.x = (tpos.x * cos(rotation)) - (tpos.y * sin(rotation));
+ tpos.y = (tpos.x * sin(rotation)) + (tpos.y * cos(rotation));
+
+ /* back to original coords system */
+ vec2 texpos = tpos + loc2d;
+
+ /* wave */
+ float value;
+ if (orientation == HORIZONTAL) {
+ float pval = (uv.x * M_PI) / Viewport[0];
+ value = amplitude * sin((period * pval) + phase);
+ texpos.y += value;
+ }
+ else if (orientation == VERTICAL){
+ float pval = (uv.y * M_PI) / Viewport[1];
+ value = amplitude * sin((period * pval) + phase);
+ texpos.x += value;
+ }
+
+ float stroke_depth = texelFetch(strokeDepth, ivec2(texpos.x, texpos.y), 0).r;
+ vec4 src_pixel= texelFetch(strokeColor, ivec2(texpos.x, texpos.y), 0);
+ vec4 outcolor;
+ outcolor = shadow_color;
+
+ /* is transparent */
+ if (src_pixel.a == 0.0f) {
+ discard;
+ }
+
+
+
+ // /* check inside viewport */
+ // else if ((uv.x - dx < 0) || (uv.x - dx > Viewport[0])) {
+ // discard;
+ // }
+ // else if ((uv.y - dy < 0) || (uv.y - dy > Viewport[1])) {
+ // discard;
+ // }
+ // /* pixel is equal to mask color, keep */
+ // else if (src_pixel.rgb == mask_color.rgb) {
+ // discard;
+ // }
+ // else {
+ // if ((src_pixel.a > 0) && (offset_pixel.a > 0)) {
+ // discard;
+ // }
+ // else {
+ // outcolor = vec4(rim_color, 1.0);
+ // }
+ // }
+
+ gl_FragDepth = stroke_depth;
+ FragColor = outcolor;
+}
diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_shadow_resolve_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_shadow_resolve_frag.glsl
new file mode 100644
index 00000000000..633dcf1fd63
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_shadow_resolve_frag.glsl
@@ -0,0 +1,32 @@
+/* ******************************************************************* */
+/* Resolve Shadow pass */
+/* ******************************************************************* */
+uniform sampler2D strokeColor;
+uniform sampler2D strokeDepth;
+uniform sampler2D shadowColor;
+uniform sampler2D shadowDepth;
+
+out vec4 FragColor;
+
+void main()
+{
+ ivec2 uv = ivec2(gl_FragCoord.xy);
+
+ float stroke_depth = texelFetch(strokeDepth, uv.xy, 0).r;
+ float shadow_depth = texelFetch(shadowDepth, uv.xy, 0).r;
+ vec4 stroke_pixel= texelFetch(strokeColor, uv.xy, 0);
+ vec4 shadow_pixel= texelFetch(shadowColor, uv.xy, 0);
+
+ /* copy original pixel */
+ vec4 outcolor = stroke_pixel;
+ float outdepth = stroke_depth;
+
+ /* if stroke is not on top, copy shadow */
+ if ((stroke_pixel.a <= 0.2) && (shadow_pixel.a > 0.0)) {
+ outcolor = shadow_pixel;
+ outdepth = shadow_depth;
+ }
+
+ gl_FragDepth = outdepth;
+ FragColor = outcolor;
+}
diff --git a/source/blender/makesdna/DNA_shader_fx_types.h b/source/blender/makesdna/DNA_shader_fx_types.h
index f3c9f06c8dc..62a1d705f3b 100644
--- a/source/blender/makesdna/DNA_shader_fx_types.h
+++ b/source/blender/makesdna/DNA_shader_fx_types.h
@@ -44,6 +44,7 @@ typedef enum ShaderFxType {
eShaderFxType_Wave = 6,
eShaderFxType_Rim = 7,
eShaderFxType_Colorize = 8,
+ eShaderFxType_Shadow = 9,
NUM_SHADER_FX_TYPES
} ShaderFxType;
@@ -169,6 +170,26 @@ typedef enum RimShaderFxModes {
eShaderFxRimMode_Divide = 5,
} RimShaderFxModes;
+typedef struct ShadowShaderFxData {
+ ShaderFxData shaderfx;
+ struct Object *object;
+ int offset[2];
+ int flag; /* flags */
+ float shadow_rgba[4];
+ float amplitude;
+ float period;
+ float phase;
+ int orientation;
+ float scale[2];
+ float rotation;
+ ShaderFxData_runtime runtime;
+} ShadowShaderFxData;
+
+typedef enum eShadowShaderFx_Flag {
+ FX_SHADOW_USE_OBJECT = (1 << 0),
+ FX_SHADOW_USE_WAVE = (1 << 1),
+} eShadowShaderFx_Flag;
+
typedef struct SwirlShaderFxData {
ShaderFxData shaderfx;
struct Object *object;
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 55bd83ece69..1278f27af75 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -621,6 +621,7 @@ extern StructRNA RNA_ShaderFxFlip;
extern StructRNA RNA_ShaderFxLight;
extern StructRNA RNA_ShaderFxPixel;
extern StructRNA RNA_ShaderFxRim;
+extern StructRNA RNA_ShaderFxShadow;
extern StructRNA RNA_ShaderFxSwirl;
extern StructRNA RNA_ShaderFxWave;
extern StructRNA RNA_TexMapping;
diff --git a/source/blender/makesrna/intern/rna_shader_fx.c b/source/blender/makesrna/intern/rna_shader_fx.c
index 2c09cfa787e..97acc47f2f4 100644
--- a/source/blender/makesrna/intern/rna_shader_fx.c
+++ b/source/blender/makesrna/intern/rna_shader_fx.c
@@ -55,6 +55,7 @@ const EnumPropertyItem rna_enum_object_shaderfx_type_items[] = {
{eShaderFxType_Light, "FX_LIGHT", ICON_SHADERFX, "Light", "Simulate ilumination" },
{eShaderFxType_Pixel, "FX_PIXEL", ICON_SHADERFX, "Pixelate", "Pixelate image"},
{eShaderFxType_Rim, "FX_RIM", ICON_SHADERFX, "Rim", "Add a rim to the image" },
+ {eShaderFxType_Shadow, "FX_SHADOW", ICON_SHADERFX, "Shadow", "Create a shadow effect"},
{eShaderFxType_Swirl, "FX_SWIRL", ICON_SHADERFX, "Swirl", "Create a rotation distortion"},
{eShaderFxType_Wave, "FX_WAVE", ICON_SHADERFX, "Wave Distortion", "Apply sinusoidal deformation"},
{0, NULL, 0, NULL, NULL}
@@ -101,6 +102,8 @@ static StructRNA *rna_ShaderFx_refine(struct PointerRNA *ptr)
return &RNA_ShaderFxPixel;
case eShaderFxType_Rim:
return &RNA_ShaderFxRim;
+ case eShaderFxType_Shadow:
+ return &RNA_ShaderFxShadow;
case eShaderFxType_Swirl:
return &RNA_ShaderFxSwirl;
case eShaderFxType_Flip:
@@ -180,6 +183,7 @@ static void rna_##_type##ShaderFx_##_prop##_set(PointerRNA *ptr, PointerRNA valu
}
RNA_FX_OBJECT_SET(Light, object, OB_EMPTY);
+RNA_FX_OBJECT_SET(Shadow, object, OB_EMPTY);
RNA_FX_OBJECT_SET(Swirl, object, OB_EMPTY);
#undef RNA_FX_OBJECT_SET
@@ -382,6 +386,89 @@ static void rna_def_shader_fx_rim(BlenderRNA *brna)
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
}
+static void rna_def_shader_fx_shadow(BlenderRNA *brna)
+{
+ static EnumPropertyItem prop_shaderfx_shadow_type_items[] = {
+ { 0, "HORIZONTAL", 0, "Horizontal", "" },
+ { 1, "VERTICAL", 0, "Vertical", "" },
+ { 0, NULL, 0, NULL, NULL }
+ };
+
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "ShaderFxShadow", "ShaderFx");
+ RNA_def_struct_ui_text(srna, "Shadow Effect", "Shadow effect");
+ RNA_def_struct_sdna(srna, "ShadowShaderFxData");
+ RNA_def_struct_ui_icon(srna, ICON_SHADERFX);
+
+ prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Object", "Object to determine center of rotation");
+ RNA_def_property_pointer_funcs(prop, NULL, "rna_ShadowShaderFx_object_set", NULL, NULL);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_update(prop, 0, "rna_ShaderFx_dependency_update");
+
+ prop = RNA_def_property(srna, "offset", PROP_INT, PROP_PIXEL);
+ RNA_def_property_int_sdna(prop, NULL, "offset");
+ RNA_def_property_range(prop, -INT_MAX, INT_MAX);
+ RNA_def_property_ui_text(prop, "Offset", "Offset of the shadow");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+
+ prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "scale");
+ RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
+ RNA_def_property_ui_text(prop, "Scale", "Offset of the shadow");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+
+ prop = RNA_def_property(srna, "shadow_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_float_sdna(prop, NULL, "shadow_rgba");
+ RNA_def_property_array(prop, 4);
+ RNA_def_property_ui_text(prop, "Shadow Color", "Color used for Shadow");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+
+ prop = RNA_def_property(srna, "orientation", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "orientation");
+ RNA_def_property_enum_items(prop, prop_shaderfx_shadow_type_items);
+ RNA_def_property_ui_text(prop, "Orientation", "Direction of the wave");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+
+ prop = RNA_def_property(srna, "amplitude", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "amplitude");
+ RNA_def_property_range(prop, 0, FLT_MAX);
+ RNA_def_property_ui_text(prop, "Amplitude", "Amplitude of Wave");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+
+ prop = RNA_def_property(srna, "period", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "period");
+ RNA_def_property_range(prop, 0, FLT_MAX);
+ RNA_def_property_ui_text(prop, "Period", "Period of Wave");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+
+ prop = RNA_def_property(srna, "phase", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "phase");
+ RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
+ RNA_def_property_ui_text(prop, "Phase", "Phase Shift of Wave");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+
+ prop = RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "rotation");
+ RNA_def_property_range(prop, DEG2RAD(-360), DEG2RAD(360));
+ RNA_def_property_ui_range(prop, DEG2RAD(-360), DEG2RAD(360), 5, 2);
+ RNA_def_property_ui_text(prop, "Rotation", "Rotation around center or object");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+
+ prop = RNA_def_property(srna, "use_object", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", FX_SHADOW_USE_OBJECT);
+ RNA_def_property_ui_text(prop, "Use Object", "Use object as center of rotation");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+
+ prop = RNA_def_property(srna, "use_wave", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", FX_SHADOW_USE_WAVE);
+ RNA_def_property_ui_text(prop, "Wave", "Use wave effect");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
+}
+
static void rna_def_shader_fx_swirl(BlenderRNA *brna)
{
StructRNA *srna;
@@ -529,6 +616,7 @@ void RNA_def_shader_fx(BlenderRNA *brna)
rna_def_shader_fx_wave(brna);
rna_def_shader_fx_pixel(brna);
rna_def_shader_fx_rim(brna);
+ rna_def_shader_fx_shadow(brna);
rna_def_shader_fx_swirl(brna);
rna_def_shader_fx_flip(brna);
rna_def_shader_fx_light(brna);
diff --git a/source/blender/shader_fx/CMakeLists.txt b/source/blender/shader_fx/CMakeLists.txt
index dacc0b3f063..89defbd4ac7 100644
--- a/source/blender/shader_fx/CMakeLists.txt
+++ b/source/blender/shader_fx/CMakeLists.txt
@@ -49,6 +49,7 @@ set(SRC
intern/FX_shader_light.c
intern/FX_shader_pixel.c
intern/FX_shader_rim.c
+ intern/FX_shader_shadow.c
intern/FX_shader_swirl.c
intern/FX_shader_wave.c
diff --git a/source/blender/shader_fx/FX_shader_types.h b/source/blender/shader_fx/FX_shader_types.h
index b8d8f04e07f..57b9ae71146 100644
--- a/source/blender/shader_fx/FX_shader_types.h
+++ b/source/blender/shader_fx/FX_shader_types.h
@@ -38,6 +38,7 @@ extern ShaderFxTypeInfo shaderfx_Type_Flip;
extern ShaderFxTypeInfo shaderfx_Type_Light;
extern ShaderFxTypeInfo shaderfx_Type_Pixel;
extern ShaderFxTypeInfo shaderfx_Type_Rim;
+extern ShaderFxTypeInfo shaderfx_Type_Shadow;
extern ShaderFxTypeInfo shaderfx_Type_Swirl;
extern ShaderFxTypeInfo shaderfx_Type_Wave;
diff --git a/source/blender/shader_fx/intern/FX_shader_shadow.c b/source/blender/shader_fx/intern/FX_shader_shadow.c
new file mode 100644
index 00000000000..d0a2ffd4590
--- /dev/null
+++ b/source/blender/shader_fx/intern/FX_shader_shadow.c
@@ -0,0 +1,110 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2018, Blender Foundation
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file blender/shader_fx/intern/FX_shader_shadow.c
+ * \ingroup shader_fx
+ */
+
+#include <stdio.h>
+
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_gpencil_types.h"
+
+#include "BLI_math_base.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_library_query.h"
+#include "BKE_modifier.h"
+#include "BKE_shader_fx.h"
+
+#include "FX_shader_types.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
+static void initData(ShaderFxData *md)
+{
+ ShadowShaderFxData *gpfx = (ShadowShaderFxData *)md;
+ gpfx->rotation = 0.0f;
+ ARRAY_SET_ITEMS(gpfx->offset, 15, 20);
+ ARRAY_SET_ITEMS(gpfx->scale, 1.0f, 1.0f);
+ ARRAY_SET_ITEMS(gpfx->shadow_rgba, 0.54f, 0.62f, 1.0f, 0.9f);
+
+ gpfx->amplitude = 10.0f;
+ gpfx->period = 20.0f;
+ gpfx->phase = 0.0f;
+ gpfx->orientation = 1;
+}
+
+static void copyData(const ShaderFxData *md, ShaderFxData *target)
+{
+ BKE_shaderfx_copyData_generic(md, target);
+}
+
+static void updateDepsgraph(ShaderFxData *fx, const ModifierUpdateDepsgraphContext *ctx)
+{
+ ShadowShaderFxData *fxd = (ShadowShaderFxData *)fx;
+ if (fxd->object != NULL) {
+ DEG_add_object_relation(ctx->node, fxd->object, DEG_OB_COMP_GEOMETRY, "Shadow ShaderFx");
+ DEG_add_object_relation(ctx->node, fxd->object, DEG_OB_COMP_TRANSFORM, "Shadow ShaderFx");
+ }
+ DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Shadow ShaderFx");
+}
+
+static bool isDisabled(ShaderFxData *fx, int UNUSED(userRenderParams))
+{
+ ShadowShaderFxData *fxd = (ShadowShaderFxData *)fx;
+
+ return (!fxd->object) && (fxd->flag & FX_SHADOW_USE_OBJECT);
+}
+
+static void foreachObjectLink(
+ ShaderFxData *fx, Object *ob,
+ ShaderFxObjectWalkFunc walk, void *userData)
+{
+ ShadowShaderFxData *fxd = (ShadowShaderFxData *)fx;
+
+ walk(userData, ob, &fxd->object, IDWALK_CB_NOP);
+}
+
+ShaderFxTypeInfo shaderfx_Type_Shadow = {
+ /* name */ "Shadow",
+ /* structName */ "ShadowShaderFxData",
+ /* structSize */ sizeof(ShadowShaderFxData),
+ /* type */ eShaderFxType_GpencilType,
+ /* flags */ 0,
+
+ /* copyData */ copyData,
+
+ /* initData */ initData,
+ /* freeData */ NULL,
+ /* isDisabled */ isDisabled,
+ /* updateDepsgraph */ updateDepsgraph,
+ /* dependsOnTime */ NULL,
+ /* foreachObjectLink */ foreachObjectLink,
+ /* foreachIDLink */ NULL,
+};
diff --git a/source/blender/shader_fx/intern/FX_shader_util.c b/source/blender/shader_fx/intern/FX_shader_util.c
index 64a1553adec..d5cbdc69ba3 100644
--- a/source/blender/shader_fx/intern/FX_shader_util.c
+++ b/source/blender/shader_fx/intern/FX_shader_util.c
@@ -49,6 +49,7 @@ void shaderfx_type_init(ShaderFxTypeInfo *types[])
INIT_FX_TYPE(Light);
INIT_FX_TYPE(Pixel);
INIT_FX_TYPE(Rim);
+ INIT_FX_TYPE(Shadow);
INIT_FX_TYPE(Swirl);
INIT_FX_TYPE(Wave);
#undef INIT_FX_TYPE