diff options
13 files changed, 471 insertions, 0 deletions
diff --git a/release/scripts/startup/bl_ui/properties_data_shaderfx.py b/release/scripts/startup/bl_ui/properties_data_shaderfx.py index fdb962aab68..8b4bd03bc6d 100644 --- a/release/scripts/startup/bl_ui/properties_data_shaderfx.py +++ b/release/scripts/startup/bl_ui/properties_data_shaderfx.py @@ -125,6 +125,19 @@ class DATA_PT_shader_fx(ShaderFxButtonsPanel, Panel): layout.prop(fx, "period") layout.prop(fx, "phase") + def FX_GLOW(self, layout, fx): + layout.prop(fx, "mode") + layout.prop(fx, "glow_color") + if fx.mode == 'LUMINANCE': + layout.prop(fx, "threshold") + else: + layout.prop(fx, "select_color") + + layout.separator() + layout.prop(fx, "radius") + layout.prop(fx, "samples") + layout.prop(fx, "use_alpha_mode", text="Use alpha mode") + def FX_SWIRL(self, layout, fx): layout.prop(fx, "object", text="Object") diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 4f9a90ba4f0..738efffcd91 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -337,6 +337,8 @@ data_to_c_simple(engines/gpencil/shaders/gpencil_edit_point_frag.glsl SRC) data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_blur_frag.glsl SRC) data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_colorize_frag.glsl SRC) data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_flip_frag.glsl SRC) +data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_glow_prepare_frag.glsl SRC) +data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_glow_resolve_frag.glsl SRC) 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) diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h index 7a9e93ec105..b8844d3c3e9 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.h +++ b/source/blender/draw/engines/gpencil/gpencil_engine.h @@ -73,6 +73,7 @@ typedef struct tGPencilObjectCache { DRWShadingGroup *fx_pixel_sh; DRWShadingGroup *fx_rim_sh; DRWShadingGroup *fx_shadow_sh; + DRWShadingGroup *fx_glow_sh; DRWShadingGroup *fx_swirl_sh; DRWShadingGroup *fx_flip_sh; DRWShadingGroup *fx_light_sh; @@ -231,6 +232,8 @@ typedef struct GPENCIL_e_data { struct GPUShader *gpencil_fx_blur_sh; struct GPUShader *gpencil_fx_colorize_sh; struct GPUShader *gpencil_fx_flip_sh; + struct GPUShader *gpencil_fx_glow_prepare_sh; + struct GPUShader *gpencil_fx_glow_resolve_sh; struct GPUShader *gpencil_fx_light_sh; struct GPUShader *gpencil_fx_pixel_sh; struct GPUShader *gpencil_fx_rim_prepare_sh; diff --git a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c index 9e04365fe1d..9513f83191e 100644 --- a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c +++ b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c @@ -50,6 +50,8 @@ 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_glow_prepare_frag_glsl[]; +extern char datatoc_gpencil_fx_glow_resolve_frag_glsl[]; extern char datatoc_gpencil_fx_swirl_frag_glsl[]; extern char datatoc_gpencil_fx_wave_frag_glsl[]; @@ -512,6 +514,67 @@ static void DRW_gpencil_fx_shadow( fxd->runtime.fx_sh_c = fx_shgrp; } +/* Glow FX */ +static void DRW_gpencil_fx_glow( + ShaderFxData *fx, GPENCIL_e_data *e_data, GPENCIL_Data *vedata, + tGPencilObjectCache *cache) +{ + if (fx == NULL) { + return; + } + GlowShaderFxData *fxd = (GlowShaderFxData *)fx; + + 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_glow_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_vec3(fx_shgrp, "glow_color", &fxd->glow_color[0], 1); + DRW_shgroup_uniform_vec3(fx_shgrp, "select_color", &fxd->select_color[0], 1); + DRW_shgroup_uniform_int(fx_shgrp, "mode", &fxd->mode, 1); + DRW_shgroup_uniform_float(fx_shgrp, "threshold", &fxd->threshold, 1); + + fxd->runtime.fx_sh = fx_shgrp; + + /* blur pass */ + fx_shgrp = DRW_shgroup_create( + 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_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); + DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1); + DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &cache->pixfactor, 1); + + fxd->runtime.fx_sh_b = fx_shgrp; + + /* resolve pass */ + fx_shgrp = DRW_shgroup_create( + e_data->gpencil_fx_glow_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, "glowColor", &e_data->temp_color_tx_fx); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "glowDepth", &e_data->temp_depth_tx_fx); + + /* reuse field */ + DRW_shgroup_uniform_int(fx_shgrp, "alpha_mode", &fxd->blur[1], 1); + + fxd->runtime.fx_sh_c = fx_shgrp; +} + /* Swirl FX */ static void DRW_gpencil_fx_swirl( ShaderFxData *fx, GPENCIL_e_data *e_data, GPENCIL_Data *vedata, @@ -617,6 +680,13 @@ void GPENCIL_create_fx_shaders(GPENCIL_e_data *e_data) e_data->gpencil_fx_shadow_resolve_sh = DRW_shader_create_fullscreen( datatoc_gpencil_fx_shadow_resolve_frag_glsl, NULL); } + if (!e_data->gpencil_fx_glow_prepare_sh) { + e_data->gpencil_fx_glow_prepare_sh = DRW_shader_create_fullscreen( + datatoc_gpencil_fx_glow_prepare_frag_glsl, NULL); + + e_data->gpencil_fx_glow_resolve_sh = DRW_shader_create_fullscreen( + datatoc_gpencil_fx_glow_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); @@ -639,6 +709,8 @@ void GPENCIL_delete_fx_shaders(GPENCIL_e_data *e_data) 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_glow_prepare_sh); + DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_glow_resolve_sh); DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_swirl_sh); DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_wave_sh); } @@ -693,6 +765,9 @@ void DRW_gpencil_fx_prepare( case eShaderFxType_Shadow: DRW_gpencil_fx_shadow(fx, e_data, vedata, cache); break; + case eShaderFxType_Glow: + DRW_gpencil_fx_glow(fx, e_data, vedata, cache); + break; case eShaderFxType_Swirl: DRW_gpencil_fx_swirl(fx, e_data, vedata, cache); break; @@ -947,6 +1022,92 @@ static void draw_gpencil_shadow_passes( DRW_draw_pass(psl->mix_pass_noblend); } +/* blur glow */ +static void draw_gpencil_glow_blur( + struct GPENCIL_e_data *UNUSED(e_data), + struct GPENCIL_Data *vedata, + struct GlowShaderFxData *fxd) +{ + 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 }; + + 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 for ping-pong frame buffers */ + 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); +} + +/* helper to draw GLOW passes */ +static void draw_gpencil_glow_passes( + struct GPENCIL_e_data *e_data, + struct GPENCIL_Data *vedata, + struct GlowShaderFxData *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 }; + int bx = fxd->blur[0]; + int by = fxd->blur[0]; + + /* prepare glow */ + 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); + + /* blur glow */ + e_data->input_depth_tx = e_data->temp_depth_tx_b; + e_data->input_color_tx = e_data->temp_color_tx_b; + + if ((fxd->samples > 0) && ((bx > 0) || (by > 0))) { + for (int x = 0; x < fxd->samples; x++) { + + /* horizontal */ + fxd->blur[0] = bx; + fxd->blur[1] = 0; + draw_gpencil_glow_blur(e_data, vedata, fxd); + + /* Vertical */ + fxd->blur[0] = 0; + fxd->blur[1] = by; + draw_gpencil_glow_blur(e_data, vedata, fxd); + + fxd->blur[0] = bx; + fxd->blur[1] = by; + } + } + /* resolve */ + GPU_framebuffer_bind(fbl->temp_fb_b); + GPU_framebuffer_clear_color_depth(fbl->temp_fb_b, clearcol, 1.0f); + + /* reuses blur field to keep alpha mode */ + fxd->blur[1] = (fxd->flag & FX_GLOW_USE_ALPHA) ? 1 : 0; + + DRW_draw_pass_subset( + psl->fx_shader_pass_blend, + fxd->runtime.fx_sh_c, fxd->runtime.fx_sh_c); + + /* 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, @@ -1003,6 +1164,12 @@ void DRW_gpencil_fx_draw( draw_gpencil_shadow_passes(e_data, vedata, fxd); break; } + case eShaderFxType_Glow: + { + GlowShaderFxData *fxd = (GlowShaderFxData *)fx; + draw_gpencil_glow_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_glow_prepare_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_glow_prepare_frag.glsl new file mode 100644 index 00000000000..237cdf15627 --- /dev/null +++ b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_glow_prepare_frag.glsl @@ -0,0 +1,68 @@ +uniform mat4 ProjectionMatrix; +uniform mat4 ViewMatrix; + +/* ******************************************************************* */ +/* create glow mask */ +/* ******************************************************************* */ +uniform sampler2D strokeColor; +uniform sampler2D strokeDepth; + +uniform vec3 glow_color; +uniform vec3 select_color; +uniform float threshold; +uniform int mode; + +out vec4 FragColor; + +#define MODE_LUMINANCE 0 +#define MODE_COLOR 1 + +/* calc luminance */ +float luma( vec3 color ) { + /* the color is linear, so do not apply tonemapping */ + return (color.r + color.g + color.b) / 3.0; +} + +bool check_color(vec3 color_a, vec3 color_b) +{ + /* need round the number to avoid precision errors */ + if ((floor(color_a.r * 100) == floor(color_b.r * 100)) && + (floor(color_a.g * 100) == floor(color_b.g * 100)) && + (floor(color_a.b * 100) == floor(color_b.b * 100))) + { + return true; + } + + return false; +} + +void main() +{ + vec2 uv = vec2(gl_FragCoord.xy); + + float stroke_depth = texelFetch(strokeDepth, ivec2(uv.xy), 0).r; + vec4 src_pixel= texelFetch(strokeColor, ivec2(uv.xy), 0); + vec4 outcolor; + + /* is transparent */ + if (src_pixel.a == 0.0f) { + discard; + } + + if (mode == MODE_LUMINANCE) { + if (luma(src_pixel.rgb) < threshold) { + discard; + } + } + else if (mode == MODE_COLOR) { + if (!check_color(src_pixel.rgb, select_color.rgb)) { + discard; + } + } + else { + discard; + } + + gl_FragDepth = stroke_depth; + FragColor = vec4(glow_color.rgb, 1.0); +} diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_glow_resolve_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_glow_resolve_frag.glsl new file mode 100644 index 00000000000..010c4ef4a88 --- /dev/null +++ b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_glow_resolve_frag.glsl @@ -0,0 +1,46 @@ +/* ******************************************************************* */ +/* Resolve GLOW pass */ +/* ******************************************************************* */ +uniform sampler2D strokeColor; +uniform sampler2D strokeDepth; +uniform sampler2D glowColor; +uniform sampler2D glowDepth; +uniform int alpha_mode; + +out vec4 FragColor; + +void main() +{ + vec4 outcolor; + ivec2 uv = ivec2(gl_FragCoord.xy); + + float stroke_depth = texelFetch(strokeDepth, uv.xy, 0).r; + vec4 src_pixel= texelFetch(strokeColor, uv.xy, 0); + vec4 glow_pixel= texelFetch(glowColor, uv.xy, 0); + float glow_depth = texelFetch(glowDepth, uv.xy, 0).r; + + if (alpha_mode == 0) { + outcolor = src_pixel + glow_pixel; + } + else { + if ((src_pixel.a < 0.1) || (glow_pixel.a < 0.1)) { + outcolor = src_pixel + glow_pixel; + } + else { + outcolor = src_pixel; + } + } + + if (src_pixel.a < glow_pixel.a) { + gl_FragDepth = glow_depth; + } + else { + gl_FragDepth = stroke_depth; + } + + if (outcolor.a < 0.001) { + discard; + } + + FragColor = outcolor; +} diff --git a/source/blender/makesdna/DNA_shader_fx_types.h b/source/blender/makesdna/DNA_shader_fx_types.h index 3884f72fb56..7c138f21887 100644 --- a/source/blender/makesdna/DNA_shader_fx_types.h +++ b/source/blender/makesdna/DNA_shader_fx_types.h @@ -45,6 +45,7 @@ typedef enum ShaderFxType { eShaderFxType_Rim = 7, eShaderFxType_Colorize = 8, eShaderFxType_Shadow = 9, + eShaderFxType_Glow = 10, NUM_SHADER_FX_TYPES } ShaderFxType; @@ -127,6 +128,27 @@ typedef enum eFlipShaderFx_Flag { FX_FLIP_VERTICAL = (1 << 1), } eFlipShaderFx_Flag; +typedef struct GlowShaderFxData { + ShaderFxData shaderfx; + float glow_color[3]; + float select_color[3]; + float threshold; + int flag; /* flags */ + int mode; + int blur[2]; + int samples; + ShaderFxData_Runtime runtime; +} GlowShaderFxData; + +typedef enum GlowShaderFxModes { + eShaderFxGlowMode_Luminance = 0, + eShaderFxGlowMode_Color = 1, +} GlowShaderFxModes; + +typedef enum eGlowShaderFx_Flag { + FX_GLOW_USE_ALPHA = (1 << 0), +} eGlowShaderFx_Flag; + typedef struct LightShaderFxData { ShaderFxData shaderfx; struct Object *object; diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index a90248ee53e..c1eed8093c8 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -619,6 +619,7 @@ extern StructRNA RNA_ShaderFx; extern StructRNA RNA_ShaderFxBlur; extern StructRNA RNA_ShaderFxColorize; extern StructRNA RNA_ShaderFxFlip; +extern StructRNA RNA_ShaderFxGlow; extern StructRNA RNA_ShaderFxLight; extern StructRNA RNA_ShaderFxPixel; extern StructRNA RNA_ShaderFxRim; diff --git a/source/blender/makesrna/intern/rna_shader_fx.c b/source/blender/makesrna/intern/rna_shader_fx.c index 22ebd3f7567..fe4e20bbd58 100644 --- a/source/blender/makesrna/intern/rna_shader_fx.c +++ b/source/blender/makesrna/intern/rna_shader_fx.c @@ -52,6 +52,7 @@ const EnumPropertyItem rna_enum_object_shaderfx_type_items[] = { {eShaderFxType_Blur, "FX_BLUR", ICON_SHADERFX, "Blur", "Apply Gaussian Blur to object" }, {eShaderFxType_Colorize, "FX_COLORIZE", ICON_SHADERFX, "Colorize", "Apply different tint effects" }, {eShaderFxType_Flip, "FX_FLIP", ICON_SHADERFX, "Flip", "Flip image" }, + {eShaderFxType_Glow, "FX_GLOW", ICON_SHADERFX, "Glow", "Create a glow effect" }, {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" }, @@ -71,6 +72,12 @@ static const EnumPropertyItem rna_enum_shaderfx_rim_modes_items[] = { {0, NULL, 0, NULL, NULL } }; +static const EnumPropertyItem rna_enum_shaderfx_glow_modes_items[] = { + {eShaderFxGlowMode_Luminance, "LUMINANCE", 0, "Luminance", "" }, + {eShaderFxGlowMode_Color, "COLOR", 0, "Color", "" }, + {0, NULL, 0, NULL, NULL } +}; + static const EnumPropertyItem rna_enum_shaderfx_colorize_modes_items[] = { {eShaderFxColorizeMode_GrayScale, "GRAYSCALE", 0, "Gray Scale", "" }, {eShaderFxColorizeMode_Sepia, "SEPIA", 0, "Sepia", "" }, @@ -108,6 +115,8 @@ static StructRNA *rna_ShaderFx_refine(struct PointerRNA *ptr) return &RNA_ShaderFxSwirl; case eShaderFxType_Flip: return &RNA_ShaderFxFlip; + case eShaderFxType_Glow: + return &RNA_ShaderFxGlow; case eShaderFxType_Light: return &RNA_ShaderFxLight; /* Default */ @@ -483,6 +492,64 @@ static void rna_def_shader_fx_shadow(BlenderRNA *brna) RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update"); } +static void rna_def_shader_fx_glow(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "ShaderFxGlow", "ShaderFx"); + RNA_def_struct_ui_text(srna, "Glow Effect", "Glow effect"); + RNA_def_struct_sdna(srna, "GlowShaderFxData"); + RNA_def_struct_ui_icon(srna, ICON_SHADERFX); + + prop = RNA_def_property(srna, "glow_color", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_range(prop, 0.0, 1.0); + RNA_def_property_float_sdna(prop, NULL, "glow_color"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Glow Color", "Color used for generated glow"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update"); + + prop = RNA_def_property(srna, "select_color", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_range(prop, 0.0, 1.0); + RNA_def_property_float_sdna(prop, NULL, "select_color"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Select Color", "Color selected to apply glow"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update"); + + prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "mode"); + RNA_def_property_enum_items(prop, rna_enum_shaderfx_glow_modes_items); + RNA_def_property_ui_text(prop, "Mode", "Glow mode"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update"); + + prop = RNA_def_property(srna, "threshold", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "threshold"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1f, 3); + RNA_def_property_ui_text(prop, "Threshold", "Limit to select color for glow effect"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update"); + + /* use blur fields to make compatible with blur filter, but only makes public first array element */ + prop = RNA_def_property(srna, "radius", PROP_INT, PROP_PIXEL); + RNA_def_property_int_sdna(prop, NULL, "blur[0]"); + RNA_def_property_range(prop, 0, INT_MAX); + RNA_def_property_ui_text(prop, "Radius", "Number of pixels for bluring glow (set to 0 to disable)"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update"); + + prop = RNA_def_property(srna, "samples", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "samples"); + RNA_def_property_range(prop, 1, 32); + RNA_def_property_ui_range(prop, 1, 32, 2, -1); + RNA_def_property_int_default(prop, 4); + RNA_def_property_ui_text(prop, "Samples", "Number of Blur Samples"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update"); + + prop = RNA_def_property(srna, "use_alpha_mode", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", FX_GLOW_USE_ALPHA); + RNA_def_property_ui_text(prop, "Use Alpha", "Glow only areas with alpha"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update"); +} + static void rna_def_shader_fx_swirl(BlenderRNA *brna) { StructRNA *srna; @@ -631,6 +698,7 @@ void RNA_def_shader_fx(BlenderRNA *brna) rna_def_shader_fx_pixel(brna); rna_def_shader_fx_rim(brna); rna_def_shader_fx_shadow(brna); + rna_def_shader_fx_glow(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 89defbd4ac7..1807635aa8d 100644 --- a/source/blender/shader_fx/CMakeLists.txt +++ b/source/blender/shader_fx/CMakeLists.txt @@ -46,6 +46,7 @@ set(SRC intern/FX_shader_blur.c intern/FX_shader_colorize.c intern/FX_shader_flip.c + intern/FX_shader_glow.c intern/FX_shader_light.c intern/FX_shader_pixel.c intern/FX_shader_rim.c diff --git a/source/blender/shader_fx/FX_shader_types.h b/source/blender/shader_fx/FX_shader_types.h index 57b9ae71146..311f5ec52e8 100644 --- a/source/blender/shader_fx/FX_shader_types.h +++ b/source/blender/shader_fx/FX_shader_types.h @@ -35,6 +35,7 @@ extern ShaderFxTypeInfo shaderfx_Type_None; extern ShaderFxTypeInfo shaderfx_Type_Blur; extern ShaderFxTypeInfo shaderfx_Type_Colorize; extern ShaderFxTypeInfo shaderfx_Type_Flip; +extern ShaderFxTypeInfo shaderfx_Type_Glow; extern ShaderFxTypeInfo shaderfx_Type_Light; extern ShaderFxTypeInfo shaderfx_Type_Pixel; extern ShaderFxTypeInfo shaderfx_Type_Rim; diff --git a/source/blender/shader_fx/intern/FX_shader_util.c b/source/blender/shader_fx/intern/FX_shader_util.c index d5cbdc69ba3..b74ff45b991 100644 --- a/source/blender/shader_fx/intern/FX_shader_util.c +++ b/source/blender/shader_fx/intern/FX_shader_util.c @@ -46,6 +46,7 @@ void shaderfx_type_init(ShaderFxTypeInfo *types[]) INIT_FX_TYPE(Blur); INIT_FX_TYPE(Colorize); INIT_FX_TYPE(Flip); + INIT_FX_TYPE(Glow); INIT_FX_TYPE(Light); INIT_FX_TYPE(Pixel); INIT_FX_TYPE(Rim); diff --git a/source/blender/shader_fx/intern/fx_shader_glow.c b/source/blender/shader_fx/intern/fx_shader_glow.c new file mode 100644 index 00000000000..cd513ed1f0a --- /dev/null +++ b/source/blender/shader_fx/intern/fx_shader_glow.c @@ -0,0 +1,78 @@ +/* + * ***** 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_glow.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" + +static void initData(ShaderFxData *md) +{ + GlowShaderFxData *gpfx = (GlowShaderFxData *)md; + ARRAY_SET_ITEMS(gpfx->glow_color, 0.75f, 1.0f, 1.0f); + ARRAY_SET_ITEMS(gpfx->select_color, 0.0f, 0.0f, 0.0f); + gpfx->threshold = 0.1f; + + ARRAY_SET_ITEMS(gpfx->blur, 50, 0); + gpfx->samples = 16; +} + +static void copyData(const ShaderFxData *md, ShaderFxData *target) +{ + BKE_shaderfx_copyData_generic(md, target); +} + +ShaderFxTypeInfo shaderfx_Type_Glow = { + /* name */ "Glow", + /* structName */ "GlowShaderFxData", + /* structSize */ sizeof(GlowShaderFxData), + /* type */ eShaderFxType_GpencilType, + /* flags */ 0, + + /* copyData */ copyData, + + /* initData */ initData, + /* freeData */ NULL, + /* isDisabled */ NULL, + /* updateDepsgraph */ NULL, + /* dependsOnTime */ NULL, + /* foreachObjectLink */ NULL, + /* foreachIDLink */ NULL, +}; |