• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..26-Jan-2020-

README.mdH A D26-Jan-20204.5 KiB9575

main.cH A D26-Jan-20208.4 KiB333276

oversample.dspH A D26-Jan-20203.6 KiB9886

oversample.dswH A D26-Jan-2020514 3019

stb_wingraph.hH A D26-Jan-202024.3 KiB830690

README.md

1# Font character oversampling for rendering from atlas textures
2
3TL,DR: Run oversample.exe on a windows machine to see the
4benefits of oversampling. It will try to use arial.ttf from the
5Windows font directory unless you type the name of a .ttf file as
6a command-line argument.
7
8## Benefits of oversampling
9
10Oversampling is a mechanism for improving subpixel rendering of characters.
11
12Improving subpixel has a few benefits:
13
14* With horizontal-oversampling, text can remain sharper while still being sub-pixel positioned for better kerning
15* Horizontally-oversampled text significantly reduces aliasing when text animates horizontally
16* Vertically-oversampled text significantly reduces aliasing when text animates vertically
17* Text oversampled in both directions significantly reduces aliasing when text rotates
18
19## What text oversampling is
20
21A common strategy for rendering text is to cache character bitmaps
22and reuse them. For hinted characters, every instance of a given
23character is always identical, so this works fine. However, stb_truetype
24doesn't do hinting.
25
26For anti-aliased characters, you can actually position the characters
27with subpixel precision, and get different bitmaps based on that positioning
28if you re-render the vector data.
29
30However, if you simply cache a single version of the bitmap and
31draw it at different subpixel positions with a GPU, you will get
32either the exact same result (if you use point-sampling on the
33texture) or linear filtering. Linear filtering will cause a sub-pixel
34positioned bitmap to blur further, causing a visible de-sharpening
35of the character. (And, since the character wasn't hinted, it was
36already blurrier than a hinted one would be, and now it gets even
37more blurry.)
38
39You can avoid this by caching multiple variants of a character which
40were rendered independently from the vector data. For example, you
41might cache 3 versions of a char, at 0, 1/3, and 2/3rds of a pixel
42horizontal offset, and always require characters to fall on integer
43positions vertically.
44
45When creating a texture atlas for use on GPUs, which support bilinear
46filtering, there is a better approach than caching several independent
47positions, which is to allow lerping between the versions to allow
48finer subpixel positioning. You can achieve these by interleaving
49each of the cached bitmaps, but this turns out to be mathematically
50equivalent to a simpler operation: oversampling and prefiltering the
51characters.
52
53So, setting oversampling of 2x2 in stb_truetype is equivalent to caching
54each character in 4 different variations, 1 for each subpixel position
55in a 2x2 set.
56
57An advantage of this formulation is that no changes are required to
58the rendering code; the exact same quad-rendering code works, it just
59uses different texture coordinates. (Note this does potentially increase
60texture bandwidth for text rendering since we end up minifying the texture
61without using mipmapping, but you probably are not going to be fill-bound
62by your text rendering.)
63
64## What about gamma?
65
66Gamma-correction for fonts just doesn't work. This doesn't seem to make
67much sense -- it's physically correct, it simulates what we'd see if you
68shrunk a font down really far, right?
69
70But you can play with it in the oversample.exe app. If you turn it on,
71white-on-black fonts become too thick (i.e. they become too bright), and
72black-on-white fonts become too thin (i.e. they are insufficiently dark). There is
73no way to adjust the font's inherent thickness (i.e. by switching to
74bold) to fix this for both; making the font thicker will make white
75text worse, and making the font thinner will make black text worse.
76Obviously you could use different fonts for light and dark cases, but
77this doesn't seem like a very good way for fonts to work.
78
79Multiple people who have experimented with this independently (me,
80Fabian Giesen,and Maxim Shemanarev of Anti-Grain Geometry) have all
81concluded that correct gamma-correction does not produce the best
82results for fonts. Font rendering just generally looks better without
83gamma correction (or possibly with some arbitrary power stuck in
84there, but it's not really correcting for gamma at that point). Maybe
85this is in part a product of how we're used to fonts being on screens
86which has changed how we expect them to look (e.g. perhaps hinting
87oversharpens them and prevents the real-world thinning you'd see in
88a black-on-white text).
89
90(AGG link on text rendering, including mention of gamma:
91  http://www.antigrain.com/research/font_rasterization/ )
92
93Nevertheless, even if you turn on gamma-correction, you will find that
94oversampling still helps in many cases for small fonts.
95