地形渲染
Terrain Rendering
地形渲染(游戏、Google Earth、开源大世界引擎 Cesium 等)要在巨大高度场上按距离分配细节,同时控制内存、绘制调用和 LOD 之间的裂缝与跳变。主流 GPU 友好方案有:类似纹理 clipmap 的几何 clipmap、按瓦片复用顶点缓冲只换索引缓冲的分块方案、基于四叉树和屏幕空间误差的 chunked LOD、预存所有过渡索引缓冲的受限四叉树,以及 GPU 细分和压缩等补充手段。任何方案都可叠加分形噪声以在拉近时提供细节,许多系统也在加载时程序化生成地形。
几何 clipmap(19.10.4 节)
与纹理 clipmap 一样使用类似 mipmap 的层次:几何被过滤成越往上越粗的金字塔,每一层只在观察者周围缓存 个高度采样;最细层渲染整个方块,其他层是中空的方环。观察者移动时窗口随之移动,加载新数据、淘汰旧数据。相邻两层之间设置过渡区,几何与纹理在其中平滑插值到更粗一层,以避免裂缝,在顶点与像素着色器中实现。Asirvatham 与 Hoppe 的 GPU 实现把地形数据存成顶点纹理,由顶点着色器读取高度;可加法线贴图增强细节,Losasso 与 Hoppe 在近距离还叠加分形噪声位移。《巫师 3》使用了几何 clipmap 的变体;《神秘海域 3》把它的变体用于水面,并通过动态添加三角形避免 T 型顶点。
瓦片与索引缓冲复用
把高度场切成如 17×17 顶点的瓦片,近处整块一次提交,而非逐个三角形或小扇。每隔一个顶点取样得到 9×9,每隔四个得 5×5,每隔八个得 2×2,最后四个角得到两个三角形的 1×1。原始 17×17 顶点缓冲常驻 GPU 复用,只需换不同的索引缓冲即可改变三角形数。
Chunked LOD
Ulrich 的方法:地形有 级离散 LOD,每更细一级是父级的 4 倍划分,编码为四叉树从根遍历。节点的屏幕空间误差低于像素阈值 就渲染它,否则递归访问四个子节点,于是近处分辨率更高。进阶版按需从磁盘加载:子节点已在内存才递归,否则排队加载并先渲染当前节点。
屏幕空间误差:
其中 为屏幕宽度, 为相机到瓦片距离, 为水平视场角(弧度), 为与 同单位的几何误差。
几何误差常用豪斯多夫距离:对原网格每点求到简化网格的最近距离,取这些距离得 ;再反过来对简化网格每点求到原网格的最近距离得 ;。必须双向测量,因为从原网格点 o 到简化网格的最近点 s,与从 s 到原网格的最近点 a 并不对称。直观上它就是用简化网格代替原网格的误差。算不起时可对每次简化手动设常数,或在简化过程中记录误差。
防跳变:Ulrich 把高分辨率瓦片的顶点 与由父瓦片近似(如双线性插值)得到的 线性插值,插值因子为 ,截断到 (提取文本为「2sτ − 1」,分数线丢失;按 和 都是像素误差、且结果要截断到 复原: 时为 0, 时为 1)。变形时只需要高分辨率瓦片,因为低一级瓦片的顶点都包含在高分辨率瓦片中。
裂缝修补
相邻瓦片 LOD 不同时(如 33×33 挨着 9×9)边上会出现裂缝。做法:
| 方法 | 说明 |
|---|---|
| 重新缝合 | 去掉边上的高细节三角形,构造正确桥接两块的三角形 |
| 裙带/条带几何 | Ulrich 用额外的 ribbon 几何, 小于 5 像素时是合理方案 |
| 屏幕空间后处理 | Cozzi 与 Bagnell 用高斯核对裂缝周围(不在裂缝内)的片元加权来填补 |
| 逐顶点变形 | Strugar 用简单的顶点着色器,无需额外几何或屏幕空间处理;与 Ulrich 的逐节点 LOD 不同,他对每个顶点用各自的 LOD 变形,三角形分布更好更灵活;他只用距离,也可加入附近深度变化等因素以改善轮廓 |
| 匹配细分因子 | Kang 等人用 GPU 细分节点并保证边细分因子一致;还用保特征几何图像渲染高度场无法表达的悬垂地形 |
Sellers 等人把 chunked LOD 与视锥剔除和地平线剔除 (horizon culling) 结合以提高性能。
受限四叉树
Andersson(Frostbite)不用均匀瓦片网格,而是用四叉树瓦片:每块基础分辨率都是 33×33,但覆盖面积不同。受限指相邻瓦片 LOD 最多相差一级,因此邻接分辨率差异的情形有限,可以把包含过渡三角形的所有索引缓冲排列组合预先存好(全分辨率边 33 个顶点,低一级边 17 个顶点),每块一次绘制调用,既消除裂缝又减少绘制调用。
flowchart TD
A["四叉树节点"] --> B{"屏幕误差 s < 阈值 τ?"}
B -- "是" --> C["渲染该瓦片"]
B -- "否" --> D{"子节点已加载?"}
D -- "是" --> E["递归四个子节点"]
D -- "否" --> F["排队加载, 先渲染当前节点"]
C --> G["按邻居 LOD 选择过渡索引缓冲或变形避免裂缝"]如上图,chunked LOD 与受限四叉树都以四叉树遍历为骨架,区别在于如何处理相邻 LOD 的接缝。Widmark 描述了 Frostbite 2 的完整地形系统,包括贴花、水、地表装饰、用美术或程序化遮罩组合不同材质着色器、程序化地形位移。
其他做法
- 不规则三角网 (TIN):源数据通常是均匀高度场网格,可用视点无关简化直到满足某个判据,小细节用颜色或凹凸纹理表达;地形面积较小且有大片平坦区域时很有用。
- 海洋:每帧把一张均匀网格变换到相机空间,近处自然更密。
- 压缩:Yusov 用四叉树加简单预测只编码差值;Schneider 与 Westermann 用顶点着色器解码的压缩格式,并在 LOD 间做几何变形、最大化缓存一致性;Lindstrom 与 Cohen 用线性预测加残差编码的流式无损编解码,再量化可进一步提高压缩率(有损),GPU 解压,压缩率 3:1 到 12:1。
- 细分:《文明 5》用自定义计算着色器做自适应细分;也可用 GPU 细分器逐 patch 细分。许多地形技术同样适用于水面渲染。
GEA 的视角:高度场地形与地形工具(卷 II 11.6.3)
- 目标:模拟地表,作为摆放其他静态和动态元素的"画布"。地形有时直接在 Maya 等软件中建模;但玩家能看得很远时通常需要动态细分或其他 LOD 系统,还可能需要压缩超大室外区域的数据量(卷 II 11.6.3)。
- 高度场地形:数据量小,因为高度场通常存在灰度纹理里。多数系统把水平面(y = 0)细分成规则网格,从高度场纹理采样顶点高度;单位面积三角形数随离相机的距离变化,远处能看到大尺度地貌,近处保留丰富细节。具体 LOD 方案见本页 RTR4 部分的 clipmap、Chunked LOD 等。
- 地形工具:通常提供绘制高度场、开凿道路和河流的专用工具。纹理常是多层混合,美术通过"露出"某一层来画草、土、碎石,各层可交叉混合以平滑过渡。有的工具允许挖掉部分地形,插入普通网格做的建筑、壕沟等。地形编辑器有时集成在世界编辑器里,有时是独立工具。
- GEA 也提醒高度场只是建模地表的众多方式之一。
水面(卷 II 11.6.7)
GEA 把水面放在地形之后简短讨论,要点如下:
- 水的种类很多:海洋、水池、河流、瀑布、喷泉、水柱、水坑、潮湿的固体表面。每种通常要专门的渲染技术,有的还要动态运动模拟。
- 大片水域可能需要动态细分或其他类似地形系统的 LOD 方法(见上文)。
- 水系统有时要与刚体动力学交互(浮力、水柱的推力等),也要与玩法交互(湿滑表面、游泳、潜水、乘着竖直水柱上升等)。
- 水效果常由多种技术和子系统组合而成。例如瀑布可能同时用到专用水着色器、滚动纹理、底部水雾的粒子效果、类似贴花的泡沫覆盖层等。实时流体动力学等研究有望让水的模拟更丰富。
GPU Gems 的视角:GPU 上生成复杂程序化地形(GPU Gems 3 第 1 章)
来源:Ryan Geiss《Generating Complex Procedural Terrains Using the GPU》;摘录 Chapter 1. Generating Complex Procedural Terrains Using the GPU — Ryan Geiss。
不用 CPU 高度场,而用 密度场 + Marching Cubes:正密度=固体,零等值面=地表,天然支持洞穴与悬挑。DX10:像素着色器经实例化切片写入 密度体积;几何着色器/流输出对约 体素抽三角,写入可复用 VB 池(约 300),空块用 stream-out query 标记避免重生。LOD 保持体素数不变、远处块覆盖更大世界立方(),由近到远覆盖绘制。密度用分层噪声与扭曲可控,便于「程序化但仍可策划」。
出处
- realtime_rendering_4ed.pdf 第 19 章 Acceleration Algorithms
- Game_Engine_Architecture_4th_Edtion_Volume_2_-_Jason_Gregory.pdf
- Jason Gregory《Game Engine Architecture》第 4 版(2026)卷 II 第 11 章 11.6.3、11.6.7 节
- Chapter 16. Vegetation Procedural Animation and Shading in Crysis — Tiago Sousa
- Chapter 1. Generating Complex Procedural Terrains Using the GPU — Ryan Geiss
- developer.nvidia.com/gpugems/gpugems3/part-i-geometry/chapter-1-generating-complex-procedural-terrains-using-gpu