From f1afa6f6a71220fefcd3d967f261edd6ad93a43a Mon Sep 17 00:00:00 2001 From: Antonioya Date: Sun, 30 Sep 2018 11:19:04 +0200 Subject: GP: implement Shadow FX (wip) Initial implementation of effect to create a drop shadow of the strokes --- source/blender/draw/CMakeLists.txt | 2 + .../blender/draw/engines/gpencil/gpencil_engine.c | 12 +- .../blender/draw/engines/gpencil/gpencil_engine.h | 9 +- .../draw/engines/gpencil/gpencil_shader_fx.c | 141 ++++++++++++++++++++- .../shaders/fx/gpencil_fx_shadow_prepare_frag.glsl | 122 ++++++++++++++++++ .../shaders/fx/gpencil_fx_shadow_resolve_frag.glsl | 32 +++++ source/blender/makesdna/DNA_shader_fx_types.h | 21 +++ source/blender/makesrna/RNA_access.h | 1 + source/blender/makesrna/intern/rna_shader_fx.c | 88 +++++++++++++ source/blender/shader_fx/CMakeLists.txt | 1 + source/blender/shader_fx/FX_shader_types.h | 1 + source/blender/shader_fx/intern/FX_shader_shadow.c | 110 ++++++++++++++++ source/blender/shader_fx/intern/FX_shader_util.c | 1 + 13 files changed, 525 insertions(+), 16 deletions(-) create mode 100644 source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_shadow_prepare_frag.glsl create mode 100644 source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_shadow_resolve_frag.glsl create mode 100644 source/blender/shader_fx/intern/FX_shader_shadow.c (limited to 'source/blender') 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 + +#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 -- cgit v1.2.3