Hacker News new | past | comments | ask | show | jobs | submit login
Text rendering using multi channel signed distance fields (github.com)
96 points by qqii on May 27, 2019 | hide | favorite | 17 comments

There is a concise description of how this works (written by the author) here:


There's also a fantastic talk on this paper at the SF PapersWeLove meetup going over it https://youtu.be/-O0-HEZAwg8?t=1025

Really enjoyed this paper, the talk, and this technique. Quite clever!

This is a great library, I used it last year for text rendering in WebGL [0]. The advantage over regular SDF is you can use lower-resolution glyph maps to achieve the same text sharpness. The disadvantage is that text effects like glow and stroke are tricker as you tend to get sharp edges and artefacts [1].

[0] https://github.com/VALIS-software/GPUText

[1] https://github.com/Chlumsky/msdfgen/issues/67

It's also trickier to support Unicode and arbitrary fonts.

I was building a 3D game for language learning on mobile, and the font rendering in Unity3D was awful (blurry and rasterized).

When I eventually ended up writing my own engine, I started with bitmap fonts and quickly switched to SDF shaders. I ended up having to regenerate the texture on-the-fly as new characters were needed, acting as a cache (one of the markets was China -- you're not going to just stash all of the characters into one texture).

Another wrinkle: There's also right-to-left writing systems like Hebrew and Arabic, but those weren't our markets.

So far, the best I've seen is Eric Lengyel's Slug library: [1] http://sluglibrary.com/

If you want languages with more interesting shaping, you have to start compositing glyphs; but good shapers are out there. HarfBuzz is amazing, I'm always amazed how well random bits of Farsi and Mongolian typeset on my systems.

Not sure about Unity, but it helps to be able to submit the geometry, the shader, and the uniforms, then asynchronously (or if you're lucky, in another thread) submit the SDF after you're done computing it.

With respect to slug, do you know if it would be usable with something like nerd fonts (custom glyphs)? My impression is yes, but I wasn't quite clear.

Their demo shows it rendering color glyphs. Try reaching out to Eric?

Unity purchased the company behind TextMeshPro and made it free.

It is vastly better than standard Unity text rendering in every way.

This is a note for future readers, and less of a reply.

> The disadvantage is that text effects like glow and stroke are tricker as you tend to get sharp edges and artefacts.

This is going to happen with every SDF format. The problem is that SDFs can fundamentally only encode the distance to a small fixed number of lines per texel. For regular SDF, that number is one; for mSDF, that number is two. If the complexity of the shape exceeds that (as can happen for complex fonts such as CJK fonts with small SDFs), then artefacts will occur.

In your demo [0], is there a reason for the artefact in the top left corner of the 'm' and the bottom left corner of the 'p'? Is that an artefact produced by the MSDF rendering or the msdfgen tool?

[0] https://valis-software.github.io/GPUText/example/

It’s a result of the MSDF technique working with small glyph textures. Bumping the glyph texture size up would remove the artefacts but I wanted to see how small I could set them and have good results at mid range font sizes

This is pretty neat work, I was considering using it to help work around the problems of anisotropically scaled SDF font rendering. (Trick: do the anisotropic scaling and add the Jacobian correction factor per color channel before combining with the median. This will avoid some subset of the artifacts you get when trying to anisotropically scale SDFs and subsequently use them for antialiasing and stroke rendering.)

If you're going to use this library, note that the maintenance situation is complicated. Some forks seem well ahead in terms of bug fixes, for example https://github.com/RCrockford/msdfgen

Are there any decent tools for generating these mSDF from arbitrary SVG? Last time I looked, the available tooling failed on most nontrivial SVGs so the whole concept was a bit of a non-starter.

Is this simply generating textures for 2D planes, that you can just strap to a cube, or does it go beyond that?

My novice take is that the author is using a low-res RGB texture and then cleverly combining it with some custom GPU code to generate an extremely high-res monochrome texture at the memory cost of the low-res texture.

Signed distance fields for vector rendering are based on the fact that you can perfectly† reconstruct the distance to any straight line via bilinear interpolation between samples of the Euclidean distance. On GPU, the texture sampling hardware provides that bilinear interpolation.

The trouble with using this property to encode and render polygons is that sometimes to render polygons properly you need to consider the distance to two or more edges simultaneously in the course of processing a pixel. A single-channel signed distance field just accepts the artefacts that result from this. A three-channel signed distance field, on the other hand, allows each texel to record the distance to two edges simultaneously. (The extra channel basically exists just to specify the Boolean operation to be performed on the two edge differences.) This enhances the quality, especially around sharp edges.

Note that rendering of general polygons with any sort of signed distance field remains an approximation, because of the limited number of edges per texel as explained above. SDFs are not general vector renderers and should not be treated as such.

† Modulo quantization error from the fact that you're encoding distance into an 8-bit channel.

It'll work on arbitrary geometry the same as any other texture.

The Valve technique starts with "distance to the edge" encoded in each pixel of the texture. Bilinear filtering turns that into a piecewise-linear approximation of the true value for each interpolated point. Thresholding that gives you a black or white depending on if a given point is inside or outside of the threshold distance from the edge. Thus, you get hard, straight edged results at pixel resolution regardless of resolution of the font texture.

This technique extends Valve's by combining multiple piecewise-linear approximations to work around the limitations of approximating corners that are not aligned with the texel grid.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact