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