The Developer’s Cry

Yet another blog by a hobbyist programmer

FTGL font rendering in multiple colors

In my last post, I was talking about font rendering in OpenGL by using the FTGL library. What I really wanted to have, however, was displaying a font with multiple colors. That is something FTGL can not do directly out of the box, but you can use a trick. Here’s a short description of two methods to display text using multiple colors per character.

Method 1: Use a texture

The GLPolygonFont can be textured. Just bind your texture and call ftglRenderFont(). It really is as simple as that. The texture will stretch over the entire text drawn; if you want a texture per character then you will have to render the characters one by one. Mind that texture is laid over the bounds of the text. The bounds are usually a bit wider than you may expect. This example image was created using an image of a gradient as texture:

A drawback of using GLPolygonFont is that it has lower performance than for example the GLBufferFont. Also, at low resolutions you will see jagged edges.

Method 2: Using the stencil buffer

OpenGL’s stencil buffer can be used for masking. You can tell OpenGL to draw where the stencil buffer is empty, or where the stencil is black. So to draw text in two colors, first draw one color, then draw a shape in the stencil buffer, and then draw the second color. It works a bit like woodcut printing in multiple colors. This example image was created using a GLBufferFont and the stencil buffer:

A drawback of the stencil buffer is that you will see jagged edges if you make a slanted line in the buffer. (It doesn’t really show in this image, but they are there. The stencil buffer creates “hard” pixels.)

The stencil buffer is easy to use. The code for creating the image above is like this:

glColor4f(1, 0, 0, 1);
ftglRenderFont(font, "World", FTGL_RENDER_ALL);

glEnable(GL_STENCIL_TEST);
glClear(GL_STENCIL_BUFFER_BIT);
glStencilFunc(GL_NEVER, 0, 0);
glStencilOp(GL_INCR, GL_INCR, GL_INCR);

... draw triangle (in stencil buffer) ...

glStencilFunc(GL_EQUAL, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);

glColor4f(1, 1, 0, 1);
ftglRenderFont(font, "World", FTGL_RENDER_ALL);
glDisable(GL_STENCIL_TEST);

The stencil buffer can also be used to other cool stuff like making holes in your text, or drawing text as a mask. [By the way, mind that masking using blending is near impossible using FTGL—ftglRenderFont() sets the glBlendFunc() for its own purposes.]

Concluding

I’ve shown two ways of rendering text in multiple colors. Both have pros and cons. Of course, there is a third method; use textures. If your text is static then you might as well use a single texture for the text. If your text is not static, you can still use one texture per character (glyph) but you lose the benefits that FTGL gives you.