README.md 2.9 KB
Newer Older
N
nothings 已提交
1 2 3
# Font character oversampling for rendering from atlas textures

TL,DR: Run oversample.exe on a windows machine to see the
N
nothings 已提交
4 5 6
benefits of oversampling. It will try to use arial.ttf from the
Windows font directory unless you type the name of a .ttf file as
a command-line argument.
N
nothings 已提交
7

N
nothings 已提交
8 9
## Benefits of oversampling

N
nothings 已提交
10 11
Oversampling is a mechanism for improving subpixel rendering of characters.

N
nothings 已提交
12 13
Improving subpixel has a few benefits:

N
nothings 已提交
14
* With horizontal-oversampling, text can remain sharper while still being sub-pixel positioned for better kerning
N
nothings 已提交
15 16 17 18 19
* Horizontally-oversampled text significantly reduces aliasing when text animates horizontally
* Vertically-oversampled text significantly reduces aliasing when text animates vertically
* Text oversampled in both directions significantly reduces aliasing when text rotates

## What text oversampling is
N
nothings 已提交
20 21 22 23 24 25 26 27 28 29 30 31 32 33

A common strategy for rendering text is to cache character bitmaps
and reuse them. For hinted characters, every instance of a given
character is always identical, so this works fine. However, stb_truetype
doesn't do hinting.

For anti-aliased characters, you can actually position the characters
with subpixel precision, and get different bitmaps based on that positioning
if you re-render the vector data.

However, if you simply cache a single version of the bitmap and
draw it at different subpixel positions with a GPU, you will get
either the exact same result (if you use point-sampling on the
texture) or linear filtering. Linear filtering will cause a sub-pixel
N
nothings 已提交
34
positioned bitmap to blur further, causing a visible de-sharpening
N
nothings 已提交
35
of the character. (And, since the character wasn't hinted, it was
N
nothings 已提交
36
already blurrier than a hinted one would be, and now it gets even
N
nothings 已提交
37 38 39 40 41 42 43 44 45
more blurry.)

You can avoid this by caching multiple variants of a character which
were rendered independently from the vector data. For example, you
might cache 3 versions of a char, at 0, 1/3, and 2/3rds of a pixel
horizontal offset, and always require characters to fall on integer
positions vertically.

When creating a texture atlas for use on GPUs, which support bilinear
N
nothings 已提交
46
filtering, there is a better approach than caching several independent
N
nothings 已提交
47 48 49 50 51 52 53 54 55
positions, which is to allow lerping between the versions to allow
finer subpixel positioning. You can achieve these by interleaving
each of the cached bitmaps, but this turns out to be mathematically
equivalent to a simpler operation: oversampling and prefiltering the
characters.

So, setting oversampling of 2x2 in stb_truetype is equivalent to caching
each character in 4 different variations, 1 for each subpixel position
in a 2x2 set.
N
nothings 已提交
56

N
nothings 已提交
57
An advantage of this formulation is that no changes are required to
N
nothings 已提交
58 59 60 61 62
the rendering code; the exact same quad-rendering code works, it just
uses different texture coordinates. (Note this does potentially increase
texture bandwidth for text rendering since we end up minifying the texture
without using mipmapping, but you probably are not going to be fill-bound
by your text rendering.)
N
nothings 已提交
63