我们曾在
第1部分中提到最小化CPU-GPU数据传送的重要性,并介绍了整合静态顶点缓冲器与纹理中存储的海拔数据这一理念。
我将在本文讨论顶点数据格式和变体的问题。
Trigger Rally sreenshot
环形 Geoclipmap渲染使用一系列的方格“环绕”顶点,每个环都是此前环形的两倍,空间分辨率也是如此分布。这就形成了所有距离间的地形几乎一致的屏幕空间分辨率。位居最中央(最高分辨率)的环拥有其中心填充,成为一个简单的三角方格:
terrain-diagram4
以方格模式自我重复的几何形有一个良好的属性:我们不会让用户看到任何可视变化(除了移动的边缘),就可以通过准确的方格数量对其进行转换:
diagram5
我们可以运用这一属性移动几何体,令其接近摄像机之下,但不要让它的移动看起来过于明显。
每个环都有自己的方格大小,由于转换距离取决于几何大小,所以我们得分别移动这些环。因此就要让顶点着色器知道顶点属于哪个图层,这样才好让它正确变体。
所以我们需要的顶点属性就是:
*X轴位置
*Y轴位置
*图层属性
vertex attributes
在《Trigger Rally》中,我们使用的是[X,Y,X]向量,并将图像索引编程为Z,这样我们的原几何图的环形就会堆叠起来。
填充空隙 每个环都用不同的比例绘制,它们还使用多个比例进行转变。这里就有一个问题:当一个环形转变了,而其旁边的环形却没有转变,那么这就会产生一个空隙。
diagram8
修复这个空隙的一个方法就是使用额外几何形,即所谓的skirt扩大环形边缘。skirt是由许多更小的碎片集合而成,使用大量的小顶点缓冲器和谨慎的CPU逻辑,但这并非我们想要的结果。
所在在部署《Trigger Rally》的地形时,我花了数个小时试图找到一种无缝而完全静态的skirt设计方法,但却无果而终。
之后我在去年的WebGL Camp Europe现场见到了Florian Bösch,他建议我将环形做得更大一点,然后让它们重叠。
现在,富有经验的图像程序员肯定会说“不行!你不能重叠几何图形!这太浪费了,并且你会看到糟糕的深度冲突问题!”不过除了有一点透支之外,这种方法还算是一种很棒的解决方案,因为几何形匹配非常妥当。
变体 在这些环形的边缘之前,我们为几何形分配一个分辨率,令其紧挨着仅有其一半分辨率的几何形。我们必须在每个环形的边缘引进一个转换区域,仅几何形逐渐移动或从高分辨率向低分辨率变体,这样当你到达环形边缘时,它就会与其相邻的环形完美匹配。
diagram6
以下就是每个顶点要与另一个环形相匹配时所需移动的方式:
diagram7
我们要在顶点着色器中执行这种转换。最简单的方法莫过于将变体方向矢量作为顶点数据格式的一部分,但Florian对此却有更好的建议,即使用模运算!
让我们列出这些数据看看如何执行:
顶点坐标 0 1 2 3 4
MOD 2 0 1 0 1 0
MOD 4 0 1 2 3 0
变体矢量 0 -1 0 1 0
我们可以使用这个GLSL代码,从面点位置来计算变体矢量:
vec2 morphVector = mod(position.xy, 2.0) * (mod(position.xy, 4.0) – 2.0);
这不需要任何额外的顶点属性!
总结 我将在下部分文章中讨论《Trigger Rally》如何存储多分辨率海拔数据,以及它如何在顶点着色器中处理。之后我们还将探讨碎片着色器中的表面着色,以及如何高效地渲染布景网眼。