8
votes

I'm still working on an image processing project that makes use of HLSL shaders to add Photoshop-esque filters like drop shadow, bevel and so on. Now I'm searching for an approach to implement an outer glow effect in HLSL.

I'm currently experimenting with the following idea:

1) Scale the current texture to create the glow (parameter: glowSize, which sets the size of the outline)

2) Blur horizontal

3) Blur vertical, change color of blur to glow color and add original texture on top

I'm using the following multi pass HLSL shader for rendering the glow:

float4 PS_Scale(VS_OUTPUT IN) : COLOR0
{
    float2 tex = IN.texture0;
    float2 scaleCenter = float2(0.5f, 0.5f);
    float2 scaleTex = (tex - scaleCenter) * glowSize + scaleCenter;
    return tex2D(foreground, scaleTex);
}

float4 PS_GlowH(VS_OUTPUT IN) : COLOR0
{
    float2 Tex = IN.texture0;

    float4 sum = float4(0.0, 0.0, 0.0, 0.0);
    sum += tex2D(secondForeground, float2(Tex.x - 4.0*blur, Tex.y))*0.05;
    sum += tex2D(secondForeground, float2(Tex.x - 3.0*blur, Tex.y))*0.09;
    sum += tex2D(secondForeground, float2(Tex.x - 2.0*blur, Tex.y))*0.12;
    sum += tex2D(secondForeground, float2(Tex.x - blur, Tex.y))*0.15;
    sum += tex2D(secondForeground, float2(Tex.x, Tex.y))*0.16;
    sum += tex2D(secondForeground, float2(Tex.x + blur, Tex.y))*0.15;
    sum += tex2D(secondForeground, float2(Tex.x + 2.0*blur, Tex.y))*0.12;
    sum += tex2D(secondForeground, float2(Tex.x + 3.0*blur, Tex.y))*0.09;
    sum += tex2D(secondForeground, float2(Tex.x + 4.0*blur, Tex.y))*0.05;

    return sum;
}

float4 PS_GlowV(VS_OUTPUT IN) : COLOR0
{
    float2 Tex = IN.texture0;

    float4 sum = float4(0.0, 0.0, 0.0, 0.0);
    sum += tex2D(secondForeground, float2(Tex.x, Tex.y - 4.0*blur))*0.05;
    sum += tex2D(secondForeground, float2(Tex.x, Tex.y - 3.0*blur))*0.09;
    sum += tex2D(secondForeground, float2(Tex.x, Tex.y - 2.0*blur))*0.12;
    sum += tex2D(secondForeground, float2(Tex.x, Tex.y - blur))*0.15;
    sum += tex2D(secondForeground, float2(Tex.x, Tex.y))*0.16;
    sum += tex2D(secondForeground, float2(Tex.x, Tex.y + blur))*0.15;
    sum += tex2D(secondForeground, float2(Tex.x, Tex.y + 2.0*blur))*0.12;
    sum += tex2D(secondForeground, float2(Tex.x, Tex.y + 3.0*blur))*0.09;
    sum += tex2D(secondForeground, float2(Tex.x, Tex.y + 4.0*blur))*0.05;

    float4 result = sum * opacity;
    result.rgb = float3(glowColor.r, glowColor.g, glowColor.b) / 255.0f;

    float4 src = tex2D(foreground, IN.texture0.xy);
    return result * (1-src.a) + src;
}

The outcome of this code looks ok when using simple shapes like an ellipse, but doesn't work when applying the shader on text:

Output of the above shader

It's obvious that there's an issue with the scaling. I don't have any clue how to scale the original texture to use it as an outline. Is that even possible? Any other ideas how to implement an outer glow or outline filter in HLSL?

Thank you in advance.

1

1 Answers

9
votes

Your scaling strategy cannot be applied in this situation. Throw the scaling step away, use only blur steps and the composing step. It will work.

Let me show you how the blur shader creates a glow effect.

A : There is a original image.

Original Image

B : Change the color of the image, and apply the blur shader.

Blurred Image

C : Combine the blurred image with the original image.

Result Image

If you want to control a glow size, use a kernel size of blur steps for that, instead of scaling. I used gaussian blurs to create below images.

  • Kernel Size 5

Gaussian Size 5

  • Kernel Size 10

Gaussian Size 10

  • Kernel Size 15

enter image description here