diff --git a/data/effects/sdf-generator.effect b/data/effects/sdf-generator.effect index 5579203e..8c2e47e4 100644 --- a/data/effects/sdf-generator.effect +++ b/data/effects/sdf-generator.effect @@ -1,3 +1,31 @@ +// 2D Signed Distance Field Generator +// +// This will produce an approximated Signed Distance Field on the fly. + +// Version 1.0: +// - Inputs: +// - _image: Source Image +// - _size: Size of SDF Frame +// - _sdf: Last SDF Frame +// - _threshold: Alpha Threshold +// - Output: +// - float4 +// - R: If outside, distance to nearest wall, otherwise 0. +// - G: If inside, distance to nearest wall, otherwise 0. +// - BA: UV coordinates of nearest wall. +// +// Version 1.1: +// - See Version 1.0 +// - Adjusted R, G to be 0..1 range, multiply by 65536.0 to get proper results. + +// -------------------------------------------------------------------------------- // +// Defines +#define MAX_DISTANCE 65536.0 +#define NEAR_INFINITE 18446744073709551616.0 +#define RANGE 4 + +// -------------------------------------------------------------------------------- // + // OBS Default uniform float4x4 ViewProj; @@ -7,14 +35,19 @@ uniform float2 _size; uniform texture2d _sdf; // in, out - swap rendering uniform float _threshold; -#define NEAR_INFINITE 18446744073709551616.0 -#define RANGE 4 - sampler_state sdfSampler { Filter = Point; AddressU = Clamp; AddressV = Clamp; }; + +sampler_state sdfSampler1_1 { + Filter = Linear; + AddressU = Border; + AddressV = Border; + BorderColor = FFFFFFFF; +}; + sampler_state imageSampler { Filter = Point; AddressU = Clamp; @@ -108,12 +141,87 @@ float4 PS_SDFGenerator_v1(VertDataOut v_in) : TARGET return outval; } +float4 PS_SDFGenerator_v1_1(VertDataOut v_in) : TARGET +{ + const float step = 1.0 / MAX_DISTANCE; + + float4 outval = float4(0.0, 0.0, v_in.uv.x, v_in.uv.y); + + // utility values + float2 uv_step = 1.0 / _size; + float lowest = NEAR_INFINITE; + float2 lowest_source = float2(NEAR_INFINITE, NEAR_INFINITE); + float2 lowest_origin = float2(NEAR_INFINITE, NEAR_INFINITE); + + // inputs + float imageA = _image.Sample(imageSampler, v_in.uv).a; + float4 self = _sdf.Sample(sdfSampler1_1, v_in.uv); + + if (imageA > _threshold) { + // Inside + // TODO: Optimize to be O(n*n) instead of (2n*2n) + for (int x = -RANGE; x < RANGE; x++) { + for (int y = -RANGE; y < RANGE; y++) { + if ((x == 0) && (y == 0)) { + continue; + } + + float2 dtr = float2(x, y); + float2 dt = uv_step * dtr; + float4 here = _sdf.Sample(sdfSampler1_1, v_in.uv + dt); + float dst = abs(distance(float2(0., 0.), dtr)) * step; + + if (lowest > (here.g + dst)) { + lowest = here.g + dst; + lowest_source = v_in.uv + dt; + lowest_origin = here.ba; + } + } + } + if (lowest < NEAR_INFINITE) { + outval.g = lowest; + outval.ba = lowest_origin; + } else { + outval.g = self.g + step; + } + } else { + // Outside + // TODO: Optimize to be O(n*n) instead of (2n*2n) + for (int x = -RANGE; x < RANGE; x++) { + for (int y = -RANGE; y < RANGE; y++) { + if ((x == 0) && (y == 0)) { + continue; + } + + float2 dtr = float2(x, y); + float2 dt = uv_step * dtr; + float4 here = _sdf.Sample(sdfSampler1_1, v_in.uv + dt); + float dst = abs(distance(float2(0., 0.), dtr)) * step; + + if (lowest > (here.r + dst)) { + lowest = here.r + dst; + lowest_source = v_in.uv + dt; + lowest_origin = here.ba; + } + } + } + if (lowest < NEAR_INFINITE) { + outval.r = lowest; + outval.ba = lowest_origin; + } else { + outval.r = self.r + step; + } + } + + return outval; +} + technique Draw { pass { vertex_shader = VSDefault(v_in); - pixel_shader = PS_SDFGenerator_v1(v_in); + pixel_shader = PS_SDFGenerator_v1_1(v_in); } } diff --git a/data/effects/sdf-shadow.effect b/data/effects/sdf-shadow.effect index bb868a56..a3e1c856 100644 --- a/data/effects/sdf-shadow.effect +++ b/data/effects/sdf-shadow.effect @@ -1,3 +1,11 @@ +// -------------------------------------------------------------------------------- // +// Defines +#define MAX_DISTANCE 65536.0 +#define NEAR_INFINITE 18446744073709551616.0 +#define FLT_SMALL 0.001 + +// -------------------------------------------------------------------------------- // + // OBS Default uniform float4x4 ViewProj; @@ -14,15 +22,21 @@ uniform float2 _outer_offset; uniform float4 _outer_color; uniform float _threshold; -#define NEAR_INFINITE 18446744073709551616.0 - sampler_state sdfSampler { - Filter = Trilinear; + Filter = Linear; AddressU = Clamp; AddressV = Clamp; }; + +sampler_state sdfSampler1_1 { + Filter = Linear; + AddressU = Border; + AddressV = Border; + BorderColor = FFFF0000; +}; + sampler_state imageSampler { - Filter = Trilinear; + Filter = Linear; AddressU = Clamp; AddressV = Clamp; }; @@ -48,7 +62,7 @@ VertDataOut VSDefault(VertDataIn v_in) float4 PS_SDFShadow_v1(VertDataOut v_in) : TARGET { float4 final = _image.Sample(imageSampler, v_in.uv); - + if (_inner_max > 0 && final.a >= _threshold) { float inner_dist = _sdf.Sample(sdfSampler, v_in.uv + _inner_offset).g; float range = (_inner_max - _inner_min); @@ -65,11 +79,77 @@ float4 PS_SDFShadow_v1(VertDataOut v_in) : TARGET return final; } +float4 PS_SDFShadow_v1_1(VertDataOut v_in) : TARGET +{ + // V1.1: + // - No longer clipping off image using _threshold. + // - Inverse Gradient supported (max < min) + // - Negative Gradient support (min/max < 0) + + // Support for inverse Gradient (Outer Shadow): Maximum < Minimum + // + // Min=4.00, Max=0.00: + // Expected: Max is fully visible, Min and higher is fully shadowed. + // d=0.5 + // d = d - 4.00 (= -3.5) + // d = d / 4.00 (= -0.875, 87.5%) + // d is 87.5% visible + // Normal: + // Min=0.00, Max=4.00: + // d=0.5 + // d = d - 0.00 (= 0.5) + // d = d / 4.00 (= 0.125, 12.5%) + // d is 12.5% visible + + float4 final = float4(0., 0., 0., 0.); + float4 base = _image.Sample(imageSampler, v_in.uv); + + //! Outer Shadow + // Are we allowed to draw an outer shadow? + float2 outer_sdf = _sdf.Sample(sdfSampler, v_in.uv + _outer_offset).rg * float2(MAX_DISTANCE, MAX_DISTANCE); + if ((_outer_color.a > 0.) && (outer_sdf.r < MAX_DISTANCE)) { + // Calculate the true distance value: + // - If we are outside, this will be positive. + // - If we are inside, this will be negative. + float sdf_distance = outer_sdf.r - outer_sdf.g; + + // Calculate the delta. + float delta = _outer_max - _outer_min; + float t1 = sdf_distance - _outer_min; + float t2 = clamp(t1 / delta, 0., 1.); + + final = lerp(final, _outer_color, 1. - t2); + } + + // Base Image + final += base; + + //! Inner Shadow + // Are we allowed to draw an inner shadow? + float2 inner_sdf = _sdf.Sample(sdfSampler, v_in.uv + _inner_offset).rg * float2(MAX_DISTANCE, MAX_DISTANCE); + if ((_inner_color.a > 0.) && (inner_sdf.g < MAX_DISTANCE) && (inner_sdf.r <= FLT_SMALL)) { + // Calculate the true distance value: + // - If we are outside, this will be positive. + // - If we are inside, this will be negative. + float sdf_distance = inner_sdf.g; + + // Calculate the delta. + float delta = _inner_max - _inner_min; + float t1 = sdf_distance - _inner_min; + float t2 = clamp(t1 / delta, 0., 1.); + + // Inner shadow does not affect alpha of image. + final.rgb = lerp(final.rgb, _inner_color.rgb, (1. - t2) * _inner_color.a); + } + + return final; +} + technique Draw { pass { vertex_shader = VSDefault(v_in); - pixel_shader = PS_SDFShadow_v1(v_in); + pixel_shader = PS_SDFShadow_v1_1(v_in); } } diff --git a/source/filter-sdf-effects.cpp b/source/filter-sdf-effects.cpp index 97361560..80b0ba1d 100644 --- a/source/filter-sdf-effects.cpp +++ b/source/filter-sdf-effects.cpp @@ -115,48 +115,54 @@ obs_properties_t* filter::sdf_effects::sdf_effects_instance::get_properties() obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_SHADOW_INNER))); obs_property_set_modified_callback2(p, cb_modified_inside, this); - p = obs_properties_add_float_slider(props, P_SHADOW_INNER_RANGE_MINIMUM, P_TRANSLATE(P_SHADOW_INNER_RANGE_MINIMUM), 0.0, 16.0, - 0.01); + p = obs_properties_add_float_slider(props, P_SHADOW_INNER_RANGE_MINIMUM, P_TRANSLATE(P_SHADOW_INNER_RANGE_MINIMUM), + 0.0, 16.0, 0.01); obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_SHADOW_INNER_RANGE_MINIMUM))); - p = obs_properties_add_float_slider(props, P_SHADOW_INNER_RANGE_MAXIMUM, P_TRANSLATE(P_SHADOW_INNER_RANGE_MAXIMUM), 0.0, 16.0, - 0.01); + p = obs_properties_add_float_slider(props, P_SHADOW_INNER_RANGE_MAXIMUM, P_TRANSLATE(P_SHADOW_INNER_RANGE_MAXIMUM), + 0.0, 16.0, 0.01); obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_SHADOW_INNER_RANGE_MAXIMUM))); - p = obs_properties_add_float_slider(props, P_SHADOW_INNER_OFFSET_X, P_TRANSLATE(P_SHADOW_INNER_OFFSET_X), -100.0, 100.0, 0.01); + p = obs_properties_add_float_slider(props, P_SHADOW_INNER_OFFSET_X, P_TRANSLATE(P_SHADOW_INNER_OFFSET_X), -100.0, + 100.0, 0.01); obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_SHADOW_INNER_OFFSET_X))); - p = obs_properties_add_float_slider(props, P_SHADOW_INNER_OFFSET_Y, P_TRANSLATE(P_SHADOW_INNER_OFFSET_Y), -100.0, 100.0, 0.01); + p = obs_properties_add_float_slider(props, P_SHADOW_INNER_OFFSET_Y, P_TRANSLATE(P_SHADOW_INNER_OFFSET_Y), -100.0, + 100.0, 0.01); obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_SHADOW_INNER_OFFSET_Y))); p = obs_properties_add_color(props, P_SHADOW_INNER_COLOR, P_TRANSLATE(P_SHADOW_INNER_COLOR)); obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_SHADOW_INNER_COLOR))); - p = obs_properties_add_float_slider(props, P_SHADOW_INNER_ALPHA, P_TRANSLATE(P_SHADOW_INNER_ALPHA), 0.0, 100.0, 0.1); + p = obs_properties_add_float_slider(props, P_SHADOW_INNER_ALPHA, P_TRANSLATE(P_SHADOW_INNER_ALPHA), 0.0, 100.0, + 0.1); obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_SHADOW_INNER_ALPHA))); p = obs_properties_add_bool(props, P_SHADOW_OUTER, P_TRANSLATE(P_SHADOW_OUTER)); obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_SHADOW_OUTER))); obs_property_set_modified_callback2(p, cb_modified_outside, this); - p = obs_properties_add_float_slider(props, P_SHADOW_OUTER_RANGE_MINIMUM, P_TRANSLATE(P_SHADOW_OUTER_RANGE_MINIMUM), 0.0, 16.0, - 0.01); + p = obs_properties_add_float_slider(props, P_SHADOW_OUTER_RANGE_MINIMUM, P_TRANSLATE(P_SHADOW_OUTER_RANGE_MINIMUM), + 0.0, 16.0, 0.01); obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_SHADOW_OUTER_RANGE_MINIMUM))); - p = obs_properties_add_float_slider(props, P_SHADOW_OUTER_RANGE_MAXIMUM, P_TRANSLATE(P_SHADOW_OUTER_RANGE_MAXIMUM), 0.0, 16.0, - 0.01); + p = obs_properties_add_float_slider(props, P_SHADOW_OUTER_RANGE_MAXIMUM, P_TRANSLATE(P_SHADOW_OUTER_RANGE_MAXIMUM), + 0.0, 16.0, 0.01); obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_SHADOW_OUTER_RANGE_MAXIMUM))); - p = obs_properties_add_float_slider(props, P_SHADOW_OUTER_OFFSET_X, P_TRANSLATE(P_SHADOW_OUTER_OFFSET_X), -100.0, 100.0, 0.01); + p = obs_properties_add_float_slider(props, P_SHADOW_OUTER_OFFSET_X, P_TRANSLATE(P_SHADOW_OUTER_OFFSET_X), -100.0, + 100.0, 0.01); obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_SHADOW_OUTER_OFFSET_X))); - p = obs_properties_add_float_slider(props, P_SHADOW_OUTER_OFFSET_Y, P_TRANSLATE(P_SHADOW_OUTER_OFFSET_Y), -100.0, 100.0, 0.01); + p = obs_properties_add_float_slider(props, P_SHADOW_OUTER_OFFSET_Y, P_TRANSLATE(P_SHADOW_OUTER_OFFSET_Y), -100.0, + 100.0, 0.01); obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_SHADOW_OUTER_OFFSET_Y))); p = obs_properties_add_color(props, P_SHADOW_OUTER_COLOR, P_TRANSLATE(P_SHADOW_OUTER_COLOR)); obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_SHADOW_OUTER_COLOR))); - p = obs_properties_add_float_slider(props, P_SHADOW_OUTER_ALPHA, P_TRANSLATE(P_SHADOW_OUTER_ALPHA), 0.0, 100.0, 0.1); + p = obs_properties_add_float_slider(props, P_SHADOW_OUTER_ALPHA, P_TRANSLATE(P_SHADOW_OUTER_ALPHA), 0.0, 100.0, + 0.1); obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_SHADOW_OUTER_ALPHA))); return props; @@ -167,23 +173,17 @@ void filter::sdf_effects::sdf_effects_instance::update(obs_data_t* data) this->m_inner_shadow = obs_data_get_bool(data, P_SHADOW_INNER); this->m_inner_range_min = float_t(obs_data_get_double(data, P_SHADOW_INNER_RANGE_MINIMUM)); this->m_inner_range_max = float_t(obs_data_get_double(data, P_SHADOW_INNER_RANGE_MAXIMUM)); - if (this->m_inner_range_max < this->m_inner_range_min) { - std::swap(this->m_inner_range_max, this->m_inner_range_min); - } - this->m_inner_offset_x = float_t(obs_data_get_double(data, P_SHADOW_INNER_OFFSET_X)); - this->m_inner_offset_y = float_t(obs_data_get_double(data, P_SHADOW_INNER_OFFSET_Y)); - this->m_inner_color = (obs_data_get_int(data, P_SHADOW_INNER_COLOR) & 0x00FFFFFF) + this->m_inner_offset_x = float_t(obs_data_get_double(data, P_SHADOW_INNER_OFFSET_X)); + this->m_inner_offset_y = float_t(obs_data_get_double(data, P_SHADOW_INNER_OFFSET_Y)); + this->m_inner_color = (obs_data_get_int(data, P_SHADOW_INNER_COLOR) & 0x00FFFFFF) | (int32_t(obs_data_get_double(data, P_SHADOW_INNER_ALPHA) * 2.55) << 24); this->m_outer_shadow = obs_data_get_bool(data, P_SHADOW_OUTER); this->m_outer_range_min = float_t(obs_data_get_double(data, P_SHADOW_OUTER_RANGE_MINIMUM)); this->m_outer_range_max = float_t(obs_data_get_double(data, P_SHADOW_OUTER_RANGE_MAXIMUM)); - if (this->m_outer_range_max < this->m_outer_range_min) { - std::swap(this->m_outer_range_max, this->m_outer_range_min); - } - this->m_outer_offset_x = float_t(obs_data_get_double(data, P_SHADOW_OUTER_OFFSET_X)); - this->m_outer_offset_y = float_t(obs_data_get_double(data, P_SHADOW_OUTER_OFFSET_Y)); - this->m_outer_color = (obs_data_get_int(data, P_SHADOW_OUTER_COLOR) & 0x00FFFFFF) + this->m_outer_offset_x = float_t(obs_data_get_double(data, P_SHADOW_OUTER_OFFSET_X)); + this->m_outer_offset_y = float_t(obs_data_get_double(data, P_SHADOW_OUTER_OFFSET_Y)); + this->m_outer_color = (obs_data_get_int(data, P_SHADOW_OUTER_COLOR) & 0x00FFFFFF) | (int32_t(obs_data_get_double(data, P_SHADOW_OUTER_ALPHA) * 2.55) << 24); } @@ -203,7 +203,6 @@ void filter::sdf_effects::sdf_effects_instance::deactivate() {} void filter::sdf_effects::sdf_effects_instance::video_tick(float time) { - this->m_tick += time; m_source_rendered = false; } @@ -223,20 +222,26 @@ void filter::sdf_effects::sdf_effects_instance::video_render(gs_effect_t*) } try { + gs_blend_state_push(); + gs_reset_blend_state(); + gs_enable_blending(false); + gs_blend_function(GS_BLEND_ONE, GS_BLEND_ZERO); + + gs_set_cull_mode(GS_NEITHER); + gs_enable_color(true, true, true, true); + gs_enable_depth_test(false); + gs_depth_function(GS_ALWAYS); + gs_enable_stencil_test(false); + gs_enable_stencil_write(false); + gs_stencil_function(GS_STENCIL_BOTH, GS_ALWAYS); + gs_stencil_op(GS_STENCIL_BOTH, GS_ZERO, GS_ZERO, GS_ZERO); + if (!this->m_source_rendered) { // Store input texture. { auto op = m_source_rt->render(baseW, baseH); gs_ortho(0, (float)baseW, 0, (float)baseH, -1, 1); gs_clear(GS_CLEAR_COLOR | GS_CLEAR_DEPTH, &color_transparent, 0, 0); - gs_set_cull_mode(GS_NEITHER); - gs_reset_blend_state(); - gs_enable_blending(false); - gs_blend_function(GS_BLEND_SRCALPHA, GS_BLEND_ZERO); - gs_enable_depth_test(false); - gs_enable_stencil_test(false); - gs_enable_stencil_write(false); - gs_enable_color(true, true, true, true); if (obs_source_process_filter_begin(this->m_self, GS_RGBA, OBS_ALLOW_DIRECT_RENDERING)) { obs_source_process_filter_end(this->m_self, default_effect, baseW, baseH); @@ -266,13 +271,6 @@ void filter::sdf_effects::sdf_effects_instance::video_render(gs_effect_t*) auto op = m_sdf_write->render(baseW, baseH); gs_ortho(0, (float)baseW, 0, (float)baseH, -1, 1); gs_clear(GS_CLEAR_COLOR | GS_CLEAR_DEPTH, &color_transparent, 0, 0); - gs_set_cull_mode(GS_NEITHER); - gs_reset_blend_state(); - gs_enable_blending(false); - gs_enable_depth_test(false); - gs_enable_stencil_test(false); - gs_enable_stencil_write(false); - gs_enable_color(true, true, true, true); sdf_effect->get_parameter("_image").set_texture(this->m_source_texture); sdf_effect->get_parameter("_size").set_float2(float_t(baseW), float_t(baseH)); @@ -291,70 +289,62 @@ void filter::sdf_effects::sdf_effects_instance::video_render(gs_effect_t*) } } - { - std::shared_ptr shadow_effect = - filter::sdf_effects::sdf_effects_factory::get()->get_sdf_shadow_effect(); - if (!shadow_effect) { - throw std::runtime_error("Shadow Effect no loaded"); - } - - gs_set_cull_mode(GS_NEITHER); - gs_reset_blend_state(); - gs_enable_blending(true); - gs_blend_function(GS_BLEND_SRCALPHA, GS_BLEND_INVSRCALPHA); - gs_enable_depth_test(false); - gs_enable_stencil_test(false); - gs_enable_stencil_write(false); - gs_enable_color(true, true, true, true); - - shadow_effect->get_parameter("_sdf").set_texture(this->m_sdf_texture); - shadow_effect->get_parameter("_image").set_texture(this->m_source_texture); - shadow_effect->get_parameter("_threshold").set_float(0.5f); - - if (this->m_inner_shadow) { - shadow_effect->get_parameter("_inner_min").set_float(this->m_inner_range_min); - shadow_effect->get_parameter("_inner_max").set_float(this->m_inner_range_max); - shadow_effect->get_parameter("_inner_offset") - .set_float2(this->m_inner_offset_x / float_t(baseW), this->m_inner_offset_y / float_t(baseH)); - shadow_effect->get_parameter("_inner_color") - .set_float4((this->m_inner_color & 0xFF) / 255.0f, ((this->m_inner_color >> 8) & 0xFF) / 255.0f, - ((this->m_inner_color >> 16) & 0xFF) / 255.0f, - ((this->m_inner_color >> 24) & 0xFF) / 255.0f); - } else { - shadow_effect->get_parameter("_inner_min").set_float(0.); - shadow_effect->get_parameter("_inner_max").set_float(0.); - shadow_effect->get_parameter("_inner_offset").set_float2(0., 0.); - shadow_effect->get_parameter("_inner_color").set_float4(0., 0., 0., 0.); - } - if (this->m_outer_shadow) { - shadow_effect->get_parameter("_outer_min").set_float(this->m_outer_range_min); - shadow_effect->get_parameter("_outer_max").set_float(this->m_outer_range_max); - shadow_effect->get_parameter("_outer_offset") - .set_float2(this->m_outer_offset_x / float_t(baseW), this->m_outer_offset_y / float_t(baseH)); - shadow_effect->get_parameter("_outer_color") - .set_float4((this->m_outer_color & 0xFF) / 255.0f, ((this->m_outer_color >> 8) & 0xFF) / 255.0f, - ((this->m_outer_color >> 16) & 0xFF) / 255.0f, - ((this->m_outer_color >> 24) & 0xFF) / 255.0f); - } else { - shadow_effect->get_parameter("_outer_min").set_float(0.); - shadow_effect->get_parameter("_outer_max").set_float(0.); - shadow_effect->get_parameter("_outer_offset").set_float2(0., 0.); - shadow_effect->get_parameter("_outer_color").set_float4(0., 0., 0., 0.); - } - - while (gs_effect_loop(shadow_effect->get_object(), "Draw")) { - gs_draw_sprite(this->m_source_texture->get_object(), 0, baseW, baseH); - } - } + gs_blend_state_pop(); } catch (...) { - gs_reset_blend_state(); - gs_enable_depth_test(false); + gs_blend_state_pop(); obs_source_skip_video_filter(this->m_self); return; } - gs_reset_blend_state(); - gs_enable_depth_test(false); + try { + std::shared_ptr shadow_effect = + filter::sdf_effects::sdf_effects_factory::get()->get_sdf_shadow_effect(); + if (!shadow_effect) { + throw std::runtime_error("Shadow Effect no loaded"); + } + + shadow_effect->get_parameter("_sdf").set_texture(this->m_sdf_texture); + shadow_effect->get_parameter("_image").set_texture(this->m_source_texture); + shadow_effect->get_parameter("_threshold").set_float(0.5f); + + if (this->m_inner_shadow) { + shadow_effect->get_parameter("_inner_min").set_float(this->m_inner_range_min); + shadow_effect->get_parameter("_inner_max").set_float(this->m_inner_range_max); + shadow_effect->get_parameter("_inner_offset") + .set_float2(this->m_inner_offset_x / float_t(baseW), this->m_inner_offset_y / float_t(baseH)); + shadow_effect->get_parameter("_inner_color") + .set_float4((this->m_inner_color & 0xFF) / 255.0f, ((this->m_inner_color >> 8) & 0xFF) / 255.0f, + ((this->m_inner_color >> 16) & 0xFF) / 255.0f, + ((this->m_inner_color >> 24) & 0xFF) / 255.0f); + } else { + shadow_effect->get_parameter("_inner_min").set_float(0.); + shadow_effect->get_parameter("_inner_max").set_float(0.); + shadow_effect->get_parameter("_inner_offset").set_float2(0., 0.); + shadow_effect->get_parameter("_inner_color").set_float4(0., 0., 0., 0.); + } + if (this->m_outer_shadow) { + shadow_effect->get_parameter("_outer_min").set_float(this->m_outer_range_min); + shadow_effect->get_parameter("_outer_max").set_float(this->m_outer_range_max); + shadow_effect->get_parameter("_outer_offset") + .set_float2(this->m_outer_offset_x / float_t(baseW), this->m_outer_offset_y / float_t(baseH)); + shadow_effect->get_parameter("_outer_color") + .set_float4((this->m_outer_color & 0xFF) / 255.0f, ((this->m_outer_color >> 8) & 0xFF) / 255.0f, + ((this->m_outer_color >> 16) & 0xFF) / 255.0f, + ((this->m_outer_color >> 24) & 0xFF) / 255.0f); + } else { + shadow_effect->get_parameter("_outer_min").set_float(0.); + shadow_effect->get_parameter("_outer_max").set_float(0.); + shadow_effect->get_parameter("_outer_offset").set_float2(0., 0.); + shadow_effect->get_parameter("_outer_color").set_float4(0., 0., 0., 0.); + } + + while (gs_effect_loop(shadow_effect->get_object(), "Draw")) { + gs_draw_sprite(this->m_source_texture->get_object(), 0, baseW, baseH); + } + } catch (...) { + obs_source_skip_video_filter(this->m_self); + return; + } } filter::sdf_effects::sdf_effects_factory::sdf_effects_factory() diff --git a/source/filter-sdf-effects.hpp b/source/filter-sdf-effects.hpp index aa67d742..a40446f5 100644 --- a/source/filter-sdf-effects.hpp +++ b/source/filter-sdf-effects.hpp @@ -95,9 +95,7 @@ namespace filter { // Distance Field std::shared_ptr m_sdf_write, m_sdf_read; std::shared_ptr m_sdf_texture; - - float_t m_tick = 0.; - + bool m_inner_shadow; float_t m_inner_range_min; float_t m_inner_range_max;