From ccc4c6ea2252ddf3c06fe8d732b732a19db0b7d6 Mon Sep 17 00:00:00 2001 From: Michael Fabian 'Xaymar' Dirks Date: Tue, 28 May 2019 02:50:03 +0200 Subject: [PATCH] filter-sdf-effects: Fix and improve effect rendering Fixes the bug that rendering an outline would remove all other effects not directly under the outline, while also improving the rendering speed drastically by only initializing and clearing the rendertarget once instead of for each effect. --- data/effects/sdf/sdf-consumer.effect | 15 +-- source/filters/filter-sdf-effects.cpp | 128 ++++++-------------------- 2 files changed, 31 insertions(+), 112 deletions(-) diff --git a/data/effects/sdf/sdf-consumer.effect b/data/effects/sdf/sdf-consumer.effect index 3aea77f4..ae09a87f 100644 --- a/data/effects/sdf/sdf-consumer.effect +++ b/data/effects/sdf/sdf-consumer.effect @@ -256,16 +256,9 @@ uniform float pOutlineSharpnessInverse < float4 PSOutline(VertDataOut v_in) : TARGET { - // Sample Input and SDF - float4 tex_input = pImageTexture.Sample(imageSampler, v_in.uv); - float4 tex_sdf = pSDFTexture.Sample(sdfSampler, v_in.uv); - - // Expand SDF range to full. - float2 sdf = tex_sdf.rg * float2(MAX_DISTANCE, MAX_DISTANCE); - - // Calculate distance. - float dist = sdf.r - sdf.g; - + float2 iodist = pSDFTexture.Sample(sdfSampler, v_in.uv).rg * MAX_DISTANCE; + float dist = iodist.r - iodist.g; + // Calculate where we are in the outline. // We can use any of the following gradient functions: https://www.desmos.com/calculator/bmbrncaiem /// Base Curve @@ -279,7 +272,7 @@ float4 PSOutline(VertDataOut v_in) : TARGET // Blend by Color.a so that our outline doesn't delete information. float l = 1.0 - ((1.0 - y1) * pOutlineColor.a); - return lerp(pOutlineColor, tex_input, l); + return float4(pOutlineColor.r, pOutlineColor.g, pOutlineColor.b, pOutlineColor.a * (1.0 - y1)); } technique Outline diff --git a/source/filters/filter-sdf-effects.cpp b/source/filters/filter-sdf-effects.cpp index c45b758f..97f3f8bd 100644 --- a/source/filters/filter-sdf-effects.cpp +++ b/source/filters/filter-sdf-effects.cpp @@ -775,32 +775,24 @@ void filter::sdf_effects::sdf_effects_instance::video_render(gs_effect_t* effect // Inner Glow // Outline - { // Normal Source + // Optimized Render path. + try { + auto op = this->m_output_rt->render(baseW, baseH); + gs_ortho(0, 1, 0, 1, 0, 1); + gs_enable_blending(false); gs_blend_function(GS_BLEND_ONE, GS_BLEND_ZERO); - auto param = gs_effect_get_param_by_name(default_effect, "image"); if (param) { gs_effect_set_texture(param, this->m_output_texture->get_object()); } - - { - auto op = this->m_output_rt->render(baseW, baseH); - gs_ortho(0, 1, 0, 1, 0, 1); - while (gs_effect_loop(default_effect, "Draw")) { - gs_draw_sprite(0, 0, 1, 1); - } + while (gs_effect_loop(default_effect, "Draw")) { + gs_draw_sprite(0, 0, 1, 1); } - // Flip Buffers - m_output_rt->get_texture(this->m_output_texture); - } - - if (m_outer_shadow) { - try { - gs_enable_blending(true); - gs_blend_function_separate(GS_BLEND_SRCALPHA, GS_BLEND_DSTALPHA, GS_BLEND_ONE, GS_BLEND_ONE); - + gs_enable_blending(true); + gs_blend_function_separate(GS_BLEND_SRCALPHA, GS_BLEND_INVSRCALPHA, GS_BLEND_ONE, GS_BLEND_ONE); + if (this->m_outer_shadow) { consumer_effect->get_parameter("pSDFTexture").set_texture(this->m_sdf_texture); consumer_effect->get_parameter("pSDFThreshold").set_float(this->m_sdf_threshold); consumer_effect->get_parameter("pImageTexture").set_texture(this->m_source_texture->get_object()); @@ -810,26 +802,11 @@ void filter::sdf_effects::sdf_effects_instance::video_render(gs_effect_t* effect consumer_effect->get_parameter("pShadowOffset") .set_float2(this->m_outer_shadow_offset_x / float_t(baseW), this->m_outer_shadow_offset_y / float_t(baseH)); - - { - auto op = this->m_output_rt->render(baseW, baseH); - gs_ortho(0, 1, 0, 1, 0, 1); - while (gs_effect_loop(consumer_effect->get_object(), "ShadowOuter")) { - gs_draw_sprite(0, 0, 1, 1); - } + while (gs_effect_loop(consumer_effect->get_object(), "ShadowOuter")) { + gs_draw_sprite(0, 0, 1, 1); } - - // Flip Buffers - m_output_rt->get_texture(this->m_output_texture); - } catch (...) { } - } - - if (m_inner_shadow) { - try { - gs_enable_blending(true); - gs_blend_function_separate(GS_BLEND_SRCALPHA, GS_BLEND_INVSRCALPHA, GS_BLEND_ONE, GS_BLEND_ONE); - + if (this->m_inner_shadow) { consumer_effect->get_parameter("pSDFTexture").set_texture(this->m_sdf_texture); consumer_effect->get_parameter("pSDFThreshold").set_float(this->m_sdf_threshold); consumer_effect->get_parameter("pImageTexture").set_texture(this->m_source_texture->get_object()); @@ -839,26 +816,11 @@ void filter::sdf_effects::sdf_effects_instance::video_render(gs_effect_t* effect consumer_effect->get_parameter("pShadowOffset") .set_float2(this->m_inner_shadow_offset_x / float_t(baseW), this->m_inner_shadow_offset_y / float_t(baseH)); - - { - auto op = this->m_output_rt->render(baseW, baseH); - gs_ortho(0, 1, 0, 1, 0, 1); - while (gs_effect_loop(consumer_effect->get_object(), "ShadowInner")) { - gs_draw_sprite(0, 0, 1, 1); - } + while (gs_effect_loop(consumer_effect->get_object(), "ShadowInner")) { + gs_draw_sprite(0, 0, 1, 1); } - - // Flip Buffers - m_output_rt->get_texture(this->m_output_texture); - } catch (...) { } - } - - if (m_outer_glow) { - try { - gs_enable_blending(true); - gs_blend_function_separate(GS_BLEND_SRCALPHA, GS_BLEND_DSTALPHA, GS_BLEND_ONE, GS_BLEND_ONE); - + if (this->m_outer_glow) { consumer_effect->get_parameter("pSDFTexture").set_texture(this->m_sdf_texture); consumer_effect->get_parameter("pSDFThreshold").set_float(this->m_sdf_threshold); consumer_effect->get_parameter("pImageTexture").set_texture(this->m_source_texture->get_object()); @@ -866,26 +828,11 @@ void filter::sdf_effects::sdf_effects_instance::video_render(gs_effect_t* effect consumer_effect->get_parameter("pGlowWidth").set_float(this->m_outer_glow_width); consumer_effect->get_parameter("pGlowSharpness").set_float(this->m_outer_glow_sharpness); consumer_effect->get_parameter("pGlowSharpnessInverse").set_float(this->m_outer_glow_sharpness_inv); - - { - auto op = this->m_output_rt->render(baseW, baseH); - gs_ortho(0, 1, 0, 1, 0, 1); - while (gs_effect_loop(consumer_effect->get_object(), "GlowOuter")) { - gs_draw_sprite(0, 0, 1, 1); - } + while (gs_effect_loop(consumer_effect->get_object(), "GlowOuter")) { + gs_draw_sprite(0, 0, 1, 1); } - - // Flip Buffers - m_output_rt->get_texture(this->m_output_texture); - } catch (...) { } - } - - if (m_inner_glow) { - try { - gs_enable_blending(true); - gs_blend_function_separate(GS_BLEND_SRCALPHA, GS_BLEND_INVSRCALPHA, GS_BLEND_ONE, GS_BLEND_ONE); - + if (this->m_inner_glow) { consumer_effect->get_parameter("pSDFTexture").set_texture(this->m_sdf_texture); consumer_effect->get_parameter("pSDFThreshold").set_float(this->m_sdf_threshold); consumer_effect->get_parameter("pImageTexture").set_texture(this->m_source_texture->get_object()); @@ -893,26 +840,11 @@ void filter::sdf_effects::sdf_effects_instance::video_render(gs_effect_t* effect consumer_effect->get_parameter("pGlowWidth").set_float(this->m_inner_glow_width); consumer_effect->get_parameter("pGlowSharpness").set_float(this->m_inner_glow_sharpness); consumer_effect->get_parameter("pGlowSharpnessInverse").set_float(this->m_inner_glow_sharpness_inv); - - { - auto op = this->m_output_rt->render(baseW, baseH); - gs_ortho(0, 1, 0, 1, 0, 1); - while (gs_effect_loop(consumer_effect->get_object(), "GlowInner")) { - gs_draw_sprite(0, 0, 1, 1); - } + while (gs_effect_loop(consumer_effect->get_object(), "GlowInner")) { + gs_draw_sprite(0, 0, 1, 1); } - - // Flip Buffers - m_output_rt->get_texture(this->m_output_texture); - } catch (...) { } - } - - if (m_outline) { - try { - gs_enable_blending(true); - gs_blend_function_separate(GS_BLEND_SRCALPHA, GS_BLEND_INVSRCALPHA, GS_BLEND_ONE, GS_BLEND_ONE); - + if (this->m_outline) { consumer_effect->get_parameter("pSDFTexture").set_texture(this->m_sdf_texture); consumer_effect->get_parameter("pSDFThreshold").set_float(this->m_sdf_threshold); consumer_effect->get_parameter("pImageTexture").set_texture(this->m_source_texture->get_object()); @@ -921,21 +853,15 @@ void filter::sdf_effects::sdf_effects_instance::video_render(gs_effect_t* effect consumer_effect->get_parameter("pOutlineOffset").set_float(this->m_outline_offset); consumer_effect->get_parameter("pOutlineSharpness").set_float(this->m_outline_sharpness); consumer_effect->get_parameter("pOutlineSharpnessInverse").set_float(this->m_outline_sharpness_inv); - - { - auto op = this->m_output_rt->render(baseW, baseH); - gs_ortho(0, 1, 0, 1, 0, 1); - while (gs_effect_loop(consumer_effect->get_object(), "Outline")) { - gs_draw_sprite(0, 0, 1, 1); - } + while (gs_effect_loop(consumer_effect->get_object(), "Outline")) { + gs_draw_sprite(0, 0, 1, 1); } - - // Flip Buffers - m_output_rt->get_texture(this->m_output_texture); - } catch (...) { } + } catch (...) { } + this->m_output_rt->get_texture(this->m_output_texture); + gs_blend_state_pop(); this->m_output_rendered = true; }