沃诺克:利用GPU几何放大技术处理矢量图形
《Proceedings of the ACM on Computer Graphics and Interactive Techniques》:Warnock: Harnessing GPU Geometry Amplification for Vector Graphics
【字体:
大
中
小
】
时间:2026年07月18日
来源:Proceedings of the ACM on Computer Graphics and Interactive Techniques 3.1
编辑推荐:
摘要
AI总结:要查看此由AI生成的总结,您需要拥有高级访问权限。了解更多信息并登录。
摘要
Warnock是一个新颖的2D向量图形库,它利用了GPU的可编程几何放大功能。Warnock通过提供一种实用的像素空间质量指标来完善极坐标描边理论;此外,它还将极坐标描边扩
摘要
AI总结:要查看此由AI生成的总结,您需要拥有高级访问权限。了解更多信息并登录。
摘要
Warnock是一个新颖的2D向量图形库,它利用了GPU的可编程几何放大功能。Warnock通过提供一种实用的像素空间质量指标来完善极坐标描边理论;此外,它还将极坐标描边扩展到能够填充路径。Warnock将路径转换为单个紧凑的GPU缓冲区,这样该缓冲区就包含了填充和描边路径所需的所有数据。与以往的技术不同,这个GPU缓冲区可以处理各种变换、描边宽度、端点处理以及连接样式的变化。Warnock支持带有细分着色器的旧版DirectX 11类GPU,而带有网格着色器的新型GPU则能实现最佳性能。
AI总结(实验性):此总结是使用自动化工具生成的,并非由文章作者撰写或审核。它旨在帮助人们发现相关内容,协助读者判断文章的关联性,以及帮助来自相关研究领域的读者理解该文章。它的作用是补充作者提供的摘要,而作者提供的摘要仍是论文的主要总结。完整文章才是权威版本。点击此处了解更多信息。点击此处对该总结的准确性、清晰度及实用性发表意见,您的反馈将有助于改进未来的生成版本。要查看此由AI生成的通俗语言总结,您需要拥有高级访问权限。
图1:Warnock的渲染流程始于HPG 2026标志的单一统一GPU存储数据表示形式(最左侧),首先按照四步依次完成对标志路径的描边(顶部)、填充(底部),最终得到结果(最右侧),这一过程是通过GPU细分着色器或网格着色器实现的极坐标细分技术来完成的。
1 引言
Warnock和Wyatt在1982年提出的关于二维向量图形的基础研究成果,确立了2D分辨率无关图形的基本渲染操作,尤其是曲线路径的填充和描边功能。他们早期的实现方式是使用基于CPU的扫描线光栅化器来渲染图像。随着GPU可编程性的提升,原本为3D图形设计的图形硬件也被巧妙地改造用于渲染2D向量图形,如今这一功能已广泛应用于全球的网页浏览器及其他应用程序中。
1.1 用于路径细分的GPU几何放大技术
然而,现有的方法并未充分利用GPU的几何放大功能,尤其是GPU细分技术以及最近的网格着色技术。我们所介绍的GPU细分和网格着色技术将路径渲染中的几何扩展步骤完全交由GPU处理,而且重要的是,无论是填充还是描边,都可以通过同一个紧凑的GPU缓冲区来完成。我们将其命名为Warnock,以此向首位系统化研究2D向量图形的已故John Warnock致敬。我们的Warnock软件库充分利用GPU的几何放大功能,应用适合GPU并行处理的创新细分算法来渲染路径。在Warnock中,将特定路径从常规的CPU表示形式(即一系列路径指令及对应的控制点)转换为GPU表示形式只需一次线性时间转换即可完成。一旦路径的GPU表示形式被转换并下载到GPU中,且被纳入图形管线后,只需最少的3D API命令即可启动可编程GPU着色器来填充或描绘原始路径,如图1所示。与以往技术不同的是,当改变渲染状态,如坐标空间变换、填充规则、描边宽度、笔形、连接样式、端点处理或着色状态时,无需修改路径的GPU缓冲区。相反,只需进行简单的缓冲区绑定,或者可能更换不同的着色器程序,就能实现常见的2D向量图形模式切换。这是因为所有必要的路径细分操作都在GPU内部完成,从而减少了CPU在路径绘制中的参与,同时也完全消除了CPU在路径细分过程中的作用。
目前尚未有任何在GPU图形管线中运行的路径渲染方法具备以下特点:
(1) 对于任何路径,都存在一个用于填充和描边的单一紧凑GPU缓冲区表示形式;
(2) 几何放大、剔除操作以及像素空间误差范围计算都在GPU高效的可编程图形管线内部完成;
(3) 仅需通过更换着色器程序、纹理或GPU缓冲区,即可支持多种标准的2D向量图形渲染模式(甚至包括投影变换和基于纹理的虚线效果)。
Warnock之所以能够同时具备这三项特性,是因为极坐标描边理论及其在极坐标填充中的应用,使得GPU能够在为每段路径、连接点或端点进行初始设置时,计算出为满足指定的像素空间质量指标而所需的几何放大程度,从而在实际进行几何扩展之前完成相应处理。
1.2 论文贡献与结构
1.2.1 我们的贡献:
(1) 开发并实现了极坐标填充技术,这是一种基于GPU加速的路径填充方法,它与极坐标描边共享相同的极坐标评估理论,同时还能适应可编程GPU细分技术以及网格着色技术,而且设计上要求输入的格式对于填充和描边来说是相同的紧凑GPU表示形式;
(2) 提出了用于极坐标细分的像素空间细分指标,并将其应用于极坐标描边和填充操作中。
1.2.2 文章结构:
第2节回顾了有关GPU加速向量图形的现有研究。第3节阐述了我们将路径分解为各个片段、通过极坐标细分实现几何放大以及所使用的像素空间误差指标的相关原理。第4节介绍了我们在GPU细分着色器和网格着色器中实现极坐标填充和描边的方法、利用可绑定缓冲区管理渲染状态以及其他相关细节。第5节通过实验评估了Warnock在利用GPU几何放大功能进行向量图形渲染方面的效果。第6节为结论部分。
2 现有研究
2.1 基于CPU的向量图形渲染
早期的路径渲染软件依赖于基于CPU的扫描线光栅化器。即便在今天,基于CPU的路径渲染系统也大多仍使用扫描线光栅化器。扫描线光栅化器所需的内存占用相对较低。所谓“扫描线”,指的是每条路径都是逐行水平扫描线进行光栅化的。为了填充曲线段内部的区域,通常首先将路径简化为近似的线段条带。而要描边路径,则需要通过描边偏移量,使路径边界在其切线方向上垂直移动描边半径的距离,这样就可以对偏移后的区域进行填充。对于二次贝塞尔曲线和三次贝塞尔曲线的偏移操作在数学上较为复杂,因此人们提出了多种近似方法,Yzerman在2020年以及Levien和Uguray在2024年又提出了新的方法。
2.2 基于GPU的向量图形渲染
虽然已经有人提出了专门的硬件实现的扫描线渲染器,但与基于现有GPU图形管线构建的高性能解决方案相比,专门用于2D向量图形的硬件所带来的额外成本往往难以被接受。
2.2.1 GPU图形管线方法
与我们的工作最为相似的现有研究,是那些利用传统GPU图形管线来实现路径填充和描边的方法。微软的Direct2D API建立在Direct3D之上,它将填充和描边的路径分解为梯形,再由GPU以三角形对的形式批量渲染。但由于路径向梯形的细分操作是在CPU上完成的,因此Direct2D更多可以说是一种在GPU辅助下的渲染方式,而非真正的GPU加速。Loop和Blinn在2005年提出了一种在片段着色器内高效处理曲线边缘光栅化的方法。Kokojima等人则在2006年将Loop-Blinn方法与模板缓冲区结合使用,用来计算帧缓冲区样本相对于TrueType字体轮廓的缠绕次数。Slug算法(由Lengyel在2017年提出)在渲染基于轮廓字体的填充字形方面效率极高。通过将预细分过的TrueType字形的网格着色器几何放大功能与条件性的二次贝塞尔曲线边缘光栅化相结合,就可以实现文本的渲染。Kilgard和Bolz在2012年将Kokojima的方法扩展到了包括椭圆路径段、描边、虚线效果以及任意路径的裁剪在内的全部路径渲染功能。他们的“先模板处理,再覆盖”方法被作为OpenGL扩展功能实现,名为NV_path_rendering。Batra等人在2015年在NV_path_rendering的基础上,进一步增加了PDF格式所需的功能,如图层、用于打印的CMYK色彩模式以及渐变网格。
目前,用于2D向量图形的主流GPU加速系统是谷歌的Skia,它为Android系统、Chrome浏览器以及微软的.NET框架提供渲染功能。Skia经过不断发展,采用了多种细分技术和“先模板处理,再覆盖”的方法来实现路径的填充和描边。Skia中最复杂的着色器会使用实例化顶点着色器来对填充和描边的路径进行细分。借助实例化顶点着色器,CPU只需发出一条绘制指令,就能在GPU上生成n个相同的几何图形副本,而这n组图形可以通过当前的顶点着色器进行不同的变换处理。具体的n值需要由CPU计算并指定。与GPU几何放大功能相比,实例化顶点着色器会导致冗余工作,因为GPU几何放大功能会在GPU内部通过初始的着色器阶段(对于网格着色器来说是任务着色器,对于GPU细分来说则是控制着色器或外壳着色器)来计算出所需的批次大小及各项参数。相较于几何放大方法,实例化顶点着色器会带来更多的工作量,同时还要求CPU预先预估最坏情况下的几何扩展规模。
2.2.2 GPU计算方法
随着可在GPU内部但并非在传统图形管线之外进行可编程并行计算的技术出现,比如NVIDIA的CUDA,为路径渲染的GPU加速提供了另一种途径。这类方法源自向量纹理技术,即在GPU的片段着色器内部对分辨率无关的边界进行评估。通过利用GPU的通用计算能力,一些研究人员开发出了向量图形系统,这些系统会在GPU内部构建整个向量图形场景的加速结构,从而能够以编程方式对场景进行光栅化处理。还有一种混合式方法,即先运行计算着色器来并行计算描边结果,然后再利用传统的图形管线,通过直线和圆弧来渲染得到的近似结果。不过,这类方法往往存在场景构建速度慢的问题(对于动态场景尤为不利)、内存使用范围难以预测、负载平衡不佳、功能集不完整(例如缺乏描边、虚线效果、裁剪、图层以及其他重要功能),并且难以与已经使用现有图形库的应用程序集成。
3 我们的方法
3.1 路径极坐标细分的泛化
GPU在计算机图形处理中能够发挥强大的并行计算能力,但这种计算机制主要是为绘制均匀的3D三角形流而设计的,而非处理那些尺寸不定、包含多种路径指令及对应控制点、且存在诸多几何复杂问题(如孔洞、凹陷、重叠、曲线形状、端点处理、连接方式以及尖点等)的2D路径。由于存在上述几何复杂问题,要精确地对填充和描边的2D路径的覆盖区域进行细分其实相当困难。采用简单的均匀参数化细分方法,即便在单一段曲线内部,也容易出现过细分或欠细分的情况,而且无法确保像素空间细分误差处于可控范围内。虽然递归曲线分割算法能够提供较好的误差控制效果——就像基于CPU的扫描线路径渲染器所做的那样——但其递归特性与GPU着色器的并行处理理念相悖。
3.1.1 极坐标描边
极坐标描边方法基于成熟的理论,能够以均匀的极坐标角度增量来计算梯度变化。这里的“极坐标”指的是,通过极坐标形式表示的曲线段梯度,可以以均匀的极坐标角度步长来逐步推进细分过程,从而使细分沿着曲线以恒定的转角增量进行。通过对梯度角度变化的限制,也可以限制细分的面角大小,使其不超过梯度角度变化值的两倍。在Warnock实现的极坐标描边技术中,有一个重要的改进之处,那就是在用于极坐标描边的曲线段间隔的两端,额外增加一步极坐标角度的细分,因为面角可能达到梯度角度变化值两倍的这种情况通常出现在曲线的拐点附近,也就是间隔的末端。这样的半步处理实际上有助于更好地控制面角的大小。
不过,这样的角度限制并不能也无法为像素空间的位移误差提供约束。因此,我们提出并实现了一种无需递归的有效策略,用于计算梯度角度变化,从而能够合理地控制细分操作在像素空间内的位移误差(详见第3.6节)。图1展示了以绿色标记的这种描边步骤。3.1.2 极坐标填充。Warnock通过调整极坐标描边方式,在填充路径时为每条路径轮廓生成锚定三角形扇形结构,并以与描边相同的手段限制像素空间内的位移误差。假设模板缓冲区被初始化为某个固定值,那么通过为路径中的所有轮廓渲染这些锚定三角形扇形,同时增加正面三角形的模板计数并减少背面三角形的模板计数,便能在模板缓冲区中确定路径的填充范围[Neider等人,1993年]。随后,会渲染一个预先计算好的、能够覆盖路径所有轮廓的凸多边形(即覆盖几何体),以此为路径内的所有被覆盖像素着色,同时重置模板缓冲区,为下一条路径的渲染做准备。图1中以橙色标记的即为这种填充步骤。3.2 将路径分解为连接段图2展示了路径中可能存在的不同类型连接段的分类:每个端点都有其对应的端点样式,而连接样式则决定了每个连接段的几何形状。在GPU能够对填充或描边的路径进行细分和渲染之前,Warnock必须先将路径分解为更简单的组成部分,即连接段。这一过程被称为路径烘焙,它会将每条路径分解为两个数组:(1)连接段数组,以及(2)控制点坐标数组。每个连接段包含其类型以及控制点坐标数组中的六个索引。不同的连接段类型(如图2所示的分类)决定了如何解读这些索引。Warnock共定义了十种连接段类型:•三次贝塞尔线段连接段,包括用于表示线段的退化三次贝塞尔曲线;•二次贝塞尔线段连接段;•以标准化有理二次贝塞尔线段形式表示的圆锥曲线连接段[Lee,1987年];•端点连接段:路径起始端点连接段、路径终止端点连接段、路径起始虚线端点连接段以及路径终止虚线端点连接段;•连接点连接段;•尖点连接段(与连接点连接段类似,但忽略连接样式,且始终为圆形);以及•用于表示隐式闭合轮廓的隐式闭合连接段。路径连接段数组中的每个连接段都独立地规定了利用GPU的几何放大功能对相应路径进行细分的所需参数。无论是在GPU细分处理还是网格着色处理中,Warnock对连接段的编码方式有所不同,但从概念上讲,这两种编码方式都会将信息转换为连接段类型以及一组坐标索引,从而从路径的控制点坐标数组中获取该连接段相关的控制点。虽然每个连接段有六个控制点索引,但实际上最多只能指定四个独特的(x, y)控制点位置。连接点连接段和各种端点连接段类型分别用于生成描边时的连接点和端点,但在填充过程中会被跳过。隐式闭合连接段则会扩展为一段锚定线段,用以闭合那些没有通过ClosePath命令明确闭合的填充轮廓。与连接点连接段和端点连接段不同,隐式闭合连接段在填充处理时会使用,而在描边处理时则会被跳过。端点的实际样式(扁平、三角形、正方形或圆形)由着色器根据着色器状态决定,这些状态建立了端点位置与端点样式之间的映射关系。同样,连接点的样式(无、斜切、三角形或圆角)也取决于着色器状态。3.2.1 位置控制点与渐变控制点。一旦确定了每个连接段的类型,就会为该连接段在路径坐标数组中的控制点索引进行分配。虽然三次贝塞尔线段只需要四个控制点,但六个控制点索引使得可以独立于线段的控制点来指定连接段的起始渐变和终止渐变。对于三次贝塞尔曲线类型的连接段,虽然有四个控制点用于构成曲线,但还有两个额外的控制点用于指定起始渐变和终止渐变。通常情况下,渐变控制点会重复中间两个控制点(第二个和第三个)的索引值;不过,当位置控制点重合时,渐变控制点则指向第一个非重合的控制点,以便通过差分计算出合适且非退化的起始或终止渐变值。对于线段而言,前两个和后两个位置控制点是重合的,而渐变控制点则分别对应起始渐变和终止渐变的端点位置。对于二次贝塞尔连接段,虽然只有三个位置控制点,但渐变控制点仍然用于指定起始渐变和终止渐变,以弥补控制点重合的情况。对于圆锥曲线连接段,第二个(中间的)控制点是以带有w坐标的2D齐次坐标(x, y, w)形式存储的。对于三次贝塞尔曲线或w值为无穷大的圆锥曲线来说,其尖点位置有四个重合的位置控制点,此时渐变控制点则用于指定尖点的起始渐变和终止渐变。连接点连接段和端点连接段的四个位置控制点也都是重合的。对于连接点连接段,渐变控制点用于指示连接的进入方向和离开方向;而对于端点连接段,一个渐变控制点即可确定端点的负法线和正法线方向。3.2.2 将弧线视为圆锥曲线样条。在路径烘焙过程中,路径渲染标准中所规定的各种圆形和椭圆形弧线的参数表示方法会被分解为一系列等效的圆锥曲线连接段和连接点连接段。由于数值上的原因,那些w值接近零或无穷大的退化圆锥曲线,对于直线和尖点而言,必须被分解为一系列三次贝塞尔连接段。3.2.3 额外的填充状态。用于填充的路径烘焙过程还包括:(1)一个包含(x, y)坐标值的锚定控制点数组,路径中的每个轮廓都有一个这样的控制点;(2)一系列数量为1到6的连接段,用于表示路径各段连接段构成的凸包;以及(3)该覆盖几何体对应的(x, y)控制点坐标。在经过填充处理的路径中,每个轮廓都有其专属的烘焙后的路径连接段序列以及对应的锚定控制点。第3.5节将详细介绍填充过程中如何使用这些状态。经过处理的极坐标描边和填充的完整状态会被存储在图1中所标注的同一个统一GPU缓冲区中。3.3.1 GPU细分技术。虽然这十种连接段类型在整体几何形态上存在差异(线段、连接点、端点等),且在处理方式上也各有不同,但Warnock提出的基于极坐标计算的统一细分策略使得所有类型的连接段都能通过同一个着色器程序进行处理。因此,在实际应用中,尽管处理的连接段类型不同,GPU的几何放大着色器阶段仍能通过高度优化的着色器执行流程高效地完成工作。无论是路径细分的准备工作,还是基于极坐标描边或填充的逐顶点计算,都在标准GPU图形处理 pipeline中的几何放大阶段中进行。例如,OpenGL 4.0或DirectX 11风格的细分着色器,可能会用到几何着色器,而较新版本的GPU则可能采用网格着色器。与网格着色器相比,GPU细分技术在提前对路径进行烘焙时的具体处理方式有所不同。关于路径烘焙的详细内容,我们已在补充文档[Kilgard和Barran,2026b年]中有详细阐述。图3展示了GPU中的细分技术概览。图4则展示了任务着色器和网格着色器的概览。3.3.1 GPU细分技术。图5根据Direct3D的规定[Microsoft,2025年](15.16.1有效位置范围),在光栅化处理之前,GPU会丢弃那些由一个或多个具有NaN(非数字)位置坐标的顶点构成的图元(左侧)。示例中的描边路径位于右上角;示例中每个连接段在(u, v)贴图空间中的GPU细分网格位于右中间;而整个示例的最终GPU细分结果则位于右下角。细分着色器的两阶段处理流程[Purcell,2010年](如图3所示)首先会生成初始控制着色器(OpenGL版本)或外壳着色器(DirectX 11版本),这类着色器会接收与路径中某个连接段对应的六个控制点输入数据,然后根据某种质量指标——可以是像素空间范围内的限制条件——计算出极坐标计算所需的参数,包括需要进行极坐标计算的次数。之后,后续的评估着色器(OpenGL版本)或域着色器(DirectX 11版本)则会执行逐顶点的极坐标计算,并输出相应的贴图顶点。Warnock通过一种我们称之为“NaN污染”的创新技术,对传统的四边形输出贴图几何结构进行了改造,使得输出几何结构被“分割成条带”,从而形成连续的三角形条带,用于描边处理(见图5),或者被“分割成扇形”,用于填充处理。另一种方法是,等值线细分着色器可以将数据传递给几何着色器,进而形成三角形条带。这些三角形要么构成用于填充的锚定三角形扇形,要么构成用于描边的由成对三角形组成的四边形条带,随后这些条带会被传递给光栅化器。经过光栅化处理后的片段在更新模板缓冲区和颜色缓冲区之前,还会经过着色和覆盖范围计算。3.3.2 网格着色技术。借助当前世代GPU所具备的网格着色功能[Kubisch,2018年;Kubisch和Brown,2018年],两阶段的细分处理流程(如图4所示)被分为任务着色器和后续的网格着色器两部分。任务着色器会执行与细分控制着色器相同的极坐标计算准备工作,但它不会为每个贴图区域生成细节级别参数,而是会创建多个网格着色器工作组。当这些网格着色器工作组启动后,它们会执行极坐标计算,并为填充用的锚定三角形扇形或描边用的三角形条带构建索引化的顶点缓冲区。为了提高网格着色器的执行效率,每个任务着色器工作组处理的都是包含多达8个连接段的连接段组合。由于GPU细分着色器是基于贴图区域的,而网格着色器与任务着色器的执行方式属于单指令多线程架构,因此针对极坐标填充和描边处理,GPU在数据表示层面需要采用截然不同的结构。3.3.3 共同的处理流程:准备阶段、极坐标计算阶段、光栅化阶段。在GPU渲染路径的过程中,路径中的各个连接段会被分配给GPU的并行计算资源(即着色器线程)进行处理,这样一来,每个连接段都可以并行处理。每个连接段都要经历一个连接段准备阶段,在此阶段,该连接段会被分类,其变换后的控制点会被收集起来,极坐标计算所需的参数也会被计算出来,同时还会根据某种质量指标来确定处理该连接段所需的顶点计算次数。在完成这个初步的连接段准备阶段后,就会进入几何放大阶段。随后,会根据每个连接段后续极坐标计算所需的分割精度,启动相应的着色器线程,这些线程会执行极坐标计算,从而为每个连接段生成所需的描边或填充顶点几何结构。最终,这些顶点几何结构会形成三角形条带(用于描边)或三角形扇形(用于填充),这些生成的几何结构会被传递给GPU光栅化器,进一步转换为片段,之后这些片段会被着色,同时用于更新帧缓冲区的模板缓冲区和颜色缓冲区。为了实现良好的抗锯齿效果,并遵循路径渲染“仅混合一次”的规则,渲染特定路径时需要进行两次处理。第一次处理称为“模板”阶段,此时会将路径的填充或描边区域渲染到模板缓冲区中,此阶段不会进行任何颜色写入操作。接着是第二次渲染阶段,称为“覆盖”阶段,该阶段会依据第一次处理生成的模板覆盖信息进行判断,将模板值重置为默认状态(通常是零),然后对片段进行着色,并将该片段与其对应的像素颜色进行混合。更换当前的着色器程序是一项相对耗时的操作,因此避免更换程序是非常有利的。由于极坐标填充的锚定几何结构和覆盖几何结构都是从相同的路径编码中生成的,且使用的是相同的极坐标填充着色器程序,因此“模板”阶段和“覆盖”阶段之间无需更换着色器程序。极坐标描边的“模板”阶段和“覆盖”阶段同样使用相同的极坐标描边着色器程序。3.4 使用连接段进行极坐标描边。在进行极坐标描边时,着色器程序会丢弃所有的隐式闭合连接段。如果通过简单的剔除检查能够确定某个描边连接段的几何结构完全位于视图投影框之外,那么该连接段也可能被丢弃。这种检查需要为所有被描边半径扩大的控制点计算出简单的裁剪代码,然后确认这些控制点都位于至少一个视图投影框的裁剪平面之外。如果启用了圆角连接,那么在计算扩大幅度时还必须考虑圆角限制。无论出于哪种原因丢弃了一个连接段,都意味着该连接段不会再被进一步处理(也不会为其生成任何几何图形)。之后,剩余的连接段会被细分成一系列三角形,从而近似表示出路径的轮廓,这一过程如Kilgard [2020c]所述。单个绑定的GPU程序会依次执行“模板”操作和“覆盖”操作,因此这两个步骤之间不会发生程序绑定;其间最少的状态变化为:(1)通过一次简单的缓冲区绑定来改变程序的运行模式,以及(2)调整图形管线的模板和颜色配置。13.5 带连接的极坐标填充在极坐标填充过程中,着色器程序会忽略所有连接点和端点连接(因为这类连接仅对描边有效)。由于填充的控制点不会因描边宽度而扩大,所以简单的剔除检查更为简单。而对于路径描边来说,细分结果是连续的四边形序列(以三角形对的形式输出);而在路径填充中,路径中每个闭合轮廓的细分结果则会形成有锚点的闭合三角形扇形。所谓闭合扇形,是指将扇形的第一个非锚点顶点复制为扇形的最后一个顶点,从而形成环绕整个轮廓的循环结构。如果子路径未被显式闭合,则可通过ImplicitClose连接来实现闭合。所谓的间接绘制命令允许通过仅一次API调用即可对任意复杂的路径进行模板处理或覆盖操作。在极坐标填充的“模板”步骤中,极坐标计算方式与描边时相同,但每个生成曲线轮廓并非以该曲线的起点为基准偏移,而是以轮廓内的重心位置为锚点,从而形成该轮廓的闭合扇形结构。在极坐标填充的“覆盖”步骤中,1到7个有锚点的线段连接会形成一个具有3到8条边的凸多边形,该多边形能够充分覆盖“模板”步骤所生成的几何结构。3.6 极坐标细分的像素空间误差度量图6显示了通过极坐标描边方式细分的立方贝塞尔线段,其最大转角误差度量为4度。作为一种与分辨率无关的保形度量标准,放大图像并不会影响细分效果。当放大到曲率最低的边界区域时,细分后的线条(橄榄色四边形轮廓)与实际描边边界(青色和品红色曲线)之间会出现细微但可观察到的间隙。(为更明显地展现误差,本图已关闭3.1.1节中提到的半步细分功能。)图7显示了图6中同一线段的最大像素位移误差度量为0.75像素。这是一种与分辨率相关的度量标准,放大图像时会自动增加细分程度。由于任何位移误差都小于1像素,这一度量标准无法检测出细分线条与实际描边边界之间的差异。线条曲率较高的部分(顶部凸起处)可能存在过度细分的情况,但这其实是出于限制位移误差的考虑,以便让曲率较低的区域(线段两端)拥有足够的细分程度。最初,极坐标描边方法仅为最大细分面角提供了误差上限(见图6)。这种保形性保证与像素分辨率无关,因此也无法确保细分后的边界与实际描边(或填充)后的路径段边界之间存在较小的像素级位移(理想情况下为亚像素级)。为解决这一问题,Warnock在极坐标描边理论的基础上引入了一种新的误差度量方法,该方法能够在不过度细分的情况下合理限制极坐标描边(或填充)生成的边界多边形与对应的严格凸且单调的子曲线之间的弗雷歇距离[Bringmann等人,2019]。这些子曲线相互连接,共同构成路径中每段曲线路径的实际描边(或填充)边界。“在不最小化的前提下进行限制”意味着Warnock旨在将最大像素位移误差控制在某个规定的正像素值db以内,但也意识到一旦误差低于像素级别,过度细分路径几何结构并不会带来任何质量上的提升。需要特别说明的是,我们并非声称能够计算出整个路径及其完整多边形细分的弗雷歇距离,而是确保所有严格凸且单调的子曲线之间——这些子曲线通过与直线边界段相连构成完整的描边(或填充)路径边界——与Warnock对应的多边形近似值之间的弗雷歇距离都能被一个可配置的最大像素位移值合理限制。为实现这一目标,Warnock的着色器实现方式为每个连接区间独立计算最大转角值,以此作为依据来进行后续的极坐标描边(或填充)细分操作。在确定了该最大转角值后,即可按照每个连接区间计算出的最大转角所需步数,正常进行细分处理(无需其他修改)。所有与这种像素空间误差度量相关的计算都在GPU细分的控制着色器或网格着色的任务着色器中完成。3.6.1 测量曲线近似的相似度弗雷歇距离是一种用于衡量两条曲线相似性的指标,它同时考虑了点的位置和顺序。严格来说,度量空间(X, d)中两条曲线A: [0, 1] → X和B: [0, 1] → X之间的弗雷歇距离,是由Alt和Godau[1995]定义的:δF(A,B)=infr,smaxt∈[0,1]d(A(r(t)),B(s(t))),其中r, s: [0, 1] → [0, 1]是具有公共端点的连续、非递减的映射函数,即r(0) = s(0) = 0且r(1) = s(1) = 1。这一通用定义属于对无限维函数的优化问题,对于Warnock的应用而言过于复杂。因此,我们对其应用方式进行了简化,使其更具实用价值。对于Warnock而言,度量空间(X, d)为二维欧几里得像素空间;曲线A是一条二维的严格凸且单调的曲线,它是某条曲线路径的描边(或填充)边界的一部分;曲线B则是通过极坐标描边(或填充)生成的、用于近似曲线A的多边形边界;同时,曲线A和B具有不同的端点以及相同的公共端点。不同端点意味着A(0) ≠ A(1),而公共端点则意味着A(0) = B(0)且A(1) = B(1)。重要的是,曲线B的所有多边形顶点都位于曲线A上。当某条曲线路径既不是严格凸的也不是单调的时,我们假设将该路径的理想边界拆分为多个严格凸且单调的子曲线区间,而极坐标细分机制本身就已经完成了这种拆分操作。这些拆分后的子曲线随后会被各自用一条多边形来近似,使得子曲线与其对应的近似多边形拥有相同的公共端点。如果某个连接段仅由直线边缘组成(例如方形接头、斜接或倒角接头,或是线段),那么该边界可直接用直线或多边形表示,此时极坐标细分无需进行任何近似处理,也就无需进一步讨论(此时弗雷歇距离为0,显然小于db值)。虽然弗雷歇距离的通用形式要求对任意的重参数化进行连续优化,但通过我们的简化假设,便能够在极坐标细分的背景下对弗雷歇距离做出实用的界定。3.6.2 通过限制切线角度来约束弗雷歇距离在设计像素空间度量标准时,我们希望开发一种迭代式(非递归式)流程,能够高效地为某个连接区间i计算出“质量控制参数”即最大切线角度步长阈值qi,该阈值能够合理限制在该区间内,通过极坐标计算过程生成的多边形与该区间对应的生成曲线之间的最大像素空间弗雷歇距离,这一限制还需考虑到从生成曲线到多边形的某个偏移量r。在填充操作中,r的值为0,而在描边操作中,r则为描边半径。采用Kilgard[2020c]的符号表示法,极坐标计算机制定了一个函数t[Ψk,Ψk+1](ψ),其中[Ψk, Ψk + 1]表示一个特定的切线角度区间范围[k, k + 1],该范围内的曲线曲率要么全为正,要么全为负(因为是严格凸曲线),且角度变化幅度小于180°(因为是单调曲线)。在这个区间范围内,存在且仅存在一个t值,我们将其记为tF,该值的对应角度与从pk点到pk+1点的弦线角度一致。由于区间[k, k + 1]内的曲线是严格凸且单调的,因此该区间的方向ω可表示为:ω=sgn(sin?(Ψk+1?Ψk))(?)intervalorientation(?1or+1),即方向ω的值为-1或1。区间曲线上的任意一点都可以通过一组三元组?θ, t, p?来唯一标识,该三元组包含该点的切线角度θ、参数t以及位置p,满足条件g(t) = pt,且g′(t)·? ? sin?θt, cos?θt? = 0,这意味着曲线的梯度与切线角度方向呈90度垂直关系。最终,我们关注的是从?Ψk, tk, pk?到?Ψk + 1, tk + 1, pk + 1?的每一个连接区间k,能否通过基于多边形与该区间曲线之间弗雷歇距离的近似方法得到良好的近似效果。我们的目标是确保所有路径中曲线链接的所有区间k的该弗雷歇距离都小于或等于预设的像素距离上限db。与其考虑整个区间,不如假设我们已经知道子区间?θa, ta, pa?和?θb, tb, pb?上的两个点a和b,且满足ta < tb,这样就可以形成另一个子区间[a, b]。我们希望计算从pa点到pb点的弦线与该子区间[a, b]所代表曲线之间的相似程度,具体方法是计算该弦线与该子区间之间的弗雷歇距离,如图8所示。图8展示了在路径链接的区间k内计算子区间[a, b]的弗雷歇距离dF的情况(左侧),以及单独的切线角度和法向量(右侧)。首先,按照以下步骤确定远离从pa点到pb点这条弦线的、位于向外弯曲的偏移子曲线上的点OF:Δ=pb?pa(?)chordgradientθF=atan2(Δy,Δx)(?)chordangletF=t[θa,θb](θF)(?)parametrictmatchingthechordanglepF=g(tF)(?)positionoftFn(θF)=??sin?θF,cos?θF?(?)normalvectortothechordangleOF=pF+ωrn(θF)(?)outwardbendingmaximallyoffsetcurveposition 由于边界子曲线是严格凸且单调的,它会“向外弯曲”,因此ω的符号与生成子曲线的曲率符号一致。连接区间[a, b]的起始点和结束点的向外偏移位置分别为:Oa=pa+ωrn(θa)Ob=pb+ωrn(θb)二维点b到由两点a和c构成的直线之间的最小距离为:d(a,b,c)=‖(b?a)×(c?a)‖‖c?a‖ 根据我们补充文档[Kilgard and Barran 2026a]中的引理1,d(a, b, c)实际上就是从a点到c点的弦线与以a点和c点为端点的严格凸且单调曲线(即从Oa点到Ob点的[a, b]区间内的描边或填充子曲线边界)之间的精确弗雷歇距离,且该曲线在点b处的最大位移量即为d(a, b, c)的值。具体而言,点OF就是[a, b]区间边界子曲线上的这样一个点。既然已经知道了从Oa点到Ob点的弦线与该段边界从Oa点到Ob点之间的弗雷歇距离,接下来就可以计算:dF=d(Oa,OF,Ob) 如果dF ≤ db,那么目标就达到了;但如果未达到该条件,Warnock(在任务着色器或控制着色器中)将会启动一个迭代过程,不断寻找合适的qi值,以降低像素位移误差,直到dF ≤ db为止(或者达到设定的最大迭代次数)。在介绍这个迭代过程之前,我们先来看看递归过程会如何处理这种情况。如果计算得到的dF ≤ db,那就说明误差限制已经达成。然而,如果dF > db,我们可以在tF处将生成子曲线和偏移子曲线分开,然后分别重新计算左半部分区间[a, F]和右半部分区间[F, b]的dF值,其中F = ?θF, tF, pF?。之后我们可以继续递归地处理左右两个子区间,直到所有递归分割后的子区间的dF值都小于或等于db为止。此时,能够确保满足像素空间误差限制的最大切线角度步长阈值q,就是所有满足dF ≤ db条件的子区间中,θa与θb之间的最小绝对角度差。如果以这种方式不断递归分割子区间,那么我们又该如何根据这些多个子区间来推断整个区间的弗雷歇距离呢?我们补充文档[Kilgard and Barran 2026a]中的引理3证明了:如果一条严格凸且单调的二维曲线在某一点处被分割成两段(而极坐标细分恰好能够保证这一点),那么整条曲线的弗雷歇距离,就等于其各个分割片段对应的弗雷歇距离中的最大值。通过递归应用这一引理,我们的递归过程最终得到的完整区间的多边形细分结果,其弗雷歇距离也将等于所有构成该区间的子区间弗雷歇距离中的最大值。不幸的是,由于这种方法是递归式的,因此在着色器环境中并不实用——不过其实也没必要这么做。因为每一个区间都是严格凸且单调的,所以那些在分割后仍存在dF > db问题的子区间,实际上都是曲率最低的区域。这些区域必然位于范围的两端。因此,只要dF > db成立,迭代方法只需不断探索并必要时分割曲率较小的子区间即可。关于内弯尖点的补充说明:在描边时,存在两个子曲线边界N和P,它们分别是当r > 0时相对于g的负向和正向偏移曲线,根据ω的不同,其中一个为外弯,另一个为内弯。如果g是严格凸且单调的,那么外弯也会如此,但当r足够大时,内弯容易出现尖点,从而不再保持严格凸或单调性。我们已经将这类内弯尖点视为特殊情况,因为此时面角没有上限[Kilgard 2020b]。当遇到此类内弯尖点时,我们忽略像素空间中的位移误差(如图6和图7所示),因为这类误差很可能“隐藏”在原始曲线的描边部分(或连接处、端点处)。而容易观察到的位移误差出现在外部偏移曲线上,该曲线仍保持严格凸且单调。
3.6.3 迭代方法。由于子区间具有严格凸且单调的特性,我们只需通过迭代方式探索dF较小的左侧或右侧,而非递归地探索两侧,即可限定位移误差。直观上,人们可能认为应该在dF较大的那一侧进行迭代,因为我们的目标是让dF降至db阈值以下。但实际上,dF较小的那一侧意味着整体曲率更低。当曲率较高时,每次迭代都能更快地降低dF;而曲率较低时,每次迭代对dF的降低幅度则较小。因此,应选择dF较小的那一侧进行迭代。
Warnock首先将迭代次数j初始化为0,然后根据给定的a0 = ?Ψk, tk, pk?和b0 = ?Ψk + 1, tk + 1, pk + 1?,按照上述方法计算OF和dF。如果dF ≤ db,则无需再迭代,仅需1步即可。否则,需在?ΨF, tF, pF?处计算子区间分割后的左侧和右侧的OF及dF值。对于左侧子区间[a, ?ΨF, tF, pF?],计算OF, left和dF, left;对于右侧子区间[?ΨF, tF, pF?, b],则计算OF, right和dF, right。如果dF, left ≤ db且dF, right ≤ db,则在第j次迭代后结束迭代。若未达到条件,则增加j的值,若dF, left < dF, right,则继续探索子区间[a, ?ΨF, tF, pF?],否则探索[?ΨF, tF, pF?, b]。如此重复,直到找到dF ≤ db为止(或迭代次数超过设定值)。实际上,像素空间的位移大致呈几何级数下降。
为确定最大切线角度步长阈值q,我们每次迭代都会增加j的值,直至dF ≤ db。在区间i的每次迭代j中,我们会保存dF以及面角的正弦值,计算公式为:dj=dF,sj=sin?(θfacet)=|(OF?Oa^)×(Ob?OF^)|。当达到阈值时,即在某次最终迭代j中,Warnock会通过对数线性插值方法计算出中间面角值(以此弥补两次迭代之间误差的几何级数下降):qi=sin?1?exp2?(log2?sj?1+log2?db?log2?dj?1log2?dj?log2?dj?1(log2?sj?log2?sj?1))(1)。有了区间i对应的qi值后,就可以计算所需的步数Δi:4 Δi=?|δi|qi?。图7展示了将该误差指标应用于与图6相同内容时的结果。
使用对数线性插值法计算面角(公式1)这一做法值得探讨。另一种方法是直接使用sin?1(sj)作为面角,但这往往过于保守,容易在细分过程中引发“2的幂次级联现象”。所谓级联现象,是指视图比例的变化可能导致多个区间需要一次性进行更多(或更少)的细分操作。这种情况存在两个问题:其一,由于级联效应导致细分速度过快,会出现渲染卡顿或性能骤降;其二,突然的细分变化会导致视觉上的突兀感。我们发现,通过对面角进行对数线性插值,可以使细分级别更平滑地变化。不过这种方法的轻微副作用是,极少数情况下,最大像素空间位移误差的限定值并非完全严格,数值上稍高于db的位移也有可能被允许通过。由于db本身已经是亚像素级别(Warnock的默认值为0.75),因此不会产生明显影响,而平滑的细分级别变化所带来的好处远大于此。若想降低数值误差,可适当调低db的值。
为了解释这一像素空间误差指标的动态特性,我们的补充材料中包含了一段视频,直观展示了该指标对应的细分效果,并将其与最大转角指标进行了对比。由于实际的像素位移误差是低于限定值的一系列微小距离的分布,因此动态直方图能够显示随着路径视图变换,这一分布是如何变化的。
4 实现方式
Warnock库是用C++语言结合OpenGL开发的。它还提供了C、C++和Python版本的接口。Warnock的核心在于其用GLSL编写的着色器,这些着色器用于GPU细分运算及网格着色,从而实现极坐标填充和描边功能。
4.1 GPU细分
图9展示了用于极坐标GPU细分的顶点着色器工作流程,每个控制点对应一个顶点。图10展示了用于极坐标GPU细分的细分控制(壳)着色器的工作流程,每条连线对应一个补片。图11展示了用于极坐标GPU细分的细分评估域着色器的工作流程,每对棱顶点对应两个评估顶点(四边形补片),或每条棱对应一个顶点(等值线)。图9为GPU细分所使用的顶点着色器的流程图,图10为对应的细分控制着色器流程图,图11则为细分评估着色器流程图。在等值线模式下,简单的几何着色器会将每条线段扩展为一对三角形。有关这些不同着色器阶段在GPU图形管线中的运作方式,可参考图3。
4.2 网格着色
图12展示了用于网格着色的任务着色器流程,每个工作组最多可处理8条连线。图13展示了用于网格着色的网格着色器流程。这些着色器阶段在GPU图形管线中的运作方式,可参考图4。
4.3 可绑定缓冲区控制渲染模式
统一缓冲区绑定用于控制极坐标细分过程的运行。Warnock依靠十种统一缓冲区绑定来管理各类状态,包括设置、表面属性、变换参数、绘制参数、笔触参数、多边形形状、弧长队列、每遍渲染控制参数、变换校正参数以及实例化变换参数。为了输入连线数据和控制点数据,GPU细分依赖于顶点数组以及顶点着色器进行的变换,从而将连线转换为由6个顶点组成的补片;而每条轮廓的锚点则是通过实例化机制获取的。
5 对于圆锥曲线,有一种技巧是使用奇数的顶点编号来标识带有w分量的延伸控制点(见图9)。不过,网格着色则不需要顶点数组和顶点着色器,因此需要额外的一组着色器存储缓冲区对象(SSBO)绑定,用来访问控制点、连线包以及每条轮廓的锚点数据。
4.4 光栅化、插值与着色处理
4.4.1 光栅化与插值
由于投影变换、弧长纹理处理以及采样数量多于颜色采样数量等因素的相互作用,Warnock在片段光栅化处理方面做了大量优化。它具备片段着色器功能,可根据需要实现透视校正或四边形插值[Hormann and Tarini 2004]。
4.4.2 位置不变着色
Warnock支持向量图形标准中的标准(非程序化)着色功能,包括纯色、线性渐变、径向渐变、图像渐变,甚至是双点圆锥渐变[Skia team 2021]。我们将这类着色模式称为位置不变着色,因为它们的效果仅取决于被着色样本的(x, y)位置,且不受其他线性变换的影响。由于填充和描边操作都遵循“仅混合一次”的标准规则,因此对于位置不变着色而言,渲染顺序并无影响。
5 实验分析
我们的主要实验研究了预先在GPU上生成的路径所占用的内存容量,以及Warnock的渲染性能与其他方案的对比情况。为进一步分析Warnock的剔除机制和任务级并行性,我们的补充文档[Kilgard and Barran 2026c]详细研究了链接剔除的效果,以及在不同32线程工作组下调整连线数量对Warnock网格着色编码性能的影响。
5.1 预先生成路径的内存占用情况
图14展示了表1中所列路径的可视化结果。表1的内容如下:
路径名称 路径复杂度计数 CPU数组占用内存 NV_path_rendering占用内存 极坐标GPU细分占用内存 极坐标网格着色占用内存 CPU数组内存的倍数
fill stroke bothfill strokeboth fillstrokeboth NVprGPU tess.Mesh shading
tiger 2402,510 12,174 51,206 178,720 740,064 918,784 69,376
81,336 95,552 68,480 85,520 93,840 17.94 ×1.87 ×1.83 ×
cougar 122,439 116,424 488,135 1,661,700 4,441,368 6,103,068 926,608
741,572 972,032 677,824 666,232 720,120 12.50 ×1.99 ×1.48 ×
dragon 12131,268 5,285 20,260 64,888 85,148 9,920 7,528
10,064 6,976 6,640 7,088 16.11 ×1.90 ×1.34 ×
star 16104648 320368 96192 224144 208256 8.00 ×4.87 ×5.57 ×
butterfly 1613561,485 7,740 31,320 39,060 2,064 1,816
2,176 1,968 1,952 2,064 26.30 ×1.47 ×1.39 ×
Arial 1001,822 5,588 24,174 61,232 172,144 233,376
33,200 46,524 58,112 42,784 47,176 56,840 9.65 ×2.40 ×2.35 ×
Pacifico 1006,190 24,148 102,782 331,920 756,224 1,088,144
124,352 147,104 185,600 160,272 145,392 173,392 10.59 ×1.81 ×1.69 ×
Wingdings 1005,345 16,478 71,257 181,672 509,192 690,864
99,440 120,328 155,040 119,680 117,120 145,968 9.70 ×2.18 ×2.05 ×
Fig. 1标志 12169113,860 12,552 57,112 69,664 8,784
6,712 9,216 5,952 5,536 6,416 18.05 ×2.39 ×1.66 ×
Celtic dogs 15,031 29,068 121,303 424,984 1,099,064
1,524,048 232,848 177,148 235,424 165,984 157,736 169,032 12.56 ×1.94 ×1.39 ×
Detail girl 1171,640 638,209 2,724,476 8,631,468
18,704,112 27,335,580 9,683,920 6,528,100 10,092,512
4,271,952 3,965,992 4,710,952 10.03 ×3.70 ×1.73 ×
表1展示了图14及其他图表中所展示的路径在GPU上预处理后的内存占用情况。CPU数组一栏显示了仅存储1字节的路径指令及其对应的浮点坐标(每个浮点数占4字节)所需的内存基数。NV_path_rendering则指预处理后的填充和描边数据在GPU上的存储大小,这一数值仅为填充和描边部分之和。极坐标GPU细分和极坐标网格着色分别表示仅填充、仅描边以及两者合并后的存储大小。CPU数组内存的倍数这一列则表明某种表示方式的存储大小是CPU数组基础大小的多少倍,数值越小说明该表示方式越紧凑(加粗显示的数值最小)。其中“tiger”指的是Ghostscript字体中的老虎图案;Arial、Pacifico和Wingdings则是从这些字体中各选取的100个字符。表1中的数据反映了图14及其他图表中所展示路径的GPU内存占用情况。CPU数组一栏为基准值,用于显示仅存储1字节长的路径指令及相应浮点坐标所需的内存量。由于NV_path_rendering也在GPU上存储数据,因此我们需要比较极坐标格式下的GPU细分、网格着色以及NV_path_rendering三种方式的存储大小。与NV_path_rendering不同,极坐标格式的填充和描边数据可以使用相同的路径坐标,因此其“两者合计”一栏的数值虽为填充和描边部分之和,但实际上小于该两者的单独数值之和。当已知某路径的渲染意图仅为填充或仅为描边时,其预处理后的表示形式可以更加紧凑,表中的填充和描边对应列正好体现了这一点。对于NV_path_rendering、GPU细分和网格着色三种方式,最右边的三列分别显示了其存储大小是CPU数组基础大小的多少倍。在除“star”之外的所有案例中,网格着色方式的存储大小均小于极坐标GPU细分方式的存储大小。“star”案例出现异常是因为该路径的复杂度较低(仅有5个控制点),导致其数据需要分为2组连线包,但第二组并未被完全填满。而在其余7种情况下,网格着色方式的存储大小均更小。总体而言,极坐标预处理方式比NV_path_rendering方式更为紧凑,尤其是在处理描边任务时表现更为突出。
5.2 与同类向量图形系统的性能对比
我们在NVIDIA RTX 3500 Ada世代笔记本电脑的GPU上,对Warnock与另外四种2D向量图形API——Cairo 1.16、Skia Ganesh(2019版)、Windows 11 Direct2D以及NV_path_rendering——进行了性能测试,测试对象为40个常用的静态SVG场景,这些场景涵盖了多种不同的路径复杂度。每个场景都在从约100 × 100像素到2000 × 2000像素不等的不同视口尺寸下进行渲染。我们根据总像素面积将数据点分为三类:低分辨率(< 0.25百万像素)、中分辨率(0.25–2百万像素)和高分辨率(> 2百万像素)。由于Warnock的GPU细分预处理格式既可以通过“毒补丁”方式处理,也可以通过几何着色器方式处理,因此我们将其中表现较好的一种称为“GPU tess”,而另一种采用独立连线包预处理格式的网格着色方式则称为“Mesh shd”。Cairo和Skia无论在何种帧缓冲区配置下都会以相同方式渲染每个场景,而Warnock和NV_path_rendering的渲染性能则会随质量等级的不同而有所差异(我们有8:8、4:4和16:1三种质量级别的测试数据可供参考)。所有API在测试前都会先预处理路径数据,因此计时的是渲染时间而非预处理时间。表2展示了相关测试结果。低分辨率:<0.25百万像素
中分辨率:0.25–2百万像素
高分辨率:>2百万像素
Warnock与其他图形API的加速比
在8:8质量下,针对40个SVG场景的几何平均加速比如下。数值大于1表示Warnock更快;数值小于1则表示其他API更快。W/L表示在每个分辨率区间内Warnock更快/更慢的场景数量。
表2总结了三个分辨率区间的几何平均加速比。在所有分辨率区间和全部40个测试案例中,Warnock的速度都远快于Cairo和Skia,且在高分辨率下的优势更为明显(例如,在高分辨率下,其网格着色器的加速比为26.6倍,而Cairo为相应值)。与Direct2D相比,根据分辨率的不同,Warnock的网格着色器方法在40个测试案例中的32–35个案例中更具优势,几何平均加速比为2.8–4.6倍,并且会随着分辨率的提高而上升。NV_path_rendering的整体速度仍快于Warnock,其在网格着色方面的几何平均优势约为2.0–2.4倍,这得益于NV_path_rendering在驱动程序层面高度优化的状态管理和实例化路径渲染功能。无论是在4:4、8:8还是16:1的质量级别下,Warnock相对于Cairo、Skia和Direct2D的优势,以及NV_path_rendering相对于Warnock的优势都保持一致。我们的补充文档[Kilgard和Barran 2026d]提供了所有质量级别的各场景详细数据。
结论
Warnock利用了GPU的几何放大功能,尤其是GPU细分和网格着色技术,用于路径的填充和描边操作。这种利用方式得益于极坐标描边(以及现在的极坐标填充)能够以一种无需递归的有效方式预判所需的几何结构扩展。针对极坐标描边和填充缺乏像素空间误差界限的问题,Warnock引入了一种仅基于迭代(无递归)的度量方法,以此合理限定位移误差。Warnock通过在GPU上使用单一的路径表示形式来支持描边和填充操作,同时通过调整缓冲区和程序绑定,可实现各种变换、描边宽度、端点处理方式、连接样式以及着色效果的变化。实验表明,与NV_path_rendering相比,这种方式大大降低了存储路径所需的GPU内存容量。Warnock的速度快于Cairo和Skia,与Direct2D相当,但慢于NV_path_rendering;进一步的优化有望缩小这一差距。目前,Warnock是基于OpenGL实现的,但该方法也适用于其他现代3D API。我们已通过将Warnock的算法和着色器移植到Vulkan和SPIR-V上并验证其正确性,但目前还没有完整的库实现。虽然超出了本次展示的范围,但Warnock还具备许多其他用于GPU加速2D图形的创新功能,比如弧长纹理映射、多边形形状的笔触,以及能更快渲染包含梯度信息的2D有符号距离场[Frisken和Perry 2006]。这些功能都是基于Warnock的极坐标细分方法自然衍生出来的。
致谢
Nick Hammel、Tristan Lorach和David Luebke为这项工作提供了支持。