Unity Technologies

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'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.

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)

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?

Unity Technologies

I wonder if it would be possible that this technique would create a smoother gradual result when the bilinear filter is applied?

Click to expand...

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.

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.

Thank you for checking it out! 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.

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.

I did not mean to put you out. I have had the Cg tutorial on my desk for a while now I really need to start reading it. I keep getting distracted with other programming tasks. Eventually this is one of the areas I plan to work on and contribute back to the community I think you have already given me a great head start.

I am more interested in where or not you think my reasoning is right. That distance fields would be able to render floating text / textures over someone's head that does not become blurry as you zoom out, without having to scale the physical size of the text area.

Unity Technologies

I am more interested in where or not you think my reasoning is right. That distance fields would be able to render floating text / textures over someone's head that does not become blurry as you zoom out, without having to scale the physical size of the text area.

Click to expand...

That should be completely possible, and wouldn't actually require Cg unless you wanted antialiasing. For AA, you can either do a fixed radius blur (which is what KvanteTore's shader does) or make it adaptive, which would be more complicated.

I think the tricky part is getting it to work with Unity's font system and 3D text. So far I've had scaling and bias issues that I can't seem to figure out.

Are you sure you have unity's 3d text working correctly first? You need to use the GUI/ Text shader plus you need to have the font material that corresponds to your font.

If you have the wrong font material, your text will look all distorted. This sounds like what you are having. It may be easier to just extend unity editor which is really easy rather than using unity's 3d text.

Unity Technologies

Are you sure you have unity's 3d text working correctly first? You need to use the GUI/ Text shader plus you need to have the font material that corresponds to your font.

Click to expand...

Using the GUI/Text shader would defeat the purpose of this whole thing, because it doesn't render SDF textures properly.

In any case, it looks like I modified the font after generating the SDF, which was causing the UV coordinates not to match. I regenerated the SDF from the font, and now it works fine with text meshes and GUIText.

The main problem I've found with using Unity's font system is that there's no way to specify a padding between characters, and without padding it's hard to get enough space between characters to create a nice SDF without it bleeding between the characters. Also, our artist was complaining about the difficulties of fitting an outline around the font.

I really like the flexibility of the BMFont character packer, whether using SDF fonts or normal coverage fonts, so I think I'll make my own clones of TextMesh and GUIText based on the BMFont character packing.

Ideally, BMFont or a similar interface could be integrated into the unity editor, but that's quite a bit more work than I have time to right now, so I think I'll stick to importing .fnt files

I don't think you need to blit the font texture to a render texture though, mainTexture on the font material is a Texture2D and you can simply cast it.

I've incorporated a similar (although less comprehensive) script as well that uses the Unity Font texture as a basis for generating a SDF. The result is a font that can use the SDF shader and scale nicely and still use GUIText, but the characters bleed into each other a bit, so it's a bit rubbish. I guess that I could generate the SDFs for each character individually to avoid bleeding, but still the slim characters like the "l" have so little texture space that the resulting SDF isn't very nice (at least not with the SDF generation algorithm i'm using).

I've also done as Timmey suggested, and made a mesh font (that can be placed/rotated/scaled anywhere in the unity scene).

The changes have been pushed to the github repo and the unity package has been updated.

Unity Technologies

The font texture isn't readable, though. I blit it to the RenderTexture in order to be able to copy that and save a PNG. Unless I'm missing something, because it does seem convoluted. I need the PNG to run through an SDF generator, which is external.

Regarding the one about a mesh getting generated if you try to access it: wouldn't your suggestion leak a mesh into the scene every time the text changes? If so, I think it would be better to get one empty mesh and destroy it the first time.

yes this will happen and unity will give a message saying that it has cleaned up a leak. At least it was doing this when I added a text mesh to compare with the SDF. Note it does not give a warning or error.

Not sure, how you can fix this because I do not believe that Destroying the mesh will fix the leak. Because the act of setting the mesh also creates a new one that will then be leaked anyway. If the mesh is null.

Should probably just check if a font if selected and return true if so.

In the same subject, I don't exactly understand how converting unity fonts work. I thought I was suppose to run that script, get the texture+material and use the material in GUITexts instead of the font's default material. When doing this, I don't see any text. (I did make sure that the 'font' points to the same font). What am I doing wrong?

2) I'm trying to use this for a large font (large in terms of number of characters), but its important for me to keep the batch count low. So I want to use large bitmap textures. The problem is a combination of two things :
A - DistanceField heavily downsamples the input image
B - Unity has a texture import limit of 4096x4096.

This essentially means that we can't use textures of over 512x512 with this method. Does anyone have any workaround for this? (Perhaps a standalone tool that renders the distance field?). The other solution would be to create a texture atlas, but that might get messy with the BitmapFont object...

Norman:
Sorry I haven't responded before, but I've been out travelig and it seems like I missed the forum notification.

Cheers Timmey!

Norman:
1a) yes, you are absolutely correct. It was fixed in the version on github, but I'd forgot to update the unitypackage on our blog
1b) the problem was that the default colors for the shader were completely transparent . I'm sorry about that. Fixed now to be completely opaque instead
2) That's a brilliant idea, and it was in fact quite straight forward to implement

I've updated the importer to use Texture2D.PackTextures to pack all the distfield pages in to a single texture. This will fail if you have more than 16 pages, will that be a problem for you?

You can grab the latest package (v4) from our blog, but it would probably be best if you clone the github repo, as that's always going to be more up-to-date than the unitypackage.

Cool, thanks!
I'll have a look at the code and see how hard it will be to modify it to my needs. I will definitely need more than 16 pages (I need to support the chinese character set), but it probably won't be hard to modify the code to merge 16 pages each time, since your original code had support for more than one texture...

I got the code, and modified it a bit - it can now create multiple atlases if needed (if the input to PackTextures is too much, it scales the textures down, which is not what we want to happen).

I attached a unitypackage with the modified code. (I modified the version from the github repository of a few hours ago)

[Edit]
I also modified the code to save the intermediate (non-atlased) versions of the distance fields, because unity was crashing due to out of memory errors. In this version, you can right click on textures to only generate the distance fields from them, and then the "Import Font" function will just load the generated distance field, separating between the two memory-consuming tasks and allowing for it to finish.

Attached Files:

This is a modified text shader that creates an outline, instead of a shadow. It can be useful for glowing effects too. This version only works on desktop (non gles). Could someone suggest how this could be ported on Iphone ? Thanks.

Unfortunately I don't have access to Unity for mobiles yet, so I can't test for you, but I notice the

#pragma exclude_renderers gles

which excludes compilation of the shader on gles targets. Mabye you can try to remove this and see if the shader works (it doesn't do anything special, so hopefully it works.

On mobiles I reccomend you use the mesh-text replacement rather than the gui-text replacement, as the latter has not at all been optimized with respect to draw call count, and will probably hurt your performance significantly.

Thanks for the reply.
It would be sooo great if I could understand the logic behind shaders. Anyway, by applying million monkeys typing techniques (ie keep typing until you see what you wish) I made a shader that works on the Iphone. It is plain, no shadows or outlines yet. Hopefully they will follow later. Any hints on how to add break lines to the custom textMesh? Or how to put the letters along a curve ? I would appreciate any advice.
Here is the code:

"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.