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