Vector Fonts

The VectorFont content processor extracts the curves that make up the characters from a .ttf file and interpolates a series of points along the contour of each character. Then it tessellates these points to end up with a polygon mesh that can be used to draw the character filled.

These informations are then written into an .xnb that can be used by the Nuclex.Fonts library to draw 3D text on the PC or XBox 360 nearly without any overhead (believe it or not, it's faster than rendering text using the SpriteBatch class!)

Vector fonts look ugly at small sizes (there's a lot of tricks and involved and .ttf files even store hints to make .ttf fonts look good at small sizes!), but they're ideal for big flashy menus, animated credits or Final Fantasy-like damage displays.






To add 3D vector fonts to your project, this is what you have to do:
  • Add references to Nuclex.Fonts and Nuclex.Graphics libraries in your project
  • Add a reference to Nuclex.Fonts.Content.TrueTypeImporter in your Content project
  • Select the VectorFont content processor for any of your .spritefont files ''(these files contain XML code describing the font to import -- my VectorFont importer uses the same files, for your utmost convenience :D)''
  • Use the Nuclex.Fonts library in your code to render the text

The fourth step probably requires some elaboration:

1. Make sure you have imported the Nuclex.Fonts and Nuclex.Graphics namespaces
using Nuclex.Fonts;
using Nuclex.Graphics;

2. Just like when you use a sprite font, you will need a VectorFont field to store the loaded asset
/// <summary>Renderable vector font imported from Arial.ttf</summary>
private VectorFont arialVectorFont;

3. The vector font is loaded normally through your ContentManager like this:
this.arialVectorFont = this.content.Load<VectorFont>("Content/Fonts/Arial");

4. Now, because setting up vector text is a bit more CPU intensive than just placing some sprites on the screen, VectorFonts allow you to pregenerate the mesh of a string (and yes, you can retrieve the vertices and indexes of that mesh to use them on your own)
/// <summary>
///   Called when graphics resources need to be loaded. Override this
///   method to load any component-specific graphics resources.
/// </summary>
protected override void LoadContent() {
  this.arialVectorFont = this.content.Load<VectorFont>("Content/Fonts/Arial");

  // Generates vertices and indices to render the string outlined
  //this.helloWorldText = this.arial24vector.Outline("Hello World!");

  // Generates vertices and indices to render the string filled
  //this.helloWorldText = this.arial24vector.Fill("Hello World!");

  // Generates vertices and indices to render the string extruded (3D)
  this.helloWorldText = this.arial24vector.Extrude("Hello World!");

/// <summary>Cached mesh data for the "hello world" vector font text</summary>
private Text helloWorldText;

5. Now we've got a text mesh and need to render it. If you don't want to write your own code to do that, Nuclex.Fonts provides a neat class named TextBatch that works almost like the SpriteBatch but renders text meshes
/// <summary>
///   Called when graphics resources need to be loaded. Override this method to load
///   any component-specific graphics resources.
/// </summary>
protected override void LoadContent() {
  // ...
  this.spriteBatch = new SpriteBatch(;
  this.textBatch = new TextBatch(;

/// <summary>Batches text rendering calls</summary>
private TextBatch textBatch;

6. Phew, now we can finally get the text on the screen
/// <summary>This is called when the game should draw itself</summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime) {
  // ...

  this.textBatch.ViewProjection = *;
    this.helloWorldText, // text mesh to render
    textTransform, // transformation matrix (scale + position)
    Color.White // text color

The TextBatch gives you easy results, but for advanced uses, you might want to access the text's .Vertices and .Indices properties providing you with everything you need to set up your own VertexBuffer and get going.

Last edited Sep 23, 2009 at 1:14 PM by Cygon, version 7


Bernybon Mar 6, 2013 at 5:37 AM 
It's for unit test.
They may have forgot to disable it in your release.

dent Jan 11, 2010 at 9:06 AM 
Hey! Thanks for this! Great Work!
This was exactly what i´m searching for. Saves a lot of time.

But i had to add a reference to nunit if i want to get the TrueTypeImporter to run. Why is that?

Greetings and thanks again!