I had previously posted about drawing outlines around fonts. The goal is to make labels easier to read in situations like these:
Especially where the text and background are the same lightness, an outline with the inverse lightness can make it more readable:
These outlines are called “halos” in the cartography world. There are many styles[1] one can use. A solid outline is the simplest thing to implement, so I started with that. Apple Maps and Google Maps use a solid outline too. However, a solid color outline can be distracting[2], and Cartographer Tom Patterson instead uses background blurring with feathering (variable strength) to produce nicer looking halos[3]. That article made me want to try other styles.
With signed distance fields, the shader can map signed distance to a color. I made a visualization of this mapping. For plain text, everything below 0 is filled and everything above 0 is transparent:
I implemented outlines by setting the color at distances between 0.0 and 0.1:
I also tried adding a separate soft outline (halo) that fades out over some distance:
Let’s look at little closer at the output:
We don’t need outlines in regular UIs because the text is readable by default. Outlines are distracting. But in maps the variety of backgrounds means the safest thing is to use an outline. Let’s look at different areas of the output:
In area A the dark lines for the mountaintops make the text harder to read, especially at the bottom of the T
and G
. In the original image at the top of the page, the beginning of the word PEAKS
is especially hard to read.
In area B the text is already readable without an outline. The same is true in area F. Area E is readable although it could be better.
In area C the black text is hard to read against a dark ocean background. Area D also has low contrast, especially the letter R
.
What can we do to improve these? Regular hard outlines are the obvious answer. But I think area B looks better without the outline. And area B may be a common case in some map styles. So I wanted to try some other options for outline styles. Tom Patterson suggests blurring the background. I tried implementing an “outline” that uses the blurred background color:
I think this helps with area A. We can think of the label as being printed on frosted glass. The downside is that the map detail is lost. And it doesn’t help in areas C, D, E. Let’s combine this with hard and soft outlines:
I still prefer area B without the outline. What would happen if I selectively applied the outlines? The shader can calculate the contrast at each pixel and suppress the halo over areas where contrast is good: B and F. Let’s see the halo only:
Suppressing the halo in some areas gives us this (and it could be tuned up or down):
Here’s the result:
However the downside of this style is that a label over different types of areas will look inconsistent.
Another thing I wanted to try is improving the outline in area C. It looks much stronger than the outline in area D. I tried tinting it the same color as the background:
My experimental code only worked for the light outlines and not for dark outlines. I think I’ll have to revisit if I want to use it in a real project.
In terms of implementation, selective outlining, outline tint, and background blur all require me to read the background pixels from the map image. I converted my code to use linear rgb to make these calculations correct. Of these three features, background blur is the trickiest, because I’m also writing the blurred value out near the labels. If there are overlapping labels, what happens is that I draw the blurred background, draw the first label, draw the blurred background again, and draw the second label. This looks bad. It would be even worse if I didn’t combine distance fields as I described in a previous blog post. I didn’t try to fix any of this for these experiments. My goal was to see whether selective outlining, outline tint, and background blur help, not to make a production-quality text renderer.
I don’t know which of these techniques will look best in a real project, but I now have some options:
- Hard outline
- Soft outline (halo)
- Blurred background
- Selective outline
- Tinted outline
Applying all of them to the example from the top of the page, I think it’s an improvement over the regular hard outlining:
In games like Magic The Gathering you spend some of your time collecting cards for your deck and some of your time playing those cards in a game. These font experiments for me are the “deck building”. I’m learning a lot, and I now have more options available. But at some point I want to use this in a real project.