9
\$\begingroup\$

I'm currently working on a 2D game, and my current task is to outline selected object.

I basically use a blur shader to do it fully runtime. I first draw my sprite using a vertical gaussian blur shader, then I draw it with an horizontal gaussian blur shader, and then I draw my sprite normally.

Here is my blur shader: sampler TextureSampler : register(s0);

#define SAMPLE_COUNT 15

float2 SampleOffsets[SAMPLE_COUNT];
float SampleWeights[SAMPLE_COUNT];


float4 PixelShaderFunction(float2 texCoord : TEXCOORD0) : COLOR0
{
    float4 c = 0;

    // Combine a number of weighted image filter taps.
    for (int i = 0; i < SAMPLE_COUNT; i++)
    {
        c += tex2D(TextureSampler, texCoord + SampleOffsets[i]) * SampleWeights[i];
    }

    return c;
}

SampleOffets are the offsets allowing me to test rounding pixels SampleWeights are weights calculate with gaussian function (http://en.wikipedia.org/wiki/Gaussian_blur)

Here is the result:

enter image description here

It's not that bad, quite smooth, but not enough visible in game... But I'd like to be able to control the thickness (to make it larger), and add a first opaque outline before fading it in alpha (to make it more visible). And i feel like gaussian blur is maybe not as good as I thought for my task :)

Another idea is to generate it automatically from the .png (using a photoshop script to make it automatic). I just need to fill the outline pixels with a custom color, storing the alpha value in the Red component for example, and set all other components to 0. Then I just have to apply a shader which replaces transparent pixels to the color I want

float4 PixelShaderFunction2(float2 texCoord : TEXCOORD0) : COLOR0
{
    float4 color = tex2D(TextureSampler, texCoord);
    float4 newColor = 0;
    if (color.a == 0 && color.r != 0)
    {
        color.a = color.r;
        // Blue outline
        color.b = 1;
    }
}

Problem is, I'm using DXT5 compression for my sprite, so I can't be sure the color I'll get in my shader will be the exact same I wrote. That's why I didn't even try it... Any thoughts?

Any advice would be welcome :)

\$\endgroup\$
3
  • \$\begingroup\$ You ought to be able to control the thickness and alpha drop-off in your shader. Care to post it for reference? \$\endgroup\$ Mar 1, 2013 at 22:21
  • \$\begingroup\$ I used the Gaussian blur shader from this sample: link let me edit my post to show you the shader in details \$\endgroup\$
    – s0ubap
    Mar 1, 2013 at 23:22
  • \$\begingroup\$ I'm not sure Gaussian blur is the right one for you. Try some radial blurring instead. \$\endgroup\$ Mar 2, 2013 at 2:14

3 Answers 3

6
\$\begingroup\$

What you are probably looking for is a form of edge detection before, after, or even before and after your Gaussian blur. Maybe a version of Sobel Edge Detection could work. I know your game is 2D but if the wiki page is too rough here's a tutorial on how to get it working in the UDK that might translate over better.

Your edge detection only really has to find the edges of the alpha channel if you need a speed boost.

\$\endgroup\$
2
  • \$\begingroup\$ Interesting! I tried it. The result was good, except when I zoom in/out... Pixels appear and disappear, resulting in unwanted artifacts... \$\endgroup\$
    – s0ubap
    Mar 2, 2013 at 15:11
  • 1
    \$\begingroup\$ What kind of artifact are you seeing? Can you provide an image? \$\endgroup\$ Mar 4, 2013 at 23:56
2
\$\begingroup\$

What worked for me with text outlining was:

  • Pick the outline colour
  • Draw the text at (x-1, y-1) with outline colour
  • Draw the text at (x+1, y-1) with the outline colour
  • Draw the text at (x-1, y+1) with the outline colour
  • Draw the text at (x+1, y+1) with the outline colour
  • Draw the text at (x, y)

You can do the same thing -- all you need to do is draw the sprite with the opaque pixels coloured with your outline colour. (Maintain transparency values so that round edges still look round).

This works, looks better than drawing a scaled version, and has some other cool properties (like being able to control the outline alpha for boldness, and retaining any "holes" in your sprite image) -- the only drawback is that you can't really control the width of the outline too well.

\$\endgroup\$
1
\$\begingroup\$

I'm kind of new to all of this, but here is my idea:

You could use your texture's alpha channel to make another texture. Any alpha value below a threshold value will be set to fully transparent. Any above will be fully opaque. Using this new texture, you could set the values of RGB to be any color you'd like. Scale this new "texture" to be slightly bigger than your character texture. This would give you a nice solid color around the character. Then use that color with your Gaussian shader to give the nice outlined glow around your created texture. I'm guessing this could be done without creating another texture, and be all shader based off the character texture.

Does this make sense at all?

\$\endgroup\$
1
  • \$\begingroup\$ This method has a major flaw when dealing with non-concave shapes. E.g when applied to a doughnut only outer edge will get an outline. Not to mention other outline thickness distortions. \$\endgroup\$
    – Kromster
    Mar 6, 2013 at 5:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .