在 3D 渲染过程中,顶点数据通常会被频繁访问,如何有效地利用 GPU 的顶点缓存(Vertex Cache)来减少对同一顶点的重复处理,是提升渲染效率的一个重要手段。针对这一需求,业界普遍采用顶点缓存优化算法来重新排序网格的索引数据(Index Buffer),从而尽量让相邻的三角形复用最近使用过的顶点。Tipsify 便是此类算法中的一种常见实现。
1. 为什么需要顶点缓存优化
渲染管线中,GPU 通常会将“最近访问过的顶点”缓存在硬件的顶点缓存中。假设顶点缓存大小为 N,那么如果在绘制三角形时所需的顶点恰好在缓存里,就能省去顶点变换的重复计算,减少 GPU 的负载,从而加快渲染速度。如果对每个三角形都得从头计算一次顶点变换,那么将极大地浪费 GPU 性能。
为了让“即将使用到的顶点”更大概率地留在缓存中,需要对网格中的索引(Index Buffer)进行排序,从而让渲染时对同一顶点的访问尽量集中、连续。这种对网格索引的“重排序”过程就被称为顶点缓存优化(Vertex Cache Optimization)。
在 Cesium 等使用 WebGL 或现代图形 API 的 3D 引擎中,顶点缓存优化会显著影响 Tiles / 模型等 3D 几何数据的加载与绘制性能。Cesium 在对模型数据进行处理时,会使用 Tipsify 来进行顶点缓存优化。
熬了几个大夜!
总结来说, Tipsify算法在 GPU三维渲染中发挥了下面几个作用:
-
顶点缓存优化
对于需要在实时渲染中充分利用 GPU 顶点缓存、减少重复计算的场合(如游戏引擎、3D 地理可视化引擎等),文中的思路可以启示如何更好地对三角形索引进行排序。 -
网格简化
大规模网格(如城市级建筑模型、电影级别模型)需要在有限的硬件条件下实现渲染或交互,论文所述的顺序化简策略有助于以更高效率减少网格面数,同时尽量保持视觉质量。 -
纹理坐标保持与优化
对建筑、角色或地理数据进行简化时,保持或改善纹理质量是一个不容忽视的需求。论文针对 UV 参数化的讨论也可以为相关项目提供可行的方法。
废话不多说, 直接上代码, 看看 Cesium 是怎么用的:
基于三个策略:
-
维护一个活跃列表(这里可以理解为“deadEnd”栈 + 其他辅助逻辑),将可能仍处在缓存中的顶点优先处理。
-
基于顶点在三角形中的使用情况(numLiveTriangles)来判断哪些顶点还“值得”优先绘制,以尽可能复用缓存。
-
使用 timeStamp 等启发式 来判断“近期使用”与“尚未使用”的顶点,提升被访问顶点的局部性。
interface VerticeType {
numLiveTriangles: number; // 顶点还涉及多少个尚未被绘制的三角形
timeStamp: number; // 顶点最近一次被访问的时间戳. 用来做缓存启发式。越新的 timeStamp,表明这个顶点越“活跃”(更有可能还在 GPU 缓存中)。
vertexTriangles: number[]; // 这个顶点所属的所有三角形索引