SFML community forums

Help => Graphics => Topic started by: Megatron on November 03, 2010, 07:28:33 am

Title: Drawing Text with an outline
Post by: Megatron on November 03, 2010, 07:28:33 am
I was wondering if it's possible to draw a text object so that the font has an outline?

for instance, if I have a white font, I may want to put a thin black border around it to accentuate it. I'd assume it'd be possible via shaders, but I was wondering if there was a way that doesnt rely on shaders.

I'm using the .net bindings for SFML so that may be a possible limitation.

If anyone has an idea how to do this that they could share, that'd be great.

Thanks
Title: Drawing Text with an outline
Post by: inlinevoid on November 03, 2010, 07:35:27 am
Well, you could try wrapping two strings inside your own string class.

Make one string slightly larger then the other, and place it behind the smaller one to give an 'outline' effect.
Title: Drawing Text with an outline
Post by: Laurent on November 03, 2010, 08:06:11 am
No, this is not possible at all sorry.

Quote
Make one string slightly larger then the other, and place it behind the smaller one to give an 'outline' effect.

This will not produce the desired effect ;)
Title: Drawing Text with an outline
Post by: Spodi on November 03, 2010, 08:22:05 am
I personally do this right now by drawing the text 5 times. Draw the background using the offsets of (0,1),(1,0),(0,-1),(-1,0) (up,down,left,right) and then the normal text. Inefficient? You betcha! But it gets the job done.

I have looked into doing this with shaders, but I couldn't find any decent way of doing it without some of the features of newer version of GLSL (namely the ability to look up the size of the texture so you could actually use a pixel scale).
Title: Drawing Text with an outline
Post by: Laurent on November 03, 2010, 08:48:38 am
Quote
namely the ability to look up the size of the texture so you could actually use a pixel scale

If that's the only thing you need, you can send it manually to the shader through a variable.
Title: Drawing Text with an outline
Post by: Spodi on November 03, 2010, 09:00:43 am
Quote from: "Laurent"
Quote
namely the ability to look up the size of the texture so you could actually use a pixel scale

If that's the only thing you need, you can send it manually to the shader through a variable.


That was what I had in mind at first, too, but didn't realize at the time that Font had a GetImage method (clearly I didn't look very hard). Maybe I'll play around with it again and see if I can whip up something.
Title: Drawing Text with an outline
Post by: bastien on November 03, 2010, 09:02:47 am
Wouldn't a font like that work? http://www.dafont.com/bower-shadow.font
Title: Drawing Text with an outline
Post by: Laurent on November 03, 2010, 09:14:05 am
It works as long as you don't want to control the outline width or color.
Title: Drawing Text with an outline
Post by: Spodi on November 03, 2010, 07:36:42 pm
The problem with doing it inside of a font file directly, or applying it to a font using SetPixel, is that you are increasing the amount of memory used to store your fonts. With using a font with outlines built-in, it also introduces a lot more hassle.

Ideally, you want to be able to just say "use outline", and it draws with outlines with no reduction to performance and takes up no extra memory. With shaders, this is likely possible since not many of us are going to be bottlenecked on the fragment processing (unless you are already using some heavy shaders).
Title: Drawing Text with an outline
Post by: Spodi on November 03, 2010, 10:09:18 pm
Well, after a few hours, I managed to come up with something that works decently. Took quite some time to come up with the right algorithm to preserve the alpha values properly.

Code: [Select]
uniform sampler2D tex;
uniform vec2 texSize;
uniform vec4 outlineColor;
void main(void)
{
vec2 off = 1.0 / texSize;
vec2 tc = gl_TexCoord[0].st;

vec4 c = texture2D(tex, tc);
vec4 n = texture2D(tex, vec2(tc.x, tc.y - off.y));
vec4 e = texture2D(tex, vec2(tc.x + off.x, tc.y));
vec4 s = texture2D(tex, vec2(tc.x, tc.y + off.y));
vec4 w = texture2D(tex, vec2(tc.x - off.x, tc.y));

vec4 origColor = c * gl_Color;

float ua = 0.0;
ua = mix(ua, 1.0, c.a);
ua = mix(ua, 1.0, n.a);
ua = mix(ua, 1.0, e.a);
ua = mix(ua, 1.0, s.a);
ua = mix(ua, 1.0, w.a);

vec4 underColor = outlineColor * vec4(ua);

gl_FragColor = underColor;
gl_FragColor = mix(gl_FragColor, origColor, origColor.a);

if (gl_FragColor.a > 0.0)
gl_FragColor.a = 1.0;
}


There is a little issue with the display of the first character. It seems SFML adds a little white block to the top-left corner of a font bitmap, so that ends up making a little artifact display for the first character. In theory, it'll also show artifacts if there are any font characters without padding between them in the font texture. Could get rid of this by just clamping the texture coordinates, but don't know of any way of finding the specified coordinates for the draw call without passing them as a parameter (which would require modifying SFML to update that parameter before each character is drawn).

Edit: Updated the shader. Kinda disappointed in myself for not realizing to take this approach initially. Was too stuck on the idea of recognizing when the edge has been reached.
Title: Drawing Text with an outline
Post by: Megatron on November 07, 2010, 06:36:08 am
Thanks spodi, the way you mentioned before worked, Ill give the shader a try later