MSDF font, CanvasFont, TextMesh: Issues supporting Japanese

Hi,

There are some great existing threads on this topic listed at the end.

My app requires access to approx 2000 Japanese characters both in the UI and in the 3D scene. The editor has an option to process a TTF font to produce a MSDF font that is usable in the app at runtime. This works great except the the VRAM usage is huge ~50MB. However I don’t need all 2000 characters in memory at the same time. Each level in the game needs around 100-150 characters. Playcanvas also has CanvasFont that can be created at runtime. However this is more memory inefficient compared to MSDF and still uses ~35MB VRAM just for 100 characters. Also the CanvasFont characters look pixelated in world space.
Here is my canvas font test https://playcanvas.com/project/1267450/overview/canvasfont-and-google-font-test.

So it seems CanvasFonts aren’t going to work for me at they consume too much memory and don’t look as good as MSDF fonts.

I could I suppose manually process many smaller MSDF fonts in the editor, one for each level. But that will be a real pain.

What I really want to do is create MSDF fonts at runtime just like I can create CanvasFonts at runtime. I note that there is a C++ tool in Playcanvas github ( linked below) related to MSDF. So presumably the algorithm details can be found there , or from reverse engineering the TextElement and MSDF shader chunks.

I also found TextMesh which parses a TTF font and creates a mesh. This would be probably suit my needs for the 3D environment https://playcanvas.com/project/1269660/overview/fork-textmesh . But as I need a font for the UI text elements I still the MSDF font.

Could the TextMesh code be modified to produce a MSDF font rather than a mesh? That would be cool.

The other option is I use TextMesh for the 3D environment and a HTML framework for the UI if that would help.

References:

Other option could be to generate MSDF textures for all characters. Then split them into a texture per character.
At load time, load characters you need and add them to an atlas. And use that for your level.
Or even preprocess those offline to generate per level atlas, and use those.
Quite a bit of work though. Probably easier to just have multiple entries of the font, and specify a list of characters per level in Editor.

Hi Martin

Thanks for the reply. The problem with this is that my game could eventually have 500+ levels needing 500 manually generated fonts in the editor. ( My game is a vocabulary game with 10 words per level * 500 = 5000 words ). Having a manual process isn’t scalable in this case.

If you had to choose a non manual way what would be your favourite?

I’d probably try to get the Canvas Font solution to work. The might not look as good when enlarged, but how large do they need to be?

I see that internally it uses RGBA8 texture. But in the engine 2 where we removed support for WebGL1, we have an option to use R8 format, which would make the VRAM use 4x smaller. (we’d need to make this change first, not done yet)

I created an issue here: Investigate using R8 format for CanvasFont instead of RGBA8 · Issue #7084 · playcanvas/engine · GitHub

1 Like

In the 2D UI the canvas font of size 64 would probably be OK. But in the 3D scene the textElement can fill the screen if the user moves close and then the canvas font looks pixelated. The MSDF looks much better in this case.

1 Like