SDF vs. MSDF vs. Slug: GPU Text Rendering

(alphapixeldev.com)

71 points | by ibobev 3 hours ago

15 comments

  • GuB-42 2 hours ago
    I once implemented SDF text rendering. To me, the thing I liked the most about this technique it how easy it is to add effects on top. With a few lines of shader code, I had outlines and softening of the edges (antialiasing). I didn't try the MSDF variant, as I didn't mind corners not being sharp when scaled up, so I don't know if these effects break on MSDF.

    Slug doesn't seem to support any of these, it is just "for a given point, am I in or am I out?", but it doesn't tell you by how much, which is great on really high resolution displays and large sizes, but you would lose the ability to do the kind of effects you can do with SDFs, and have to deal with antialiasing separately.

    • JoshTriplett 1 hour ago
      Having a technique that optimizes solely for whole pixels seems relatively reasonable, given current hardware PPIs. Systems that want to handle grayscale could use a different technique for that.

      That said, there are interesting effects other than grayscale antialiasing, and I wonder how well slug could handle things like outlines (useful for subtitles over video, to make them readable on any background).

      • eviks 8 minutes ago
        I don't follow, current hardware PPIs are generally low, while whole pixels work for high?
        • JoshTriplett 5 minutes ago
          > current hardware PPIs are generally low

          Not especially, unless you're running something like a high-refresh-rate gaming monitor that's still 1080p or less.

          On most current phones, laptops, and monitors, I would expect the difference between grayscale antialiasing and monochrome rendering to be hard to notice.

  • jdanford 3 hours ago
    Man, I am getting incredibly tired of reading LLM-generated writing
    • 20k 2 hours ago
      What signals this as being LLM writing for you? I'm crap at noticing specifics here
      • nurumaik 1 hour ago
        For me it was "head to head" table. Typical complete nonsense llm-generated comparison table. Rest of the content is still quite good tbh, generated or not
        • JoshTriplett 1 hour ago
          Not arguing whether this article is or isn't LLM-generated, but I've seen skewed comparison tables like that in marketing since before LLMs. Pick a bunch of qualities skewed towards the new thing being proposed, highlight all the ways the new thing wins.
      • poly2it 1 hour ago
        > A note on fairness, because the technical reader will ask.

        I think it's a mix of human and LLM writing.

    • cute_boi 3 hours ago
      Author probably didn't even read...
    • stuaxo 1 hour ago
      [dead]
  • Const-me 1 hour ago
    “What makes glyphs hard” Another reason is hinting. Traditional text renderers like FreeType are aware of the pixel grid and they adjust the curves slightly, snapping them to that grid. For all methods in the article quite hard to do on GPUs.

    “Chinese, Japanese, and Korean have tens of thousands of glyphs, and baking all of them at several sizes is a memory disaster” One possible solution is dynamic atlas built on CPU for visible glyphs only.

    “The distance-field panels notch, where interpolating between stored samples no longer matches the true curve” Can’t it be fixed in the shader, using screen-space derivatives of the SDF? I think in theory, SDF value for pixel center combined with screen-space gradient vector of that number delivers enough data to compute partial coverage for the pixels on the edge.

  • mattdesl 2 hours ago
    I've also been working on a GPU curve renderer, Windfoil, based on a formulation that Fable 5 originally proposed to me during a directed search [1]. It is similar in some ways to Slug, not always as fast, but uses less shader storage (single band instead of two) and produces higher quality anti-aliasing i.e. closer to a box-filtered ground truth.

    It may be of interest to some game/graphics devs here...

    [1] https://github.com/texel-org/windfoil-algorithm

    • yeoyeo42 2 hours ago
      interesting. how does the AA work in your algorithm?

      the reason slug has two bands is precisely because of its anti-aliasing. you having only one implies you do the AA differently, or are less efficient with searches off the main direction.

      for readers: the slug shader traces two rays, one horizontally, and one vertically, to find out if a pixel is inside a glyph or outside. one would be enough for pure inside outside, but for anti-aliasing purposes it's also helpful to know how far away you are from the closest edge. but if you have a horizontal ray running parallel to a horizontal glyph edge (not uncommon), the ray glyph intersection will return no value at all. so slug traces two rays and blends between them for anti-aliasing that always works in both cases. the bands mentioned here are just acceleration structures, basically a list of cells where each tells you which parts of a glyph are contained within it.

      it's still approximate. a true ground truth would just supersample and do many point-in-glyph tests within one real pixel - at edges some of them would be inside, and some of them would be outside, giving you a smooth value to display depending on the shape of the glyph within the edge pixel.

      • mattdesl 2 hours ago
        Windfoil uses boundary integrals to average winding over a given rectangular footprint (normally one pixel, independently in a fragment shader). For many cases, like typical text glyphs, this will reproduce a box-filtered ground truth exactly, i.e. for those shapes it is not approximating AA like Slug or MSDF. But because it takes the average and then applies a fill rule after, it's not an exact in all cases (fwiw, Slug can produces similar errors with tricky self-crossing curves and such).
  • flohofwoe 2 hours ago
    Here's a simple Slug rendering example on top of sokol_gfx.h:

    via WebGPU backend: https://floooh.github.io/sokol-webgpu/slug-sapp.html

    via WebGL2 backend: https://floooh.github.io/sokol-html5/slug-sapp.html

    There's quite a bit of helper code plus stb_truetype.h and stb_ds.h under the hood to parse TTF files and crunch the TTF curve data into the runtime format expected by the Slug shader (this stuff should better go into an offline asset pipeline tool):

    https://github.com/floooh/sokol-samples/blob/master/libs/slu...

    ...the actual text rendering code is also taking a couple of shortcuts, e.g. no kerning, no right-to-left, and also no text shaping.

    There's also a new and complete text rendering stack by Mikko Mononen called Skribidi (AFAIK not based on Slug though):

    https://github.com/memononen/Skribidi

    ...the list of external dependencies is a bit scary for a small self-contained sample though (Harfbuzz, SheenBidi, libunibreak, etc...), but that basically shows that proper international text rendering is really damn hard, even when trying to simplify the code as much as possible.

    • whizzter 1 hour ago
      ... or why it's best to just use the OS libraries to render to textures if you only need an OSD :P

      Question though, you implemented the slug system? The article mentions root eligibility but doesn't expand on it, what's the point of it because slug doesn't seem too "magical" for only doing winding counts?

  • seanw265 2 hours ago
    Interesting read. Text rendering techniques have always fascinated me.

    I'm a bit confused because at some points it seems like the author is conflating "tessellation" and "Rive". Are they the same thing? As an uneducated reader, my understanding would be that Rive is an implementation of a renderer using the tessellation approach. But surely a generic tessellation approach could support perfect arbitrary transformations even if Rive doesn't?

    Maybe there's something I'm missing.

    Also, a nitpick: in the "head to head" section, the author highlights Slug's better performance in green for the entries that it wins (or ties). For the sake of fairness, shouldn't we highlight the winners in every category? Surely Rive's "low" memory usage beats Slug's "moderate"?

  • jayd16 1 hour ago
    Is there a runtime comparison of the shaders needed? Seems like you might have to do a lot of texture sampling if you have to walk the ray through the data but maybe there's a trick?

    MSDF is pretty much just the target texel in question plus the surrounding samples in a way the GPU can do entirely upfront before the math starts. (M)SDF glyphs also play nicely with mip mapping and I would think this Slug algorithm needs uncompressed data. Maybe that doesn't matter because you just don't scale the data ever?

    • flohofwoe 1 hour ago
      Slug doesn't use "bitmap" font data but more like parameter lookup tables in storage buffers, pre-processed from TTF files. The lookup data can of course also live in textures (so that it works in WebGL), but using those textures as "poor-man's storage buffers", e.g. fetching the data directly without filtering.

      The pixel shader is indeed quite complex compared to SDF:

      https://github.com/floooh/sokol-samples/blob/8afa83928ce1870...

  • pavlov 2 hours ago
    > "In 2017 Eric Lengyel published an algorithm, called Slug, that stopped dodging. It renders glyphs directly from their outlines in the fragment shader, with no texture atlas and no per-frame tessellation. Lengyel patented it in 2019, and on March 17, 2026 he dedicated that patent to the public domain."

    It's nice that he gave the patent to public domain, but this is not how patents are supposed to work. You can't patent something two years after it was already published.

    I'm guessing he actually filed for a patent before publishing, and the article should read: "Lengyel was granted a patent for it in 2019"

    It's an AI-written article, so maybe it's not reasonable to expect it to be consistent on this level...

  • rezmason 3 hours ago
    Slug looks impressive!

    The project I'm most known for is basically an MSDF shader with a bloom pass. It serves my needs 100%, though if I expand to support arbitrary text, I may reach for Slug.

    The one issue with MSDF I want to raise is, it seems everybody uses the same msdfgen texture creation program from Viktor Chlumský's master's thesis 11 years ago. I wish there were other implementations. Who ever heard of a graphics technique that was only ever programmed once, and then used everywhere without substantial iteration? We need to de-XKCD-2347 MSDFs for everyone's sake, including and especially Chlumský.

    • torginus 2 hours ago
      I haven't heard of Chlumský or MSDF before, but I think a lot of people have been aware of the technique before he published his paper, thanks to Valve's TF2 text rendering paper:

      https://web.archive.org/web/20120505013814/https://www.valve...

      The pdf details only simple SDF, but in the closing paragraphs, it mentions the weakness of the technique and mentions how it can be solved with multiple SDFs, but the exact technique wasn't showcased.

      Which led to people trying to reverse engineering it, and making their implementation, for years (it's Valve after all). Including me. Not sure if what I came up with was exactly MSDF, but certainly there are a lot of implementations out there.

      • rezmason 1 hour ago
        We mostly agree! I should elaborate.

        I'd say what you and the others did was research, not implementation. Your results were solutions to the same problem, not variations of the same recipe. What you did is important but separate from what's concerned me.

        A recipe of Chlumský's— the msdfgen utility— is widely used, but only has one producer. I'm just saying that that's a liability. Like, imagine if HarfBuzz was the only text shaper, and was maintained by one person.

  • sirwhinesalot 2 hours ago
    There's another GPU text rendering algorithm missing from the comparison: Rook & Possum's Scanline Sweeper:

    https://rookandpossum.com/posts/scanline-sweeper/

    Sean Barret (creator of the stb public domain libraries) independently invented a CPU-based implementation of the same idea, used in stb_truetype.

  • hncbw02z5a 2 hours ago
    MSDF corners gave me trouble til I bumped the distance range at small sizes.
  • bel8 3 hours ago
    MSDF looks better than Slug for me in the first example.

    But slug wins in perspective in my eyes.

    I use MSDF to render crisp text in my webgl hobby game. Hope to publish it with source code when I get the time.

    thanks for sharing the article. I'll take a deeper look at it later.

    • Keyframe 3 hours ago
      I do MSDF as well and since I'm not doing a huge-ass text editor (and even then) it works and it's great. One thing to consider is that with any solution that does things directly from vector outlines means you also then have to distribute proper font outlines and you might not have a license to do that. With MSDF and similar atlas-like solutions, you pre-render a font and distribute that rendered image instead of an actual font.
      • dcrazy 1 hour ago
        Which you also might not have the license to do. I once licensed a Monotype typeface that prohibited its use in anything editable, including fillable PDF forms.
    • __m 3 hours ago
      [dead]
  • logdahl 2 hours ago
    I knew the second Eric posted about releasing Slug to the public domain we'd get 100s of "OpenSlug" slopped-up. Will be interesting to see which implementation will win or if Slug will keep being a thing.
    • flohofwoe 1 hour ago
      Tbf, the Github repo doesn't look particularly 'sloppy' to me, more like some mild AI assistance. There's several months of fairly regular looking git history, a couple of commits with an LLM disclaimer for python bindings, and two llm-context files.

      https://github.com/AlphaPixel/slughorn

  • sophietaylor 1 hour ago
    [dead]
  • reactordev 3 hours ago
    Excellent write up. The cited references are on point too. Eric Lengyel is a legend.