Scaling Bitmap Fonts

Hi there!

I’ve made an implementation of the Improved Alpha-Tested Magnification for Vector Textures and Special Effects (recently mentioned on Joakim Hårsmans blog) for scaling bitmap fonts in Unity.

The implementation uses AngelCode’s BMFont bitmap textures which are converted into distance field textures by a unity importer.

Check it out on our blog.

The code is of course freely available, but it is a bit rough around the edges, and could do with a bit of tlc. If anyone finds it interesting I might try to make it a bit cleaner though. :slight_smile:

cheers,

1 Like

Bitmap Font Generator is a great tool

Very cool. I’m surprised that everyone hasn’t been using this method since Valve published that paper. I implemented an SDF generator for Unity earlier this year, but I didn’t bother optimizing it at all, and abandoned it because I couldn’t get it to play nice with Unity’s fonts.

I’ll check out your solution this weekend.

I’ve not tried to use the font system at all, and it’s all a bit messy. I haven’t been able to get very good results on small font sizes (which, i guess, is to be expected), so i guess it’s best suited for large fonts like HUD elements and vector graphics.

I’d love to hear what you think, though :slight_smile:

I just tried it out, and it looks very nice. There must be a better way of using it in GUI, though. You can’t change the material used for GUI/Layout, but you can for GUIText.

Very interesting stuff.

Are you sure? I haven’t tried it out, but it seems like you can set Font.material.

Yes, it would be great with a better integration with the GUI systems in unity.

Making a GUIText replacement should be really straight forward.

If we can replace the material on GUI.skin.font, I guess it would be possible to get Unity to rasterize a high res version of the font and then create a reduced scale SDF from that, although I’m not really impressed with the flexibility of the unity font rasterizer, so the optimal solution would be to replace their entire font thing with a BMFont based renderer (although I doubt that’s currently possible)

GUI/Layout ignores font materials and uses its own shader no matter what.

Ah, I see… :frowning:

I guess I’ll go for a GUIText kind of approach then.

How can I import font ? I chose Assets → BitmapFonts → Import font , and nothing happen.

EDIT :
Sorry it’s works just fine, my mistake in import .

PS.

Great work, thanks a lot

Yes, you need to right-click the .fnt file in the project view and select BitmapFonts → Import font from there (in case anyone else wonders) :slight_smile:

It’s a good idea to use the MenuItem(string, bool) version of the attribute to provide a function that enables the menu item only when an appropriate file type is selected.

I’m trying to rotate a previously rendered bitmap which contains lines and shapes at various angles. When this is rotated, even though it was rendered originally with great antialiasing, it creates a bitty look when normally diagonal lines are rendered near horizontal or vertical. I wonder if it would be possible that this technique would create a smoother gradual result when the bilinear filter is applied?

The actual rendering process doesn’t do anything special when it renders the signed distance field. The reconstruction operation is just alpha testing. If you want higher quality data, you need to increase the resolution of the source bitmap you are using, and possibly the resolution of the distance field bitmap. That is, increase the quality of the original data first, and if that doesn’t work then you need to increase the resolution of the extracted distance field so that it can better represent the original.

I should also mention that antialiasing in the original image doesn’t help, as the SDF generation method KvanteTore is using doesn’t take grayscale into account.

Have you looked at the RotSprite algorithm (http://en.wikipedia.org/wiki/2xSaI#RotSprite), I came over that wikipedia article when I was reading about font scaling, but I haven’t looked any more into those algorithms.

The distance field approach works best for round features and is not awesome for thin lines or sharp features, and as Daniel is saying, you need a really high resolution version of the original image for the current algorithm to create a good distance field. There are other algorithms for creating distance fields though (http://contourtextures.wikidot.com/) which supposedly works with antialiased original images as well.

Awesome! That’s a brilliantly hidden gem right there.

Thank you for pointing it out. I’ve updated the github repo and the uploaded unity package :slight_smile:

A version without a shadow in the unity demo package would be sweet.

Hi Timmey,

Thank you for checking it out! :slight_smile: You can easily remove the shadow by setting 100% transparency on the shadow colour, or by setting both the upper and lower shadow alpha thresholds to 1

When I have time I’ll make a GUIText clone, only using the BMFont renderer and this scaling technique. When that’s done, I’ll be sure to include examples without shadow as well. Mabye even implement a simpler shader for text without outline/shadow as well.

cheers,

Cool but wouldn’t it make more sense to use this for 3d text. Where you can scale the text based on distance from camera or something? Right now Unity’s 3d Text "Text Mesh become horribly blurry and unreadable.

Unity already has truetype font for 2d and GUIs

"