XNA Vector Font Renderer

I’ve been fiddling around with font rendering again this weekend. For my upcoming game, I wanted a cool intro effect like in some movies, where the displayed text is very very slowly expanding. But I couldn’t quite replicate that effect with the XNA SpriteFont class. Even with antialiasing turned on, the borders of the text were flickering. Using very large font sizes resulted in hopelessly oversized .xnb files with only a slight improvement for the unsteady borders.

So my new solution was to write a component that renders vector-based text instead of bitmaps. Extracting the vector data from a font was a bit harder than I had expected because fonts consist mostly of complicated second and third order bezier curves. I managed to break these down into plain straight line segments and am now in the possession of a content pipeline importer that converts .ttf fonts into arrays of line segments. Behold:

Screenshot of vector fonts rendered as outlines in 3D

In the upper left is my replacement sprite font importer which can take the place of Microsoft’s own importer by the flip of a combobox. It produces identical .xnb files that can be used with the SpriteFont class, so you can toggle forth and back at will. The upper line is from a font imported with my own importer (using FreeType) and the lower line is from the same font imported with the XNA SpriteFont importer (using Windows Vista .ttf rendering).

The big outlined vector text highlights the separate outlines the characters consist of in the upper line and shows the normal rendered result below. Both outputs have been generated by writing a series of line strips into a vertex buffer and rendering it.

Now filling the characters requires the outlines to be tessellated into a triangle mesh, which is another unexpected complexity I hadn’t thought about when I set out to create a vector font rendering component. But I already took the hurdle by cheating with OpenGL’s gluTess...() routines. Of course, these will only be used in the content pipeline assembly, the final game .exe has zero references to unmanaged code and/or OpenGL.

Update: I completed the GLU tessellator interfacing code and am now proud to announce the near completion of the Nuclex.Fonts VectorFont importer. Once I’m done with the runtime side of things, you can have smooth-zooming text without any blurry pixels or loss of quality, rotating 3D text or just a means of converting strings into vertices for whatever purpose you want.

Screenshot of vector fonts rendered as 3D faces in wireframe mode