From 75009c617a91080ab21ae5fd149cda07c5ef83b8 Mon Sep 17 00:00:00 2001 From: Michael Fabian 'Xaymar' Dirks Date: Wed, 30 Jan 2019 03:12:12 +0100 Subject: [PATCH] filter-sdf-effects: Support for scaling SDF Texture Size This allows increasing or decreasing the accuracy of the Signed Distance Field at runtime without requiring the initial source to be resized. Use case for this would be small text where the higher quality would only be noticable on the shadow and not the text itself. --- data/locale/en-US.ini | 2 + source/filter-sdf-effects.cpp | 71 +++++++++++++++++++++++++---------- source/filter-sdf-effects.hpp | 4 ++ 3 files changed, 58 insertions(+), 19 deletions(-) diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index 15340fb..24f23b1 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -138,6 +138,8 @@ Filter.SDFEffects.Shadow.Outer.Offset.X="Outer Offset X" Filter.SDFEffects.Shadow.Outer.Offset.Y="Outer Offset Y" Filter.SDFEffects.Shadow.Outer.Color="Outer Color" Filter.SDFEffects.Shadow.Outer.Alpha="Outer Alpha" +Filter.SDFEffects.SDF.Scale="SDF Texture Scale" +Filter.SDFEffects.SDF.Scale.Description="Percentage to scale the SDF Texture Size by, relative to the Source Size.\nA higher value results in better quality, but slower updates,\n while lower values result in faster updates, but lower quality." # Filter - Shape Filter.Shape="Shape" diff --git a/source/filter-sdf-effects.cpp b/source/filter-sdf-effects.cpp index 9971e78..2637569 100644 --- a/source/filter-sdf-effects.cpp +++ b/source/filter-sdf-effects.cpp @@ -39,6 +39,8 @@ #define P_SHADOW_OUTER_COLOR "Filter.SDFEffects.Shadow.Outer.Color" #define P_SHADOW_OUTER_ALPHA "Filter.SDFEffects.Shadow.Outer.Alpha" +#define P_SDF_SCALE "Filter.SDFEffects.SDF.Scale" + // Initializer & Finalizer INITIALIZER(filterShadowFactoryInitializer) { @@ -137,21 +139,24 @@ void filter::sdf_effects::sdf_effects_factory::destroy(void* inptr) void filter::sdf_effects::sdf_effects_factory::get_defaults(obs_data_t* data) { - obs_data_set_bool(data, P_SHADOW_INNER, false); - obs_data_set_double(data, P_SHADOW_INNER_RANGE_MINIMUM, 0.0); - obs_data_set_double(data, P_SHADOW_INNER_RANGE_MAXIMUM, 4.0); - obs_data_set_double(data, P_SHADOW_INNER_OFFSET_X, 0.0); - obs_data_set_double(data, P_SHADOW_INNER_OFFSET_Y, 0.0); - obs_data_set_int(data, P_SHADOW_INNER_COLOR, 0x00000000); - obs_data_set_double(data, P_SHADOW_INNER_ALPHA, 100.0); + obs_data_set_default_bool(data, P_SHADOW_INNER, false); + obs_data_set_default_double(data, P_SHADOW_INNER_RANGE_MINIMUM, 0.0); + obs_data_set_default_double(data, P_SHADOW_INNER_RANGE_MAXIMUM, 4.0); + obs_data_set_default_double(data, P_SHADOW_INNER_OFFSET_X, 0.0); + obs_data_set_default_double(data, P_SHADOW_INNER_OFFSET_Y, 0.0); + obs_data_set_default_int(data, P_SHADOW_INNER_COLOR, 0x00000000); + obs_data_set_default_double(data, P_SHADOW_INNER_ALPHA, 100.0); - obs_data_set_bool(data, P_SHADOW_OUTER, false); - obs_data_set_double(data, P_SHADOW_OUTER_RANGE_MINIMUM, 0.0); - obs_data_set_double(data, P_SHADOW_OUTER_RANGE_MAXIMUM, 4.0); - obs_data_set_double(data, P_SHADOW_OUTER_OFFSET_X, 0.0); - obs_data_set_double(data, P_SHADOW_OUTER_OFFSET_Y, 0.0); - obs_data_set_int(data, P_SHADOW_OUTER_COLOR, 0x00000000); - obs_data_set_double(data, P_SHADOW_OUTER_ALPHA, 100.0); + obs_data_set_default_bool(data, P_SHADOW_OUTER, false); + obs_data_set_default_double(data, P_SHADOW_OUTER_RANGE_MINIMUM, 0.0); + obs_data_set_default_double(data, P_SHADOW_OUTER_RANGE_MAXIMUM, 4.0); + obs_data_set_default_double(data, P_SHADOW_OUTER_OFFSET_X, 0.0); + obs_data_set_default_double(data, P_SHADOW_OUTER_OFFSET_Y, 0.0); + obs_data_set_default_int(data, P_SHADOW_OUTER_COLOR, 0x00000000); + obs_data_set_default_double(data, P_SHADOW_OUTER_ALPHA, 100.0); + + obs_data_set_default_bool(data, S_ADVANCED, false); + obs_data_set_default_double(data, P_SDF_SCALE, 100.0); } obs_properties_t* filter::sdf_effects::sdf_effects_factory::get_properties(void* inptr) @@ -235,8 +240,16 @@ bool filter::sdf_effects::sdf_effects_instance::cb_modified_outside(void*, obs_p return true; } +bool filter::sdf_effects::sdf_effects_instance::cb_modified_advanced(void* ptr, obs_properties_t* props, + obs_property* prop, obs_data_t* settings) +{ + bool show_advanced = obs_data_get_bool(settings, S_ADVANCED); + obs_property_set_visible(obs_properties_get(props, P_SDF_SCALE), show_advanced); + return true; +} + filter::sdf_effects::sdf_effects_instance::sdf_effects_instance(obs_data_t* settings, obs_source_t* self) - : m_self(self), m_source_rendered(false) + : m_self(self), m_source_rendered(false), m_sdf_scale(1.0) { this->m_source_rt = std::make_shared(GS_RGBA, GS_ZS_NONE); this->m_sdf_write = std::make_shared(GS_RGBA32F, GS_ZS_NONE); @@ -311,6 +324,13 @@ obs_properties_t* filter::sdf_effects::sdf_effects_instance::get_properties() 0.1); obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_SHADOW_OUTER_ALPHA))); + p = obs_properties_add_bool(props, S_ADVANCED, P_TRANSLATE(S_ADVANCED)); + obs_property_set_long_description(p, P_TRANSLATE(P_DESC(S_ADVANCED))); + obs_property_set_modified_callback2(p, cb_modified_advanced, this); + + p = obs_properties_add_float_slider(props, P_SDF_SCALE, P_TRANSLATE(P_SDF_SCALE), 0.1, 500.0, 0.1); + obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_SDF_SCALE))); + return props; } @@ -331,6 +351,8 @@ void filter::sdf_effects::sdf_effects_instance::update(obs_data_t* data) 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); + + this->m_sdf_scale = double_t(obs_data_get_double(data, P_SDF_SCALE) / 100.0); } uint32_t filter::sdf_effects::sdf_effects_instance::get_width() @@ -413,18 +435,29 @@ void filter::sdf_effects::sdf_effects_instance::video_render(gs_effect_t*) throw std::runtime_error("SDF Effect no loaded"); } + // Scale SDF Size + double_t sdfW, sdfH; + sdfW = baseW * m_sdf_scale; + sdfH = baseH * m_sdf_scale; + if (sdfW <= 1) { + sdfW = 1.0; + } + if (sdfH <= 1) { + sdfH = 1.0; + } + { - auto op = m_sdf_write->render(baseW, baseH); - gs_ortho(0, (float)baseW, 0, (float)baseH, -1, 1); + auto op = m_sdf_write->render(sdfW, sdfH); + gs_ortho(0, (float)sdfW, 0, (float)sdfH, -1, 1); gs_clear(GS_CLEAR_COLOR | GS_CLEAR_DEPTH, &color_transparent, 0, 0); sdf_effect->get_parameter("_image").set_texture(this->m_source_texture); - sdf_effect->get_parameter("_size").set_float2(float_t(baseW), float_t(baseH)); + sdf_effect->get_parameter("_size").set_float2(float_t(sdfW), float_t(sdfH)); sdf_effect->get_parameter("_sdf").set_texture(this->m_sdf_texture); sdf_effect->get_parameter("_threshold").set_float(0.5); while (gs_effect_loop(sdf_effect->get_object(), "Draw")) { - gs_draw_sprite(this->m_sdf_texture->get_object(), 0, baseW, baseH); + gs_draw_sprite(this->m_sdf_texture->get_object(), 0, sdfW, sdfH); } } this->m_sdf_write.swap(this->m_sdf_read); diff --git a/source/filter-sdf-effects.hpp b/source/filter-sdf-effects.hpp index a40446f..3c1a7ec 100644 --- a/source/filter-sdf-effects.hpp +++ b/source/filter-sdf-effects.hpp @@ -95,6 +95,7 @@ namespace filter { // Distance Field std::shared_ptr m_sdf_write, m_sdf_read; std::shared_ptr m_sdf_texture; + double_t m_sdf_scale; bool m_inner_shadow; float_t m_inner_range_min; @@ -115,6 +116,9 @@ namespace filter { static bool cb_modified_outside(void* ptr, obs_properties_t* props, obs_property* prop, obs_data_t* settings); + static bool cb_modified_advanced(void* ptr, obs_properties_t* props, obs_property* prop, + obs_data_t* settings); + public: sdf_effects_instance(obs_data_t* settings, obs_source_t* self); ~sdf_effects_instance();