Skip to content

bbredesen/ttf-renderer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ttf-renderer

This mini-Vulkan app written in Go demonstrates usage of a stencil buffer to render text from a TrueType font file.

There are three graphics pipelines bound across two rendering subpasses. The first pipeline fills the body of the glyph (and knocks out interior areas) by drawing a triangle fan across the vertices of the glyph. TrueType specifies a clockwise winding rule. For example, on an 'O' character, there is an outer polygon with the vertices given in clockwise order, and an inner polygon going counter-clockwise.

The stencil test leverages this winding rule by incrementing the stencil value for front facing triangles, and decrementing for back facing triangles. If you were to insepect the stencil after this phase, glyphs would be recognizable, but very blocky.

The second pipeline fills in the curves of the glyph. Triangles are drawn between each sequential pair of vertices, along with the control point for that segment. The shader uses barymetric coordinates of each fragment to determine if that fragment should be discarded or drawn in the stencil. (See quad_shader.frag)

In the second subpass, a color attachment is added and a square representing the bounds of the glyph is drawn and tested against the stencil.

Usage

Run go generate in the project root to compile the shaders before running. Requires the glsc compiler, bundled with the Vulkan SDK.

Pass a TTF font filepath with the -font flag, or set the character to render with -char.

Known Issues

  • The stencil is tested against a pair of triangles matching the glyph bounds provided by sfnt. There are several font/glyph combinations that are not getting bounds from sfnt, or getting bounds that are far too small. The net effect is just a blank screen. It seems to be more common with non-letter glyphs in display fonts. For example, see:

    • Elephant - &
    • Algerian - $

    I have not investigated if this is coming from the font file or a bug in sfnt

  • "320" is hard-coded in several places, notably the shaders. This is half of the em-width requested from sfnt. (sfnt modifies the glyph bounds for better visuals based on the requested rendering size.) I arbitrarily chose an em-width of 640 pixels per em, labeled ppem in the code) to minimize the effect. The fix is to get the true curves from the TTF files and scaling proprtionately, instead of relying on sfnt.

Next Steps

  • Live rendering a string, not just a single glyph. This is a slipery slope into typography.
  • Background rendering the full font (or a subset) to texture memory on the GPU, then being able to print text with a bunch of textured quads.
    • Also, each glyph could be generated as a mipmap. Take note of the ppem parameter passed to sfnt.

About

Glyph rendering in Go + Vulkan via stencils.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published