Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make Outer Glow Effect using HLSL?

Tags:

wpf

hlsl

In WPF OuterGlowBitmapEffect is no longer supported nor rendered by Net4.0. DropShadow has a little in common and not acceptable in my case. My initial goal is to make a white blurry background for black ClearType text upon AeroGlass window to make it more readable on a dark scenes. I started to play with fx and HLSL. It is quite interesting and powerful but I still can not get closer to OuterGlowBitmapEffect.

My current dummy version that reflects the idea:

sampler2D  Sampler : register(S0);
#define PI 3.14f
float4 main(float2 uv : TEXCOORD) : COLOR
{
    float4 px = tex2D(Sampler, uv);

    /*
    if (px.a > 0.9)
    {
        return px;
    }
    */

    const float d = 3;

    int cnt = 0;
    float a = 0;
    for (float x = -0.1*d; x < 0.1*d; x += 0.05*d)
    {
        a += tex2D(Sampler, uv + float2(x, 0)).a;
        a += tex2D(Sampler, uv + float2(0, x)).a;
        a += tex2D(Sampler, uv + x).a;
        cnt += 3;
    }
    a /= cnt;

    float4 s = a;

    float4 r = float4(px.rgb*px.a + s.rgb*(1-px.a), max(px.a, a));

    return r;
}

BTW: can I get a HLSL source for DropShadowEffect to use it as a reference? Can someone point me to an OuterGlowEffect algorithm in any language?

NOTE: Windows 7 Aero Glass title bar have such effect to make title more readable! That exactly what I'd like to have for my text on other parts of window (DwmExtendFrameIntoClientArea applied) Aero Glass Window Title

like image 525
Dmitry Gusarov Avatar asked Oct 22 '22 18:10

Dmitry Gusarov


1 Answers

The general idea is to render the white text first, then blur it. And finally to use the blurred white text as the background image for the black text.

Your shader is a correct blur, but it's somewhat inefficient (redundant samples for x=0, for example). You can create a good large blur with two passes: one horizontal and one vertical blur. HLSL code:

float4 PS_BlurHorizontal( float2 Tex : TEXCOORD0 ) : COLOR0
{
    float Color = 0.0f;

    Color += tex2D(sampler, float2(Tex.x - 3.0*blurSizeX, Tex.y)) * 0.09f;
    Color += tex2D(sampler, float2(Tex.x - 2.0*blurSizeX, Tex.y)) * 0.11f;
    Color += tex2D(sampler, float2(Tex.x - blurSizeX, Tex.y)) * 0.18f;
    Color += tex2D(sampler, Tex) * 0.24f;
    Color += tex2D(sampler, float2(Tex.x + blurSizeX, Tex.y)) * 0.18f;
    Color += tex2D(sampler, float2(Tex.x + 2.0*blurSizeX, Tex.y)) * 0.11f;
    Color += tex2D(sampler, float2(Tex.x + 3.0*blurSizeX, Tex.y)) * 0.09f;

    return Color;
}

float4 PS_BlurVertical( float2 Tex : TEXCOORD0 ) : COLOR0
{
    float Color = 0.0f;

    Color += tex2D(sampler, float2(Tex.x, Tex.y - 3.0*blurSizeY)) * 0.09f;
    Color += tex2D(sampler, float2(Tex.x, Tex.y - 2.0*blurSizeY)) * 0.11f;
    Color += tex2D(sampler, float2(Tex.x, Tex.y - blurSizeY)) * 0.18f;
    Color += tex2D(sampler, Tex) * 0.24f;
    Color += tex2D(sampler, float2(Tex.x, Tex.y + blurSizeY)) * 0.18f;
    Color += tex2D(sampler, float2(Tex.x, Tex.y + 2.0*blurSizeY)) * 0.11f;
    Color += tex2D(sampler, float2(Tex.x, Tex.y + 3.0*blurSizeY)) * 0.09f;

    return Color;
}
// weights: 0.09 + 0.11 + 0.18 + 0.24 + 0.18 + 0.11 + 0.9 = 1
// By default, weigths are symmetrical and sum up to 1,
// but they don't necessarily have to.
// You can change the weights to create more fancy results.

These two 7-sample passes simulate a 7x7 gaussian blur (14 samples instead of 49). You can use more samples to improve the result (make blur wider) or just adjust the weights to create more soft look.

like image 81
miloszmaki Avatar answered Nov 01 '22 13:11

miloszmaki