Font rendering is one of those problems that looks solved until you look closely. Ten years ago, Eric Lengyel at Terathon Software started building Slug, a library that renders TrueType and OpenType glyphs analytically on the GPU, and his recent retrospective is worth sitting with. The post reads as a product anniversary, but the decade it covers maps closely onto how game developers learned that rendering text correctly on the GPU is harder than the widely adopted shortcuts suggest.
What the GPU Sees When It Draws a Letter
To appreciate what Slug does, it helps to understand what a GPU is bad at by default. A TrueType glyph is a vector outline: a series of quadratic Bezier curves that define the boundary between ink and paper. The GPU, by contrast, works in fragments, small rectangular samples of the framebuffer. Mapping one representation to the other is the central challenge of GPU text rendering.
The industry settled on two main strategies before Slug came along. The first is rasterization on the CPU, using libraries like FreeType or platform APIs like DirectWrite and CoreText, which produce pre-rasterized bitmaps at specific sizes. This works well when you know the exact size at which text will appear, but breaks down in 3D scenes where text might be viewed at any distance, or in UIs that need to scale arbitrarily.
The second strategy is signed distance fields, popularized by Chris Green’s 2007 SIGGRAPH paper from Valve on alpha-tested magnification for vector textures. An SDF texture stores, for each texel, the distance to the nearest glyph outline edge. In the fragment shader, you sample this texture and threshold at zero to determine inside from outside, applying a smoothstep curve around the boundary for anti-aliasing. SDF is cheap at runtime, scales reasonably well, and became the dominant approach for game text rendering through the 2010s.
But SDF has visible limits. Sharp corners, the pointed apex of an “A” or the inner corner of a “k”, get rounded because the distance field cannot represent a sharp discontinuity at arbitrary scale. SDF also degrades when rendered at sizes far from the precomputed resolution. Multi-channel SDF, developed by Viktor Chlumský and released as msdfgen, partially addresses corners by encoding directional information across three color channels, but it adds preprocessing complexity and only partially resolves the underlying issue.
The Analytical Approach
Slug takes the third path: evaluate glyph outlines directly in the fragment shader with no pre-baked approximation. For each fragment, the shader loads the Bezier curve data for the glyph being rendered, determines which curves could influence that fragment, and computes coverage analytically.
The inside/outside determination uses the nonzero winding rule. For a given sample point, you cast a ray (conventionally horizontal) and count signed crossings with the glyph outline. For quadratic Bezier curves, each crossing requires solving a quadratic equation:
// Quadratic Bezier: P(t) = (1-t)^2 * P0 + 2t(1-t) * P1 + t^2 * P2
// Find t where P_y(t) == sample_y, then check P_x(t) vs sample_x.
float a = P0.y - 2.0 * P1.y + P2.y;
float b = 2.0 * (P1.y - P0.y);
float c = P0.y - sample_y;
float disc = b * b - 4.0 * a * c;
// Real roots indicate intersections; sign of derivative gives winding direction.
This tells you whether the sample is inside or outside the glyph, but winding alone does not produce anti-aliasing. For that, Slug computes the fractional area of the glyph outline within the fragment’s area, a coverage value between 0.0 and 1.0. The alpha assigned to a fragment is the proportion of its area covered by ink. This is the exact answer, derived analytically, without approximation at any scale.
The precision that falls out of this is notable. Slug renders sharp corners sharp, fine strokes fine, and remains correct whether rendering a headline at 200pt or a footnote at 8pt. Lengyel published the core algorithm in a 2017 JCGT paper, “GPU-Centered Font Rendering Directly from Glyph Outlines,” but the library existed before the paper and continued evolving after it.
One performance concern is obvious: iterating over all Bezier curves in a glyph per fragment is expensive. Slug addresses this with a spatial acceleration structure that culls curves whose bounding regions do not overlap the current fragment, so the shader only evaluates the small subset of curves that could realistically contribute coverage. The result is that the per-fragment cost grows with local glyph complexity, not with total glyph outline length.
What a Decade of Maintenance Looks Like
The GPU landscape changed substantially over the decade Slug was under development. The library now supports Vulkan, Metal, Direct3D 12, and OpenGL 4 across Windows, macOS, Linux, iOS, and Android. Each API has its own memory model, synchronization primitives, and shader binding conventions. Maintaining correctness across all of them is a sustained engineering effort distinct from the rendering algorithm itself.
The OpenType specification is also a moving target. Variable fonts, added to the spec in 2016, allow a single font file to encode a continuous design space, with named axes for weight, width, slant, and arbitrary parameters defined by the type designer. Rendering a variable font correctly requires interpolating glyph outlines at a position in this space before handing the curves to the GPU. Color fonts add another layer, with glyphs composed from multiple colored layers or from embedded SVG data.
The decade Lengyel describes involved a specification that moved continuously while the correctness guarantee stayed fixed. That is a harder maintenance posture than it sounds. A library that approximates can absorb specification drift by staying within the margin of error. A library that promises exactness has to track every new glyph format, every new color model, every new variable font interpolation rule.
Where Slug Sits in 2026
The GPU text rendering space has grown more crowded since Slug launched. Mozilla’s Pathfinder (now archived) and Raph Levien’s Vello both take analytical or near-analytical approaches to GPU vector rendering, building on newer GPU compute capabilities. Vello uses a tiling architecture: the screen is divided into tiles, curves are assigned to tiles in a geometry stage, and a compute shader fills each tile using an exact area integral. This is architecturally different from Slug’s per-fragment evaluation, but it shares the commitment to correctness over approximation.
The difference is ecosystem and deployment target. Vello is open source and Rust-native, developed under the Linebender umbrella and aimed at desktop application development in Rust. Slug is a commercial SDK with C++ bindings, targeted at game engines and graphics pipelines that need reliable integration into existing codebases. Neither is displacing the other; they address different contexts and different engineering constraints.
SDF is not going away either. For mobile games with simple UI text at predictable sizes, the runtime cost savings of SDF over analytical rendering outweigh the quality trade-off. The situations where Slug’s correctness matters most are the situations where text appears at unpredictable scales: 3D billboards in a rendered scene, zoomable document viewers, high-DPI displays where sub-pixel accuracy is legible.
The Argument for Exactness
Libraries like this, narrow in scope, correct by construction, and maintained across a decade of platform changes, are useful precisely because the alternatives optimize for the common case. SDF is fast and sufficient for the majority of rendering scenarios. The cases where it falls short tend to be exactly the cases where text rendering quality matters most, where the text is prominent, where the user is looking closely, where rendering artifacts become part of the visual impression of the product.
Lengyel has written at length about mathematics for 3D graphics, and Slug reflects the same sensibility: do not approximate what you can compute. The rendering artifacts that SDF introduces are invisible most of the time; the situations where they are visible tend to be the situations where your text rendering is most prominent. Ten years of maintaining one library in service of that principle is the kind of long-term commitment that the tools you use without thinking about tend to be built on.