GPU font rendering has a dominant solution and it is approximately correct. Signed distance fields, popularized by Chris Green’s 2007 SIGGRAPH paper at Valve on improved alpha-tested magnification, store the distance from each texel to the nearest glyph edge in a texture. A fragment shader thresholds that value to reconstruct the outline. The technique scales better than plain texture atlases and runs fast at runtime. It also has persistent problems at corners, with thin strokes, and at extreme zoom levels, because it encodes an approximation of the signed distance function at finite texture resolution rather than the actual glyph geometry.
Eric Lengyel’s Slug library takes a different position: compute the exact coverage of each pixel from the raw Bézier curves of the glyph outline, analytically, in the fragment shader. No approximation, no pre-baked distance fields, no texture atlas. The decade anniversary post at Terathon is a useful prompt to examine what that commitment to exactness actually requires, how the algorithm works, and what a specialized library looks like after ten years of maintenance.
What exact coverage means
When a rasterizer renders a glyph, the theoretically correct answer for each pixel is the fraction of the pixel area that falls inside the glyph outline. A pixel that is 60% covered should have 60% opacity. This is the geometric definition of anti-aliased rendering.
Texture atlases achieve this at native resolution by rasterizing on the CPU using libraries like FreeType and caching the result. The computation is exact, but the cached texture is locked to a specific size. Scale it up and the result blurs; scale it down and it aliases. Single-channel signed distance fields avoid some of this but lose the curvature information that determines actual coverage at fine scales. Multi-channel signed distance fields (MSDF), developed by Viktor Chlumský, improve corner handling by storing three independent distance values per texel, allowing sharper corners to survive the threshold. MSDF is a significant improvement over single-channel SDF for most use cases; it still shows artifacts at extreme magnification and on glyphs with features finer than the texel grid, because it remains an approximation computed at finite resolution.
Slug computes the coverage fraction directly. Given the Bézier curves that define a glyph outline, the fragment shader calculates the exact signed area contribution of each curve segment to the current pixel. Sum the contributions with winding-number semantics, and you have a geometrically correct coverage value, a number between 0 and 1 that is accurate regardless of scale, rotation, or sub-pixel position.
The algorithm
The formal description of Slug’s method appears in Lengyel’s open-access paper “GPU-Centered Font Rendering Directly from Glyph Outlines,” published in the Journal of Computer Graphics Techniques in 2020. The central observation is that the coverage of a pixel by a closed curve can be expressed as a sum of signed contributions from each curve segment, using the same winding-number logic that CPU vector rasterizers apply.
For each glyph, Slug preprocesses the outline on the CPU and builds a band structure: the glyph’s vertical extent is divided into horizontal strips, and each strip stores references only to the curve segments that pass through it. This reduces per-pixel work from O(n) in the total number of curves to O(k) where k is the number of curves in the local band, typically between 4 and 12 for most glyphs.
At render time, each glyph is drawn as a textured quad. The fragment shader for each pixel:
- Looks up the band containing the pixel’s Y coordinate.
- Iterates over the curve segments in that band.
- For each segment, computes the signed x-extent of the intersection between the segment and the horizontal strip spanning the pixel, using the analytical form of the Bézier coverage integral.
- Sums contributions to produce a coverage value in [0, 1].
- Uses that value as alpha.
The logic for a quadratic Bézier coverage contribution follows this general structure:
float coverage_quadratic(vec2 p0, vec2 p1, vec2 p2, float y_min, float y_max) {
// Reparameterize: find t where curve Y(t) crosses y_min and y_max
float a = p0.y - 2.0 * p1.y + p2.y;
float b = p0.y - p1.y;
// Solve for t at y_min and y_max, clamp to [0,1]
// Evaluate x at each t, sum signed trapezoidal area contribution
return signed_coverage;
}
For quadratic Béziers used in TrueType fonts, the coverage integral has a closed form involving square roots. Cubic Béziers used in OpenType/CFF fonts require solving a cubic equation to find scanline crossings, which is more expensive but runs entirely in the fragment shader without round-tripping to the CPU. Band data and curve control points live in GPU buffers: SSBOs in Vulkan and OpenGL, structured buffers in HLSL, and texture buffers on older hardware. The CPU-side preprocessing can be serialized, so the GPU sees a compact binary representation of each glyph at runtime.
Comparison with the alternatives
Texture atlases are fast and exact at native size. They degrade when the application renders text at continuously varying sizes, because the cache must be rebuilt or the result degrades. For a game with fixed UI font sizes, this is usually acceptable.
SDF and MSDF are scale-independent within a range and GPU-friendly at runtime. MSDF is the most widely deployed approach for games and real-time applications that need variable font sizes. Its artifacts are subtle at normal scales and appear mainly at extreme zoom or with certain glyph features. For the majority of shipped titles, that trade-off is workable.
Charles Loop and Jim Blinn’s 2005 paper “Resolution Independent Curve Rendering using Programmable Graphics Hardware” introduced exact cubic Bézier rendering on the GPU by mapping each curve to a canonical coordinate space where inside/outside can be evaluated in a fragment shader. It is the closest precursor to Slug’s approach. The key differences are that Loop-Blinn determines inside/outside rather than computing coverage area, which requires MSAA for anti-aliasing rather than analytical coverage; it requires tessellating the glyph into triangles, classifying each cubic into one of several canonical types, and handling concave regions with stencil operations. Slug produces exact coverage without any stencil, with a single quad per glyph and a self-contained fragment shader.
Mozilla’s Pathfinder project takes a tile-based approach using compute shaders to rasterize paths into small tiles and composite them. It handles arbitrary vector graphics beyond text and is open source under the MIT license. The pipeline is more complex; for text-only rendering, Slug’s quad-based approach integrates more simply into an existing rendering pass.
| Approach | Correctness | Scale-independent | Render cost | Artifacts |
|---|---|---|---|---|
| Texture atlas | Exact at native size | No | Very low | Blurry at off-native sizes |
| SDF | Approximate | Moderate | Very low | Blurry corners, thin strokes |
| MSDF | Approximate | Good | Low | Corner artifacts at extremes |
| Loop-Blinn | Exact (inside/outside only) | Yes | Medium | Requires stencil, MSAA |
| Slug | Exact | Yes | Medium | None |
Sub-pixel rendering
Slug supports LCD sub-pixel anti-aliasing, which exploits the R, G, B sub-pixel layout of LCD panels to triple effective horizontal resolution. The coverage computation runs three times per pixel, with the horizontal pixel bounds shifted by one-third of a pixel for each channel. The result is a three-channel alpha mask that drives separate R, G, B opacity during compositing.
This extends cleanly from the analytical framework. The coverage integral is parameterized by pixel bounds, and shifting those bounds by a fractional pixel amount is a direct numeric change to the same computation. Implementing correct sub-pixel rendering with MSDF requires a separate multi-channel texture designed for the purpose; with a texture atlas it requires separate CPU rasterization passes per channel. The analytical approach makes sub-pixel a parameter, not a separate code path.
Ten years in a niche
Slug started around 2014 and was released commercially around 2016, initially supporting OpenGL and Direct3D 11. Vulkan, Metal, and Direct3D 12 support followed over subsequent years. The JCGT paper in 2020 provided the formal academic description of the algorithm. The library is used in Lengyel’s own Tombstone game engine, which gives the algorithm a continuous production test alongside his other work on the engine, documented in his Foundations of Game Engine Development book series.
The licensing is commercial and proprietary. The algorithm is published, so a developer can implement the approach from the JCGT paper. The implementation is non-trivial, particularly for the cubic Bézier case, but the paper provides enough detail to build a working system. Studios that need exact coverage without a commercial license have that path available at the cost of writing and maintaining the shader and preprocessing code themselves.
MSDF won on ecosystem: Unity, Unreal, and most game engines ship SDF-based text rendering because it is fast, easy to integrate, and correct enough for the majority of shipping titles. Slug is relevant for applications that render text at continuously varying scales, at large sizes where atlas approaches degrade, or in contexts where typographic correctness is a hard requirement rather than a preference. Technical visualization, editors, and design tools fall into this category more often than games do.
That a single-developer operation has maintained a specialized GPU library with broad platform coverage for a decade reflects a sustained demand: applications where the standard solutions leave visible artifacts that the end user will notice. The anniversary post at Terathon marks how long it takes for a geometrically correct approach to accumulate platform support and production validation. The algorithm was right from the beginning; the decade is the story of everything else catching up around it.