GPU文本渲染的技术抉择:从位图到Slug

文本渲染看似简单,实则复杂。字母并非图片,而是由直线和贝塞尔曲线构成的闭合轮廓。在CPU上光栅化是成熟方案,但在GPU上实现任意尺寸、3D变换下的每帧清晰渲染仍是难题。多数引擎通过预烘焙字形纹理来规避,但需承受相应妥协。

2017年,Eric Lengyel提出Slug算法,直接在片段着色器中从轮廓渲染字形,无需纹理图集或每帧细分。Lengyel于2019年申请专利,并定于2026年3月17日将其贡献至公共领域。基于此,AlphaPixel构建了C++20实现的Slughorn库。本文将解析从位图图集到Slug的GPU文本渲染工作流及适用场景。

为何字形渲染极具挑战

可缩放字体将字形存储为矢量轮廓:TrueType使用二次贝塞尔曲线,OpenType (CFF) 使用三次曲线。填充通常遵循非零缠绕规则。渲染器需同时满足三点:正确填充内部、提供清晰抗锯齿边缘、在任意尺度(从8像素菜单项到全屏广告牌)下保持锐利。GPU需在每帧绘制数千个字形且理想情况下不重新光栅化,这一约束导致了不同技术路线的权衡。

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

这是最古老且常用的方法:将字形以单一尺寸光栅化并存入共享纹理图集,屏幕字符通过采样对应槽位绘制。其优势在于速度快、易移植。但缺陷明显:放大超过烘焙尺寸会导致模糊或像素化;缩小则产生闪烁,除非使用多级渐远纹理(mipmaps)。每种语言、每个尺寸都需新图集,对于中日韩(CJK)等数万字形的语言,内存开销巨大。此外,位图无法感知3D透视,导致表面文本模糊。

方案二:有符号距离场(SDF)

Valve在2007年SIGGRAPH上提出的SDF曾是行业标准。它存储每个纹素到最近边缘的有符号距离(内正外负)。着色器采样并在零处阈值处理,利用距离插值实现平滑放大和廉价抗锯齿。SDF纹理小、分辨率无关,是UI和游戏HUD的默认选择。但其本质仍是固定分辨率烘焙,双线性插值会圆滑锐利角落(如“A”的顶点),且在极端缩放或小尺寸下细节丢失。

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

Viktor Chlumsky在2015-2018年的研究中提出MSDF,通过红绿蓝三通道编码不同边缘子集的距离,利用中值技巧重建锐利角落。MSDF在放大时比SDF更清晰,msdfgen工具采用MIT许可证并被广泛采用。然而,MSDF仍依赖预烘焙图集,面临动态文本、庞大字符集的内存和管线成本。三通道查找消耗更多带宽,且在极小尺寸下仍受限于采样率。

方案四:细分与覆盖(Loop-Blinn、NV_path_rendering、Rive)

此类方法跳过纹理,将轮廓转换为GPU几何体:

  • Loop-Blinn:馈送弯曲三角形,结合模板缓冲区解决缠绕,但抗锯齿实现困难。
  • NV_path_rendering:先模板后覆盖,质量高但依赖NVIDIA硬件扩展。
  • Pathfinder:将边缘细分为微三角形,计算有符号梯形面积,基于图块在现代GPU上速度较快。
  • Rive:2024年开源,将抗锯齿矢量路径转化为三角形补丁,通过像素局部存储并行光栅化,动画矢量艺术可达120 fps。

细分方法实现真正的分辨率无关,适合动画矢量图形。但代价是几何体膨胀、细分成本高昂、抗锯齿复杂,且部分方案依赖特定硬件。

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

Slug跳过图集和每帧细分,将字形保持为存储在GPU缓冲区中的二次贝塞尔曲线和线段列表。它构建轻量级每字形加速结构(水平带),使像素仅需计算附近曲线。

片段着色器直接解析覆盖范围:对每个像素投射射线,计算与贝塞尔曲线的交叉点及缠绕数。核心创新在于Lengyel的“根资格”(root eligibility)测试,确保曲线交汇处的缠绕数学精确,避免裂缝或重复计数。由于通过分析求解而非采样,Slug在任意2D/3D变换(包括透视)下均能保持锐利,无烘焙分辨率限制。

Slug无需为CJK等大字集准备视频级大小的图集,仅需字体大小的轮廓数据。文本可每帧更改而无烘焙成本,适合实时数据和本地化内容。它在单次绘制中使用普通片段着色器完成,无需厂商扩展。当摄像机视角、缩放不可预测时(如VR/AR、飞行模拟、CAD),Slug优于依赖固定分辨率烘焙的图集、SDF和MSDF。

直观对比与选型建议

在相同每em 64纹素预算下,对比Slughorn(Slug实现)、SDF、MSDF、Rive和位图图集。在透视倾斜和放大边缘时,基于纹理的方法出现模糊或伪影,而Slug保持锐利。SDF和MSDF虽优于位图,但在极端角度下仍会发生混叠或圆滑。Rive在动画矢量表现优异,但在3D映射时可能像位图一样模糊。

关注点 位图图集 SDF MSDF 细分 / Rive Slug
任意尺度下锐利 否 部分 大部分 是 是
锐利角落 仅在烘焙尺寸下 否 是 是 是
极小尺寸 按尺寸烘焙 弱 更好 好 好
大型字形集内存 (CJK) 非常高 高 高 低 中等
动态/变化文本 重新烘焙 重新烘焙 重新烘焙 重新细分 免费
3D 和透视 柔和 尚可 尚可 好 优秀
重度动画矢量艺术 否 否 否 优秀 (Rive) 好
低端/旧 GPU 兼容性 优秀 优秀 好 视情况而定 需较强着色器能力
实现复杂度 低 低 中 高 中高

淡绿色标记表示 Slug 是最佳或并列最佳选择。

选型指南

  • 选择 Slug (Slughorn):需任意尺度和3D透视下锐利文本(VR/AR/xR)、巨大或动态字形集、文本频繁变化或混合矢量UI渲染。适用于GIS、视觉仿真、空间显示及AR叠加层。
  • 选择 MSDF:需锐利可扩展文本、可预烘焙图集、追求广泛硬件兼容性。是游戏HUD和应用UI的绝佳默认值。
  • 选择纯 SDF:硬件受限、文本静态、可接受柔和角落。
  • 选择位图图集:固定UI、固定尺寸、追求最简单便携方案。
  • 选择 Rive 或细分渲染器:主要任务为动画矢量艺术设计,而非纯文本。

Slughorn:Slug的现代C++20实现

Slughorn是AlphaPixel对Slug技术的实现。它在构建时预处理轮廓数据和带状结构,运行时无需细分,着色器仅评估覆盖范围。Slughorn不特殊对待字形,任何矢量路径(SVG、FreeType、Blend2D、Cairo、Skia)均通过同一管道渲染。它支持OpenGL、Vulkan、WebGPU和DirectX,提供Python绑定和C++ API。

随着Slug专利于2026年3月进入公共领域,Slughorn旨在降低该技术的使用门槛。若你正受困于3D场景中的模糊标签、图集内存限制或移动锐利文本需求,Slughorn提供了针对性解决方案。