Hacker News 中文摘要

RSS订阅

GPU 文本渲染技术对比:SDF、MSDF 与 Slug -- SDF vs. MSDF vs. Slug: GPU Text Rendering

文字看起来简单,直到你得亲手把它画出来。一个字母不是图片,而是一组轮廓:由直线和贝塞尔曲线构成的闭环,按填充规则填充。CPU 上渲染成位图早已解决,GPU 上要任意大小都清晰、承受 3D 变换、每帧文字都在变,则不然。多数引擎提前把字形烘焙进纹理。2017 年,埃里克·伦吉尔(Eric Lengyel)发布 Slug,直接在片元着色器中从轮廓渲染字形,不用图集,也不逐帧细分。

正文

如何在 SDF、MSDF、Slug、纹理图集或 Rive 之间选择文本渲染算法

文字看似简单,自己绘制却难。字母不是图片,而是一组轮廓:直线和贝塞尔曲线围成的闭合环,按绕数规则填充。CPU 光栅化位图已解决;GPU 上要任意尺寸、3D 变换、逐帧变化还清晰,则未解决。多数引擎预烘焙字形入纹理图集,妥协了事。

2017 年 Eric Lengyel 发表 Slug 算法,直接在片元着色器从轮廓渲染,无图集无逐帧细分。2019 年专利,2026 年 3 月 17 日投入公有领域。因此我们构建了 Slughorn(C++20 实现),借此讲解原理与优势。

下面从位图图集到 Slug 遍历 GPU 文字渲染。

字形的难点

可缩放字体用矢量轮廓存字形:TrueType 二次曲线,OpenType CFF 三次曲线。内部由填充规则(通常非零绕数)定:从像素射線数轮廓交叉,绕数非零则在形内。

渲染器要快做三事:正确填充、干净抗锯齿边、8 像素菜单或透视广告牌都锐利。CPU 一次光栅化目标尺寸即可;GPU 想逐帧数千字形任意缩放不重光栅,此约束令各技术权衡。

方法一:纹理图集(位图字形)

最老最常见。一次光栅化各字形入共享纹理(图集),屏幕字符用纹理四边形采样槽位。

快、可移植、任何设备跑,故无处不在。

缩放出问题:放大超烘焙尺寸模糊块化;缩小需烘焙 mip 否则闪烁缺笔。每种清晰尺寸需新图集。拉丁图集小,中日韩数万字形多尺寸烘焙是内存灾难。位图不知透视,贴 3D 表面软。

方法二:符号距离场(SDF)

Valve 的 Chris Green 2007 SIGGRAPH 论文提出存符号距离场:每纹素存到最近边距离,内正外负。着色器采样阈值零。距离平滑插值,小 SDF 纹理可大幅放大得净边,软阈值廉抗锯齿。

一小张纹理、合理分辨率无关、廉着色器。长期清晰 UI 和游戏 HUD 默认,受限硬件仍用。

但 SDF 仍固定分辨率烘焙纹理,且尖角说谎:尖角距离场不连续,双线性插值削圆。A 尖 K 凹变软。放大过多或字形太小场仅几纹素宽时细茎断细节糊。

方法三:多通道符号距离场(MSDF)

Viktor Chlumsky 2015 论文及 2018 论文修正角。MSDF 存三通道(RGB)各编码到不同边子集距离使锐角存活。着色器中值重建角几乎完美,放大不圆。

MSDF 是当前许多团队甜点,msdfgen MIT 广用。需清晰可缩放且愿烘焙图集时极佳。

但仍图集,有对应成本:预烘焙各字形,动态/用户文字、CJK 巨集仍管线内存;生成贵于 SDF;极小尺寸纹素少细节丢;极缩仍走样;三通道带宽高。MSDF 提质仍用图集。

方法四:细分与覆盖(Loop-Blinn、NVpathrendering、Pathfinder、Rive)

此类跳纹理,轮廓转 GPU 几何:

  • Loop-Blinn 喂曲线三角形,逐像素丢弃着色器留二次贝塞尔内部,模板缓冲解绕数。优雅但干净抗锯齿难。
  • 模板后覆盖(NVIDIA NVpathrendering 扩展)先画路径入模板再覆盖。质量高但赖厂商扩展硬件。
  • Pathfinder 细分边为微三角,算每像素有符号梯形面积,计算通道累覆盖。瓦片式现代 GPU 快。
  • Rive 渲染器 2024 开源,抗锯齿矢量路径化独特三角片,像素本地存储大规模并行光栅,动画矢量艺术 120fps。

此类真分辨率无关,动画设计矢量图常正确,Rive 专为动图。代价是细分本身(几何变需重做)、复杂字形几何膨胀、解析抗锯齿难、某些赖特定硬件。

方法五:Slug,直接从轮廓渲染

Slug 跳图集和逐帧细分,字形存少量二次贝塞尔和线段的小 GPU 缓冲,并建轻量每字形加速结构分水平带,像素只考虑近处少数曲线。

片元着色器直接解覆盖:每像素射線找附近贝塞尔交叉,数交叉得绕数即覆盖。难点 Lengyel 秘方“根资格”测试:精确规则判哪些曲线-射线交应计数,使共享端点绕数精确免裂缝重计。解析解曲线非采样烘焙场,故任意尺度精确覆盖净抗锯齿。

无烘焙分辨率,同字形 6 或 6000 像素锐利,任意 2D/3D 含透视锐利,因覆盖变换后逐像素算。无图集,十万 CJK 只花字体轮廓数据非大模型集。文字逐帧变零烘焙成本,适实时数据用户输入本地化。单普通片元着色器绘制无厂商扩展。

无法预判观看方式时关键:图集/SDF/MSDF 预烘焙固定分辨率暗设尺寸视角有界;自由 3D 相机、任意缩放、近距陡斜角时烘焙近似崩,超分辨率放大图集糊 SDF/MSDF 圆糊斜角走样,不能预存够分辨率否则存储爆。Slug 解析算覆盖变换后逐像素,无烘焙无上限。细分家族唯一共享此但付细分和抗锯齿难。故 Slughorn 用于交互 3D、AR/VR、飞行、移动 HUD、CAD/数字孪生等无法预知视距视角处。

看差异

用 Slughorn(osgSlug)渲染同大写 R,对比单通道 SDF、MSDF、Rive、osgText 位图及其派生 SDF。每纹理面板同预算 64 纹素/em,区分在技术非分辨率。

正对烘焙尺寸六中五几乎同:Slughorn、Rive、MSDF 复现轮廓,单通道 SDF 仅腿根角稍圆;osgText 位图(64px/em 放大四倍)无法恢复未存细节。

倾入透视则变:掠射下 Slughorn 和三距离场面板保持 R 净边,因字形平面逐像素算覆盖投影无成本;osgText 随远模糊;Rive 的 R 变形,其仅受 2D 仿射变换,透视非仿射只能中心精确边缘漂。

极放大仅基于曲线渲染器 Slughorn 和 Rive 仍直净边(Rive 每帧重细分);距离场面板缺刻因插值不匹真曲线;osgText 溶为单灰梯度。

公平注记:各纹理法同 64 纹素/em,给更多推回伪影不除;SDF/MSDF 默认烘焙,MSDF 纠错软某些缺刻;Rive 视图最佳每帧经相机渲染,比通常嵌 3D 画入纹理贴面更优,后者避畸但如位图糊。

正面对比

| 关注点 | 位图图集 | SDF | MSDF | 细分/Rive | Slug | | --- | --- | --- | --- | --- | --- | | 任意尺度清晰 | 否 | 部分 | 大多 | 是 | 是 | | 尖角 | 烘焙尺寸是 | 否 | 是 | 是 | 是 | | 极小尺寸 | 每尺寸烘焙 | 弱 | 较好 | 好 | 好 | | 大字形集内存(CJK) | 极高 | 高 | 高 | 低 | 中 | | 动态/变文字 | 重烘焙 | 重烘焙 | 重烘焙 | 重细分 | 免费 | | 3D透视 | 软 | 可 | 可 | 好 | 极好 | | 重动画矢量艺术 | 否 | 否 | 否 | 极好(Rive) | 好 | | 低端/老 GPU | 极好 | 极好 | 好 | 不定 | 需强着色器 | | 实现复杂度 | 低 | 低 | 中 | 高 | 中到高 |

浅绿标 Slug 最优或并列最优。

该用哪个

无单一赢家,按活选具:

  • 用 Slug(horn):需任意尺度 3D 透视清晰文字(VR/AR/xR),巨或动态字形集,文字常变,或混合矢量 UI 入实时管线。如 GIS 座舱、仿真标签、空间域显示、AR 叠加、移动清晰界面。
  • 用 MSDF:欲清晰可缩放,可预烘焙图集,广硬件乐用。简游戏 HUD 应用 UI 佳默。
  • 用平 SDF:硬件受限文字静可忍角软。
  • 用位图图集:固定 UI 固定尺寸最简可移植。
  • 用 Rive 或细分渲染器:活是设计矢量动画艺术非主要文字。

还有更多

常提文字因 Slug 得名,但 Slughorn 画任何填充描边矢量几何任后端,即全 SVG 含渐变分层动画,地图制图尺度清晰达预烘焙不及。更多将演示,未提特性见 Slughorn GitHub。

吹 Slughorn 的号

Slughorn 是我们现代 C++20 实现 Slug。构建时一次重活无运行细分:轮廓数据和带结构预存,着色器仅估覆盖。不特殊待字形:任何矢量路径同管线同质渲染。吃 SVG、FreeType、Blend2D/Cairo/Skia 路径,露 Canvas 风 API 直创作形,填充描边渐变合成单 GPU 轮廓图集。瞄 OpenGL、Vulkan、WebGPU、DirectX,带 Python 绑定及 C++ API,同渲染嵌 HUD 到全 3D 场。

Slug 算法属 Eric Lengyel,发 Journal of Computer Graphics Techniques,2026 年 3 月公域自由实现。Slughorn 是其易用实现。

评论

讨论整体认可这篇文章的选题和参考文献(不少人点名 Eric Lengyel 是传奇),但很快分成两派:一派认为 MSDF 加图集在工程上依然更划算,另一派被 Slug 直接从轮廓出字的精确度吸引;同时有相当多人怀疑文章本身是 LLM 写的,据此给其中的论断和细节打折。

认为 MSDF 在真实项目里仍然够用且更省心

  • 首个例子里 MSDF 观感更好,只有透视场景下 Slug 占优;自己在 WebGL 小游戏里就是用 MSDF 渲染清晰文字(较多人)
  • MSDF 图集不必静态烘焙,可以异步上传,所以「CJK 字形太多、图集爆炸」并非无解;渲染本身很便宜,甚至能在 CPU 上做,真正贵的是图集生成,而那是每字每字体一次性的成本(较多人)
  • 质疑 Slug 的运行时开销:可能要沿射线在数据里游走,带来大量纹理采样;MSDF 只取目标纹素加邻域,GPU 能在算数学前就并行取好,还天然兼容 mipmap(较多人)
  • 小字号下 MSDF 尖角会出问题,把 distance range 调大就好(少数人)

认为 Slug 精确度更高,但代价和限制被低估

  • Slug 观感惊艳;自己最有名的项目本质就是一个 MSDF 着色器加 bloom 通道,完全够用,但如果要支持任意文本,可能会转向 Slug(较多人)
  • SDF 最大的好处是容易叠效果,几行着色器就能加描边和边缘柔化;Slug 只回答「这个点在字形内还是外」,不告诉你距离,所以这类效果做不了,抗锯齿得另外处理(较多人)
  • 有人给出基于 sokol_gfx.h 的 Slug 示例,同时承认该实现取了不少巧:没有 kerning、没有从右到左、没有 text shaping(较多人)
  • 传统渲染器(如 FreeType)会做 hinting,把曲线吸附到像素网格,文章里的 GPU 方法都很难做这件事;CJK 图集可以用只针对可见字形的动态 CPU 图集解决;距离场在插值处的缺口,理论上可以用 SDF 的屏幕空间导数算出边缘像素的部分覆盖率来修(较多人)

认为专利叙述有硬伤,且公有领域化会带来跟风乱象

  • 2017 年发表的东西不可能 2019 年才申请专利,作者应该是先申请后发表,正确说法是「2019 年被授予专利」;文章在这一点上前后矛盾,而它又是 AI 写的(较多人)
  • Eric 一宣布 Slug 进入公有领域,肯定会冒出一堆粗制滥造的「OpenSlug」,值得看谁会胜出(较多人) > 一宣布进入公有领域,我们就会看到几百个「OpenSlug」式的糊弄产物。(@logdahl)

认为比较本身有遗漏,也有概念混淆

  • 比较漏掉了 Rook & Possum 的 Scanline Sweeper,而 Sean Barrett 独立发明了同一思路的 CPU 版本,用在 stb_truetype 里(较多人)
  • 文章有时把「tessellation」和「Rive」混为一谈:Rive 只是采用细分法的渲染器实现,通用细分方案未必不能支持任意变换;另外 head-to-head 表只给 Slug 赢的项目标绿,按公平原则每一类都该标出赢家,比如 Rive 的低内存明明胜过 Slug 的中等占用(较多人)
  • 看不出 Slug 相对「MSDF 加光栅回退」有什么显著收益,它更精确,但这点边缘分辨率提升是否值得换来复杂得多的、依赖 GPU 的渲染管线,需要自己实测而不能听信一篇明显是 AI 写的文章(较多人)

怀疑文章由 LLM 生成,因而整体降低信任

  • 有人直言受够了读 LLM 生成的文章;也有人看到署名就直接跳过;专利那处不一致被当作 AI 写作的证据之一(较多人) > 天哪,我真的受够了读 LLM 生成的文章。(@jdanford)

有价值的补充

  • 基于 sokolgfx.h 的 Slug 示例同时提供 WebGPU 与 WebGL2 后端,底层用 stbtruetype.h 和 stb_ds.h 解析 TTF,再把曲线数据压成 Slug 着色器要的运行时格式;补充者认为这类工作更应该放进离线资产管线。
  • 同一人提到 Mikko Mononen 的 Skribidi 是一套完整文本渲染栈(并非基于 Slug),但依赖 Harfbuzz、SheenBidi、libunibreak 等一长串库——这恰好说明国际化文本渲染本身有多难。
  • 有人自写字体光栅化器,把贝塞尔曲线用 de Casteljau 细分成单调段,让绕数计算大幅简化并可并行(GPU 用 warp/subgroup,CPU 用 SIMD)。因为字体里大多数曲线本来就是单调的,拆分带来的曲线增量很小。两个优化:先用包围盒对 uv 空间的像素块做剔除;在只有无旋转、无斜切、无透视的仿射变换时,把每像素解二次方程所需的开方和除法摊到每行每列,从 n² 降到 2n,而这两步本身就占三成以上计算量。据称其 GPU 基准不输 Slug。
  • 有人吐槽 MSDF 生态就是 XKCD 2347 的翻版:全世界十几年来都在用 Viktor Chlumský 硕士论文里那一个 msdfgen,一种图形技术居然只被实现过一次就到处复用,实在该有人去打破它。
  • 另一条平行工作:有人基于 Fable 5 提出的公式做了 GPU 曲线渲染器 Windfoil,思路上和 Slug 有相似之处,未必总是更快,但只用单带而非双带,着色器存储更少,抗锯齿质量更接近盒式滤波的真值。