Monday, May 16, 2016

c++ - Font outline in OpenGL, FTGL


I'm using FTGL library to render fonts in my game, but I have completely no idea how to create an outline around text. Achieving a shadow could be easy, because I can simply do it like this:


(pseudo code)


font.render(Color::BLACK, position.x + 1, position.y + 1); // Shadow
font.render(Color::WHITE, position.x, position.y) // Normal text


But how to create an outline? Unfortunately I haven't found any interesting solutions for it over internet which seemed to me a bit strange, because I thought it's quite popular problem.


Drawing outline with just a bigger font is not a right way, because as I found out, letters just don't match in this case:


enter image description here


So is there any simple way to create an outline for fonts? How do they do it in real games?


Thanks in advance for any answer



Answer



Flexible & Accurate: Filters


Use a texel filter either on the texture on the CPU side, or if you are using programmable pipeline OpenGL, directly in the fragment shader.


The idea of a filter is simply that you run through a 2D loop to process every texel. If it is white, then you run through an inner 2D loop for each of its surrounding pixels in some radius, and adapt accordingly. This is also known as a box filter, though if you include the radius check, it is really a circular filter -- which avoids axis-al artifacting.



A faster way to do this is to precalculate the set of offsets from each central pixel that you check; this way, you needn't run a square root for every pixel surrounding a given pixel. You want to keep complexity down to `O(texWidth*texHeight) rather than O(texWidth*texHeight*filterRadius*filterRadius), in other words.


Easy: Multiple renders


Another way to achieve the effect would be not to scale the text, but instead to render your red outline at each of eight (or more) directions, each slightly offset from the original in that direction:


 \|/
--+--
/|\

By offsetting each of the red versions like this, you would get a fairly uniform outer edge around your original text. Bear in mind that when shifting diagonally, you should use the same vector magnitude as when you shift horizontally or vertically, rather than simply offsetting by the same x and y values (which leads to a approximatlely 1.4x further length -- basic trig).


FYI


This sort of effect is known as dilation, and is sometimes performed via Minkowski Summation, which is the vector-based (continuous) approach to the pixel-based (quantised) box filter I described above.



No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...