parent
0a1d82f9e3
commit
c6e1ec0cec
1 changed files with 44 additions and 0 deletions
@ -0,0 +1,44 @@ |
|||||||
|
# Font character oversampling for rendering from atlas textures |
||||||
|
|
||||||
|
TL,DR: Run oversample.exe on a windows machine to see the |
||||||
|
benefits of oversampling. Type the name of a .ttf file on |
||||||
|
the command-line, or it will look for Arial in the Windows |
||||||
|
font directory. |
||||||
|
|
||||||
|
## About oversampling |
||||||
|
|
||||||
|
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 |
||||||
|
positioned bitmap to blur further, causing a visible desharpening |
||||||
|
of the character. (And, since the character wasn't hinted, it was |
||||||
|
already blurrier than a hinted one would be, and not it gets even |
||||||
|
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 |
||||||
|
filtering, there is a better approach than caching several indepdent |
||||||
|
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. |
Loading…
Reference in New Issue