Signed Distance Field Fonts
Blog post: 23 Mar 2024 Each week I pick one or two things to work on. In week 2 of this year, I decided I should update my “hello world” OpenGL+Emscripten code[1] from 2015. It’s boilerplate I use occasionally in other…

Each week I pick one or two things to work on. In week 2 of this year, I decided I should update my “hello world” OpenGL+Emscripten code[1] from 2015. It’s boilerplate I use occasionally in other projects. It wasn’t compiling anymore, and I wanted to fix that as well as several other things.
One of the unsolved issues in that starter code was that the fonts never looked good. I was using the stb_truetype[2] library, and got this output:
Look at how H and e are too far apart, and S and D are too close together. I tried various things but couldn’t figure it out, so I had two workarounds at the time:
- Use Omar Cornut’s Dear ImGui[3], which has nice looking font rendering.
- Use a monospace font to hide the spacing problems.
I decided to look into it again. After all, Dear ImGui uses stb_truetype, so why would my output be so different? After looking through the docs and also several examples, I concluded that my code was all wrong. I tried kerning but that wasn’t the issue. I tried a few different fonts but that wasn’t the issue. One issue on stb_truetype[4] suggests “left side bearing”. I found example code from Justin Meiners[5] that rendered nicely, and it was using left side bearing. But Dear ImGui doesn’t use it. And example code from Benjamin Attal[6] didn’t use it either. I spent many hours studying the docs and examples before I figured out how to rewrite my code[7]. It looks better now (although still not great — look at the gap between m and o):
This awakened my desire to play with font rendering. In particular, back in 2016 I bookmarked https://github.com/Chlumsky/msdfgen[8] with the note:
Multi-channel distance fields can represent sharp corners, unlike Valve’s original paper, which had rounded corners. This is C++ code to implement the algorithm described here: https://computergraphics.stackexchange.com/questions/306/sharp-corners-with-signed-distance-fields-fonts/2151#2151[9] (there’s also a thesis paper)
So I decided week 3’s project would be to try that out! It was a great week. I learned a lot.
Along the way I kept some notes about what commands I ran and what I learned. These notes were originally meant for myself only but I’m making them available because I think sometimes people don’t realize what my learning process is like. My articles especially present everything in the “final form” and readers might think I just write code like that from the start. I don’t! I have lots of bugs and dead ends and misconceptions along the way. I find that keeping a journal (for myself) helps me work through them.
Some high level notes:
- Signed Distance Fields are cool.
- There are some things I don’t understand about gamma correction, supersampling, outlines, antialiasing, etc. I experimented some but I feel like I still don’t understand these topics well.
- Towards the end of the week there were several things I felt like I should have understood much earlier, but didn’t.
- The code to generate the MSDF files may be complex, but the code to render is incredibly simple, probably under 50 lines.
- I should take lots of screenshots and make lots of notes when I’m learning something.
Take a look my notes, as well as an interactive demo I used for testing my knowledge. Random tidbit: the 2403 in the url means year=2024 week=03. I’ve been using this naming scheme since 2015 for my weekly projects.
After playing with fonts week 2 and week 3, I still had more I wanted to do. But I am trying to keep to a project-per-week rhythm, so I decided to wrap up the basic font rendering and move on. In week 4 I’ll explore outlines and other effects. That’s the next blog post.
The new No Man's Sky Forsaken update delves into "the darker side
SEGA's Glitzy Virtua Fighter PS5 Revival Teases New Info for This Week
Cyberpunk 2077: Edgerunners 2 Free Update (2.5) Arrives This Week
Nintendo Download: 22 October 2026 (North America)