Skip to content

浏览器开放世界的动态 LOD 与流送地形生成

带 Perlin 噪声的高度图是程序化地形的默认起点。叠几层 fBm,应用一个颜色渐变,你就得到了像地形的东西。每篇教程到这里就结束了。但真实景观并不像堆叠的噪声。它们有水流凿出的河谷,应力裂痕塑造的崖面,数百万年侵蚀形成的洞穴和拱门。它们有相关联的纹理(平地上的草、陡坡上的岩石、林线之上的雪),这些纹理来自塑造几何形状的同一种物理过程。

本指南覆盖噪声之后的内容。基于物理的生成方法、处理洞穴和悬挑的体积表示、基于扩散的神经地形合成,以及在浏览器标签里以 60fps 渲染这一切所需的 GPU 驱动 LOD 和流送流水线。

这里的所有内容都瞄准我们的具体约束:在 WebGL 2 / WebGPU 中运行、通过网络流送、可由创作者编辑的多人开放世界。

为什么高度图不够

高度图为每个网格点存储一个高度值。它是一个 2D 函数:给定 (x, z),返回 y。这种表示紧凑、GPU 友好、渲染快。但它有对创作者世界至关重要的根本限制。

没有洞穴或悬挑。 高度图无法表示一个点有两个不同高度的地形。洞穴、拱门、悬崖悬挑、隧道和漂浮岛屿都不可能。Minecraft、No Man's Sky 和 Deep Rock Galactic 都因此需要体积地形。

没有垂直特征。 高度图中的垂直崖面是近乎无限的坡度,造成极端的纹理拉伸和碰撞伪影。真实崖面有水平特征(凸缘、裂缝),高度图无法表示。

噪声看起来像噪声。 即使有 8 个 octave 的 fBm 和域扭曲,地形也有合成感。它缺少真实地质的方向性结构:山脊线、排水网络、沉积、构造褶皱。这些图案来自物理过程,而不是噪声函数。

创作者编辑受限。 如果创作者只能修改高度,他们就不能挖隧道、造洞穴或建地下空间。对一个创作者能真正塑造的世界,地形表示需要支持减法和加法两者。

解决方案不是完全放弃高度图。它们对 90% 是简单表面的地形仍是最佳表示。解决方案是混合方法:高度图基础地形,在需要复杂几何的地方加体积叠加;为真实地貌做物理正确的生成;用神经合成提供噪声无法实现的多样性。

速答:我们实际会构建什么

在深入之前,先给出决策框架。文章的其余部分解释每块。

地形表示

使用混合高度图 + SDF系统。高度图覆盖整个世界(便宜、紧凑、成熟)。SDF 体只在洞穴、悬挑或创作者雕刻特征需要的地方存在(也许 5-10% 的 chunk)。这让 90% 的世界保持高度图成本,仅在需要时支持任意几何。

生成流水线

服务端运行的链式过程:

  1. Terrain Diffusion(或 MESA,用于文本提示)从种子生成基础高度图。这把噪声替换为以真实高程数据训练的地质真实地形。
  2. 解析侵蚀(stream power law)在毫秒级用河网和山脊线细化高度图。
  3. TerraFusion 或 Geodiffussr 从高度图生成相关纹理(或在 WebGL 2 回退中使用程序化坡度/海拔规则)。
  4. 生态系统模拟产生植被密度图。
  5. Arenite 风格侵蚀在地形要求处生成 SDF 体(崖面、拱门、洞穴)。
  6. 分块、压缩、上传到 CDN。 平均 chunk:2-8 KB。带体积数据的复杂 chunk:20-100 KB。

创作者通过调整参数(「更湿」、「更山」、「加洞穴」)、绘制意图,或直接用笔刷和 SDF 工具雕塑,与这条流水线交互。

LOD 策略

浏览器能力高度图 LOD体积 LOD植被 LOD
WebGPUGPU 驱动的四叉树(CDLOD)配合 compute culling + 间接绘制多分辨率 SDF 配合 compute marching cubes + TransvoxelComputeInstanceCulling 配合间接绘制
WebGL 2Geometry clipmap 配合 CPU 侧环更新2-3 个 LOD 等级的预生成网格,缓存CPU 视锥剔除,InstancedMesh

两条路径都在 vertex shader 中使用 geomorphing 做无弹出过渡。两条都对远处植被使用广告板假体。WebGPU 路径更快(地形预算 3.5ms),但 WebGL 2 路径可行(6.5ms)。

流送

渐进加载:先地形几何(<100ms)、其次纹理(<300ms)、再植被(<1s)、最后体积数据(<3s)。基于玩家速度预取。内存预算:地形总共 256 MB。

编辑

高度图笔刷做表面雕塑(隆起、降低、平滑、侵蚀)。SDF 原始体做体积编辑(开凿洞穴、添加拱门)。两者本地都是瞬时的,100-300ms 同步到服务器,通过差量更新广播给其他玩家。

按什么顺序构建

第 1-2 个月:带 geometry clipmap 的高度图地形。 仅 WebGL 2。从 CDN 流送。程序化坡度/海拔材质。这能让地形在每个浏览器里显示。生成用噪声 + 解析侵蚀(Terrain Diffusion 可以等)。

第 3-4 个月:植被与大气。 来自密度图的 GPU 实例化草和树。带昼夜循环的程序化天空。大气雾。级联阴影贴图。世界开始有地方感。

第 5-6 个月:创作者编辑。 高度图笔刷工具。多人地形编辑的差量同步。并发编辑的空间锁定。这时创作者开始塑造世界。

第 7-9 个月:体积地形与 WebGPU 路径。 用于洞穴和悬挑的 SDF 叠加。WebGPU compute 中的 marching cubes。LOD 边界的 Transvoxel。SDF 雕塑工具。这解锁完整创作工具包。

第 10-12 个月:神经生成和打磨。 基础高度图的 Terrain Diffusion 或 MESA。纹理的 TerraFusion/Geodiffussr。微细节的 phasor noise。Hex-tiling 抗重复。虚拟纹理。拉普拉斯混合。地形达到生产质量。

这种顺序意味着 2 个月后有可玩的东西,4 个月后有美观的,6 个月后可编辑,12 个月后是最新水平。

文章其余部分是每个决策背后的研究。

超越高度图的地形表示

Signed Distance Field(SDF)

有符号距离场在 3D 空间的每一点存储到最近表面的距离。正值在外,负值在内,零交叉就是表面本身。SDF 表示任意 3D 形状,包括洞穴、拱门和漂浮几何。

要把 SDF 渲染为网格,你运行 marching cubes(或变体)将零交叉提取为三角形。网格分辨率取决于网格分辨率:256x256x256 SDF 网格在 1m 分辨率下产生约一个 chunk 的地形。

浏览器实现: WebGPU marching cubes 完全通过 compute shader 在 GPU 上运行。Will Usher 的 webgpu-marching-cubes 实现在浏览器中实时处理 256^3 网格,达到原生速度性能。算法是尴尬地并行(每个单元独立处理),是 GPU compute 的理想用例。

wgsl
@compute @workgroup_size(4, 4, 4)
fn marchingCubes(@builtin(global_invocation_id) id: vec3<u32>) {
    let sdfValues = sampleSDF(id);
    let caseIndex = classifyCell(sdfValues);
    if (caseIndex == 0u || caseIndex == 255u) { return; }
    let triangles = lookupTriangulation(caseIndex);
    let vertices = interpolateEdges(sdfValues, triangles);
    appendToMeshBuffer(vertices);
}

存储成本: 256^3 SDF 在 8 位量化精度下未压缩为 16 MB。但大部分体积是空的(远离表面)。游程编码或稀疏八叉树存储通常把这个减到 100-500 KB 每 chunk,与高度图地形相当。

编辑: SDF 地形天然可编辑。添加材质是对距离场的 min() 操作。移除材质(挖掘)是对取反形状的 max()。形状之间的平滑混合使用 smoothMin()。这些操作在 compute shader 中以交互速率运行。

Dual Contouring

Marching cubes 把顶点放在网格边上,产生平滑表面,但丢失尖锐特征(崖边、岩石角点)。Dual contouring 在每个单元放置一个顶点,位置最能代表该单元内的表面,保留尖锐边缘和角点。

算法需要每个网格点的距离场值和表面法线(SDF 梯度)。它在每个单元求解一个小的最小二乘问题以找最优顶点位置。结果是同时捕捉平滑地形和尖锐岩石特征的网格。

Neural Dual Contouring(Chen 等,2022,arXiv:2202.01999)用预测最优顶点位置和边交叉的神经网络替换最小二乘求解器。它在复杂自然岩石形态上的表面重建精度和特征保留更佳。

Transvoxel 算法

体积地形最难的问题不是生成网格,而是 LOD 过渡。当高分辨率 chunk 紧挨低分辨率 chunk 时,网格在边界处对不上,产生可见裂缝。

由 Eric Lengyel 设计的 Transvoxel 算法(transvoxel.org)在分辨率间边界插入特殊过渡单元来解决。这些单元用额外三角形精确匹配两侧来桥接分辨率差异。算法将复杂边界问题归约到 73 个等价类(对比暴力法约 120 万种情况)。

Transvoxel 专为体素数据动态变化的实时应用(创作者编辑、侵蚀、挖矿)设计。它免专利,已用于已发布游戏(Space Engineers、Astroneer)。对于带可编辑体积地形的浏览器世界,Transvoxel 就是 LOD 方案。

混合:高度图基础 + 体积叠加

浏览器开放世界的实用方法是分层系统:

第 1 层:高度图地形覆盖整个世界。这是丘陵、河谷和山脉的便宜、紧凑表示。它以每 chunk 的小高度图补丁流送(每个 2-4 KB)。渲染使用具有恒定 GPU 成本的 geometry clipmap。

第 2 层:体积叠加仅在需要复杂几何的 chunk 中存在。洞穴、崖面、拱门、创作者雕刻的隧道和地下空间存储为稀疏 SDF 体。只有带体积数据的 chunk 才承担 SDF 存储和 marching cubes 成本。

第 3 层:创作者修改作为基础层之上的 SDF 编辑存储。挖隧道的创作者存储该隧道的 SDF 形状。渲染系统把高度图表面与体积减/加组合,产生最终网格。

这种混合对平地几乎无成本(只有高度图),仅在复杂处扩展。在典型世界中,也许 5-10% 的 chunk 需要体积数据。

物理正确的地形生成

噪声产生随机地形。物理产生真实地形。差异可见:噪声地形没有结构(到处随机起伏),而物理地形有侵蚀和构造产生的河网、山脊线、冲积扇和崖带。

水力侵蚀:基础

Sebastian Lague 的水力侵蚀实现。模拟雨滴顺坡流下,按速度和坡度侵蚀材质,速度下降时沉积——把平的噪声变成河谷、山脊线和冲积扇。

水向下流,捡起沉积物,在减速时沉积。这一过程在虚拟百万年里模拟,能把无特征的噪声变成有可识别地质特征的地形。

基于粒子的方法在高度图上投放模拟雨滴。每滴顺坡流(沿梯度),按速度和坡度侵蚀材质,把沉积物作为溶解负荷携带,在速度下降或容量超出时沉积。20-50 万颗粒子后,地形发展出:

  • 河谷沿最大水流路径
  • 山脊线分隔流域
  • 冲积扇在陡谷开向平原处
  • 山地中的 V 形河谷,冰川化地形中的 U 形

GPU 实现: 粒子模拟可并行。每颗粒子独立(近似忽略颗粒间交互,对侵蚀没问题)。WebGPU compute shader 在 60fps 下每帧处理 1 万颗粒子,约 3 秒实时完成 20 万颗。

Sebastian Lague 的开源实现(GitHub)是标准起点。它在 C# 中单线程运行,几秒内处理 1024x1024 高度图。GPU 版本快 50-100 倍。

热侵蚀

水不是唯一侵蚀力。温度变化使岩石裂开和崩塌(热风化)。当两个地形点之间的坡度超过材料的安息角时,材料从高点落到低点。这产生:

  • 崖底的碎石坡(落石堆)
  • 随时间软化的山脊线
  • 材质相关的剖面(硬岩保持陡坡,软土崩塌为缓角)

热侵蚀比水力侵蚀简单。它是局部操作:对每个 cell,比较与邻居的高度差。若坡度超阈值,材料下移。每次迭代作为单 compute shader pass 运行,50-100 次迭代收敛。

水力和热侵蚀组合产生的地形看起来比单独使用都更自然。水开凿河谷,热侵蚀软化它们之间的山脊并用碎屑填充谷底。

Stream Power Law:解析侵蚀

最近研究提供了基于粒子模拟的替代方案。stream power law(关于侵蚀速率与流域面积和坡度的地貌学方程)可解析求解,而不是迭代模拟。

Cordonnier 等(2024,HAL)把解析 stream power law 与滑坡和山坡扩散过程组合。结果是物理基础但作为数学函数运行的地形生成,而不是时间模拟。你输入基于噪声的高度图和参数(降雨率、岩石硬度、构造抬升率),毫秒内得到侵蚀地形。

这种解析方法对浏览器世界理想,因为它在服务端地形生成时运行一次,不是迭代地。参数对创作者可调(「让这个区域更山」调高抬升率;「让它更湿」增加降雨并加深河谷)。

Arenite:多物理侵蚀(SIGGRAPH 2025)

Arenite 模拟应力、风蚀、河流侵蚀和颗粒沉积,从分层岩石生成拱门、土柱和方山。服务端生成产生 SDF 体,直接喂给 marching cubes 流水线。

Arenite(项目页)是基于物理的砂岩模拟器,从简单初始条件生成拱门、壁龛、土柱和方山。用户绘制可侵蚀性图(软岩 vs 硬岩层)和植被,然后系统模拟:

  • 通过岩柱的应力分布
  • 优先移除暴露软材料的风蚀
  • 来自水流的河流侵蚀
  • 形成新形态的颗粒沉积

GPU 实现在桌面 GPU 上对复杂形态在 5 分钟内运行。虽然这对实时浏览器使用太慢,但对服务端生成足够快。创作者可定义带软/硬岩层的崖面,几分钟内得到真实拱门形态。

输出是 3D 体素场,直接适合我们的 SDF/marching cubes 流水线。

跨表示的灵活侵蚀

来自 IRIT-STORM 的 2024 年论文(「Flexible Terrain Erosion」,Springer)解决了一个实际问题:大多数侵蚀方法只对高度场工作。如果你的地形用体素、SDF 或分层材质,你需要为每种单独的侵蚀代码。

灵活侵蚀方法把侵蚀分解为两个独立过程:地形改变(从表面移除材料)和材料运输(用受基本物理控制的粒子移动沉积)。每颗粒子有可配置的大小、密度、弹性和沉积容量。可选向量场为真实流体动力学控制粒子运动。

由于粒子通过统一材料改变接口与地形交互,同一模拟在高度场、体素网格、隐式表面和分层材质栈上工作。对于我们的混合地形(高度图基础 + SDF 叠加),这意味着一个侵蚀系统处理两种表示。粒子模拟在 GPU 上并行运行。

河网和流域

侵蚀开凿河流,但生成令人信服的河网需要的不只是让水顺坡流。两种方法产生更好结果:

排水优先生成(Amit Patel,Red Blob Games,项目)在分配高程之前构建河网。从图(Voronoi 或三角网格)开始。把边分类为山脊(无流)、入口(水流入)或出口(水流出)。这创建真实的排水层级,河流从小支流汇聚到主水道,遵循不同河流类型的 Rosgen 分类系统(平地的辫状河道、山地的窄峡谷)。

流量累积追踪有多少水经过每个地形 cell。均匀地投放模拟雨,让它顺坡流,统计每个 cell 的访问数。累积量高的 cell 是河道。中等累积的是季节性溪流。累积图还驱动侵蚀强度(更多水 = 更多侵蚀)和植被分布(河岸更湿,支持不同植物物种)。

对于创作者世界,河网在地形创建时服务端生成,作为每 chunk 的 2D 流向图加水量累积图存储。浏览器客户端使用这些图渲染水面(河道中正确高度的平面)并驱动植被分布(水边更繁茂)。

海岸和海岸线生成

海岸线是地形与水的交界,有标准侵蚀不会产生的特征:海崖、海滩沉积、潮间带、海蚀柱和海蚀平台。

NEWTS1.0(2024,MIT)用两种侵蚀机制建模岩石海岸线演化:均匀后退(恒定侵蚀率)和波驱动侵蚀(侵蚀率作为风区距离和入射波角的函数)。模型在数千模拟年上运行,产生与真实海岸地貌匹配的海岬、海湾、海蚀柱和拱门。

对于浏览器世界,海岸特征在世界创建时预生成。参数(主导波向、沿海岸的岩石硬度变化)让创作者控制其海岸线特征。「挪威峡湾」设置产生陡壁的入海口。「热带环礁」设置产生带潟湖的低洼沙滩。

洞穴和地下生成

洞穴需要完全体积地形(SDF 或体素),因为高度图无法表示封闭空间。生成方法:

3D 噪声阈值是最简单的方法。在每个体素采样 3D Perlin 或单纯形噪声。低于阈值的值为固体,高于为空。调整阈值和噪声参数控制隧道直径、连通性和腔室大小。这产生有机的、虫状洞穴系统,类似 Minecraft。

PLUME(Procedural Layer Underground Modeling Engine)(2024,arXiv:2508.20926)用分层程序化规则生成真实的洞穴和熔岩管环境。最初为太空探索研究构建(模拟火星熔岩管),它产生带钟乳石、柱和腔室系统的地质合理地下结构。

L-system 隧道配合 metaball 雕刻用 L-system 语法在地形中生长分支隧道路径,然后用 metaball 隐式表面雕刻实际隧道几何。Metaball 产生平滑、圆润的洞壁。不同参数的多次 pass 创建主通道、侧腔室和窄连通隧道。

对创作者世界,洞穴生成接入 SDF 叠加系统。基础地形是高度图(无洞穴)。当 chunk 需要洞穴(来自程序化生成或创作者设计),生成一个从基础地形减去洞穴几何的 SDF 体。marching cubes 流水线渲染组合表面。

作为物理过程的植被

游戏中的植被通常按规则程序化放置,比如「2000m 以下草、1500m 以下树、3000m 以上雪」。这很快但产生均匀、不真实的分布。

基于物理的植被模拟把每棵植物建模为竞争资源(光、水、土壤养分)。模拟:

  1. 种子散布在地形上
  2. 每棵植物根据可用资源生长(水来自水力侵蚀模拟,阳光取决于坡度和朝向,土深取决于侵蚀历史)
  3. 植物竞争:树遮蔽草,密集冠层阻止新幼苗
  4. 在模拟时间里,群落自然出现:水的河谷里是森林,多风山脊是稀疏植被,水积处是湿地

Deussen 等的生态系统模拟(论文)生成与真实生态模式匹配的森林分布。模拟在 2D 网格上运行(每个地形 chunk 一个 cell),产生渲染系统用于 GPU 实例化植被放置的密度图和物种分配。

对浏览器世界,植被模拟在世界生成时服务端运行一次。输出是每 chunk 的一组密度图:树密度、草密度、花密度、岩石碎屑密度。浏览器客户端使用这些图配合 GPU 实例化在运行时散布植被。

基于扩散的地形合成

这是领域发展最快的方向。扩散模型(与 Stable Diffusion 同样的技术)被应用于地形生成,结果比基于噪声的方法真实得多。

Terrain Diffusion:Perlin 噪声的继任者

Terrain Diffusion 在 Minecraft 中实时流送无限的种子一致地形。它在真实高程数据上训练,产生噪声函数无法匹及的地质结构。

Terrain Diffusion(Goslin,2025,arXiv:2512.08309项目页)是自 1985 年 Perlin 噪声以来程序化地形生成最重要的进步。

关键创新是 InfiniteDiffusion,一种把扩散采样重新表述为无界域的算法。传统扩散模型生成固定大小的输出(例如 512x512 高度图)。InfiniteDiffusion 生成无限范围的地形,具有:

  • 种子一致性: 同一种子总是产生相同地形,像 Perlin 噪声
  • 常数时间随机访问: 你可以查询任意点的高度,无需先生成邻近区域
  • 无边界伪影: 无限生成,无可见接缝或重复

系统使用扩散模型的分层栈。顶层捕捉行星级特征(大陆、山脉)。每个后续层添加更细的细节(单独的山峰、河谷、小尺度起伏)。紧凑的拉普拉斯编码在从海平面到喜马拉雅山峰的巨大动态范围内稳定输出。

性能: 在消费级 GPU 上比基线扩散快 9 倍,带少步骤一致性蒸馏以交互式生成速度。项目包括 Minecraft 集成,演示实时地形合成。

为什么这对我们重要: Terrain Diffusion 产生在真实高程数据(地球的实际地形)上训练的景观。输出来自训练数据,具有河网、山脉、海岸特征和高原结构,不是从手调噪声参数。创作者可以说「生成像苏格兰高地的地形」,扩散模型会产生带正确地质特征的东西。

模型在世界生成时服务端运行。输出是标准高度图,像其他地形数据一样流送到浏览器。生成方法对客户端不可见。

TerraFusion:联合几何与纹理

TerraFusion 使用潜变量扩散从草图联合生成地形高度图和匹配的表面纹理
TerraFusion 从手绘草图同时生成高度图和纹理。几何与材质的相关性已内置——河床出来是沙、崖面是岩石、平地是草——不需手工 splat 绘制。

TerraFusion(2025,arXiv:2505.04050)更进一步,联合生成高度图和地形纹理。关键洞见:地形几何和表面外观相关(河床是沙、崖面是岩石、平地是草)。分别生成会产生不匹配。

TerraFusion 使用带高度图和纹理独立 VAE 的潜变量扩散模型,训练以建模它们的联合分布。系统支持:

  • 无条件生成: 带匹配纹理的随机可信地形
  • 草图条件生成: 创作者画粗略地图(河谷在这、山脊在那、崖沿这边),模型生成与草图匹配的详细几何和纹理

对创作者世界,这很强大。创作者画其地块的总体布局,系统填充地质合理的地形和合适表面材质。无需高度图绘制、纹理 splat 或手动材质分配。

MESA:文本到地形

MESA 从文本提示生成卫星风格地形图像和高程图,在 Copernicus 全球数据上训练
MESA 从文本提示输出配对的卫星图像和 DEM。在 Copernicus 全球数据集上训练,它理解每个尺度和气候区的真实地形——峡湾、草原、农田、阿尔卑斯山脊。

MESA(2025,arXiv:2504.07210,CVPR 2025 Workshop)从文本描述生成地形。它在 Copernicus 项目的全球遥感数据上训练,所以接触到每种地球景观。

像「带陡峭花岗岩壁通向岩石海岸的峡湾」这样的提示产生带合适地质结构的高度图。「带缓坡和宽阔河谷的连绵农田」产生完全不同的东西。

MESA 引入了 Major TOM Core-DEM 扩展数据集,全球配对卫星图像与数字高程模型。这种训练数据让模型理解真实地形在每个尺度和每个气候区的样子。

Geodiffussr:文本引导的地形纹理化

Geodiffussr 从文本描述生成地形纹理,同时尊重高程数据——山峰上的雪、海岸的沙、坡上的森林
Geodiffussr 接受一个高度图和一个文本提示,生成尊重高程的表面纹理。雪只出现在合理海拔以上;植被随高度变稀;水位于洼地。几何不变。

Geodiffussr(2025,arXiv:2511.23029)接受现有高度图,并由文本描述引导生成纹理,同时尊重高程数据。「秋季森林」在中等坡度产生橙金色叶子、在陡面产生裸岩。「热带海岸」在低地产生棕榈植被、在海平面产生珊瑚沙。

系统使用多尺度内容聚合确保纹理分配尊重高程:雪只在物理合理的海拔以上出现,水特征位于洼地,植被随海拔变稀。

对创作者世界,这意味着地形纹理可从文本提示重新生成,无需改变几何。创作者雕塑想要的地形,然后描述氛围(「黑暗火山荒原」或「茂密温带森林」),系统生成合适的表面材质。

浏览器地形的动态 LOD

在浏览器中全分辨率渲染大型地形是不可能的。4 km x 4 km 世界在 1m 分辨率下仅地形就有 1600 万顶点。动态 LOD 把它减到常量、可管理的顶点数,无论世界大小。

Geometry Clipmaps

SIGGRAPH 2004 上 geometry clipmap 的原始介绍。同心环以分辨率减半的方式让顶点数保持常量,与世界大小无关——至今仍是大多数浏览器地形 LOD 的基础。

Geometry clipmap(Losasso 与 Hoppe,SIGGRAPH 2004,论文)仍是高度图地形 LOD 的黄金标准。思路:把地形渲染为围绕相机的一组同心方环。每环面积是前一环的两倍,但分辨率是一半。

靠近相机(最内环):全分辨率,1m 网格间距。 向外一环:2m 间距,覆盖 4 倍面积。 下一环:4m 间距,覆盖 16 倍面积。 依此类推 6-8 层,直到最外环覆盖整个可见距离。

总顶点数是常量:大约 N^2 * 等级数,N 是环宽(顶点数)。N=256 和 8 层时,约 50 万顶点。无论世界 1 km 或 100 km,渲染相同。

浏览器实现: Geometry clipmap 在 WebGL 2 中工作,因为只需标准顶点缓冲更新(无 compute shader)。随着相机移动,CPU 通过在合适分辨率采样地形更新每环的高度图数据。顶点着色器从纹理读高度值并位移平面网格。

变形: LOD 等级间的过渡若处理不当会产生可见「弹出」。Geomorphing(下面有专门章节)在顶点着色器中跨过渡区混合等级间的顶点位置,产生平滑、无弹出过渡,零额外绘制成本。

CDLOD:四叉树自适应 Clipmap

CDLOD(Strugar,2014,论文)通过用四叉树替代固定同心环改进 geometry clipmap。四叉树适应地形:平地用粗节点,细节高的区域(崖、山脊)得到更细分。

这对创作者世界重要,因为不同 chunk 有不同复杂度。平坦草地需要最小分辨率。带崖和洞的山区需要最大细节。CDLOD 把分辨率分配到重要的地方。

CPU 侧的四叉树遍历轻量(几百节点),确定要在哪个分辨率绘制哪些地形 patch。GPU 把每个 patch 渲染为带每 patch LOD uniform 的实例化网格。

Concurrent Binary Trees:行星级细分

用于行星级地形的 CBT 自适应细分:三角形在相机附近细分、在远处合并,完全在 GPU 上。在主机硬件上耗时不到 0.2ms。

Concurrent Binary Trees(CBT)是用于自适应地形细分的 GPU 友好数据结构,由 Benyoub 和 Dupuy 提出(Intel,HPG 2024,论文GitHub)。

核心思想:把地形表示为二叉树,每个节点是一个三角形。自适应细分分裂靠近相机的三角形,合并远的。二叉树完全位于 GPU 内存中作为 1D 数组(二叉堆),细分/合并操作作为 compute shader 运行。

2024 年论文把 CBT 从方形高度图域扩展到任意多边形网格。这意味着你可以细分球体(用于行星渲染)或任意基础网格(用于带非矩形边界的游戏世界)。关键改进:使用 CBT 作为内存池管理而不是隐式编码,允许更高的细分等级。

性能:在主机级硬件上 0.2ms 内完成行星级地形细分。算法随处理器数线性扩展。对 WebGPU,这提供在浏览器中渲染行星级地形的路径,不过实现复杂度高。

使用 WebGPU 的 GPU 驱动 LOD

WebGPU 启用了完全 GPU 驱动的地形流水线,消除了 CPU 在 LOD 决策中的参与:

  1. Compute pass 1:视锥和遮挡剔除。 Compute shader 把每个地形 patch 的边界盒与视锥和遮挡缓冲(来自上一帧的下采样深度缓冲)测试。不可见的 patch 完全丢弃。

  2. Compute pass 2:LOD 选择。 对可见 patch,计算屏幕空间大小并选择合适 LOD 等级。把 LOD 等级和 patch ID 写入间接绘制缓冲。

  3. Compute pass 3:网格生成(用于体积地形)。 对带 SDF 数据的 chunk,在选定 LOD 分辨率运行 marching cubes 生成网格。

  4. 间接绘制。 单个 drawIndexedIndirect() 调用渲染所有地形 patch。GPU 决定一切:画什么、在什么分辨率、什么顺序。

这条流水线的 CPU 成本是常量(派发 compute shader 和间接绘制调用),无论世界大小或复杂度。GPU 处理所有每 patch 决策。

wgsl
@compute @workgroup_size(64)
fn lodSelection(@builtin(global_invocation_id) id: vec3<u32>) {
    let patchIdx = id.x;
    let bounds = patchBounds[patchIdx];

    if (!frustumTest(bounds, viewProjection)) { return; }
    if (occlusionTest(bounds, depthPyramid) == OCCLUDED) { return; }

    let screenSize = projectedSize(bounds, viewProjection, screenDimensions);
    let lod = clamp(u32(log2(maxScreenSize / screenSize)), 0u, MAX_LOD);

    let drawIdx = atomicAdd(&drawCount, 1u);
    drawArgs[drawIdx] = DrawArgs(patchIdx, lod, indexCount[lod], indexOffset[lod]);
}

Geomorphing:无弹出的 LOD 过渡

地形 LOD 中最大的视觉伪影是弹出:当 patch 切换 LOD 等级时顶点突然跳到新位置。Geomorphing 通过在过渡区平滑插值等级间的顶点位置来消除。

实现完全在顶点着色器中。每个顶点存储其当前 LOD 位置和下一更粗 LOD 位置。当相机距离跨过过渡阈值时,一个 morph 因子在两者间混合:

glsl
float morphFactor = smoothstep(lodNear, lodFar, distanceToCamera);
float morphedHeight = mix(fineLodHeight, coarseLodHeight, morphFactor);
gl_Position = viewProjection * vec4(worldPos.x, morphedHeight, worldPos.z, 1.0);

Hoppe 的 geometry clipmap 论文(GPU Gems 2,第 2 章)描述了 clipmap 环的完整实现。morph 区是每环的外侧 20%。在该区内,顶点平滑收敛到下一环的分辨率。视觉效果:地形几何在细节等级间「融化」,而不是跳变。在典型相机速度下,过渡不可见。

图像空间混合(Scherzer 等,论文)是一种替代方案,在屏幕空间混合两个 LOD 等级的渲染图像。这处理更极端的 LOD 差异(例如网格到广告板过渡),但过渡区需要额外渲染 pass。

GPU 驱动的植被剔除

植被(树、草、岩石)通常是开放世界中绘制调用的最大来源。朴素方法每帧绘制每个植被实例。GPU 驱动剔除(现在通过 WebGPU 在 Three.js 中可用)在不可见实例到达光栅化器之前消除它们。

Three.js 的 ComputeInstanceCulling文档)为实例化网格提供视锥和 LOD 剔除,对大实例数有 10-100x 性能提升。流水线:

  1. Compute shader 读所有实例边界球
  2. 把每个对相机视锥测试(6 平面测试)
  3. 应用基于距离的 LOD:阈值外的实例切换到低细节或完全剔除
  4. 幸存实例压紧到缓冲,通过 drawIndirect 绘制

CPU 不做每实例工作。初始设置后,每个植被类型的成本是一次 compute 派发加一次间接绘制,无论实例数。

对于更密的植被,Three.js 的 IndirectBatchedMesh文档)把多种几何类型(树、灌木、岩石)打包到一个缓冲,用 multi-draw indirect 绘制。一次绘制调用渲染 chunk 中的所有植被。

与我们植被系统的基于密度图的散布组合,意味着:密度图在 compute shader 中生成 5 万个草叶位置,剔除 pass 消除 70% 屏外或太远的,一次间接绘制调用渲染剩余 1.5 万叶。CPU 总成本:可忽略。

体积地形的 LOD

体积地形(SDF + marching cubes)需要自己的 LOD 系统,因为网格是生成的,不是预创作的。方法:

多分辨率 SDF 存储。 把 SDF 存储在类似 mipmap 的层级中。Level 0 全分辨率(1m 体素)。Level 1 是 2m 体素(数据少 8 倍)。Level 2 是 4m 体素。每级 SDF 通过取最小绝对距离下采样。

LOD 选择的 marching cubes。 在匹配所需 LOD 的 SDF 等级上运行 marching cubes。近 chunk 用 Level 0。远 chunk 用 Level 2 或 3。Transvoxel 算法处理不同等级间的边界。

缓存。 生成的网格被缓存,直到 SDF 改变(创作者编辑)或 LOD 等级改变(相机显著移动)。对静态地形,网格生成一次后复用。

地形流送架构

Chunk 数据格式

每个地形 chunk(64x64 米)作为紧凑二进制包流送:

ChunkPacket {
  header: {
    chunkX: i16, chunkZ: i16,
    version: u32,
    flags: u8  // hasHeightmap | hasVolumetric | hasVegetation
  }
  heightmap: {
    resolution: u8,      // 全为 65x65,半为 33x33,四分之一为 17x17
    quantizedHeights: u16[resolution * resolution],  // delta 编码,zlib 压缩
    splatMap: u8[4 * resolution * resolution]         // RGBA 混合权重,LZ4 压缩
  }
  volumetric?: {         // 仅当 flags.hasVolumetric 时出现
    sdfResolution: u8,   // 通常 32 或 64
    sparseOctree: bytes  // 游程编码的稀疏 SDF
  }
  vegetation?: {         // 仅当 flags.hasVegetation 时出现
    treeDensityMap: u8[16 * 16],    // 4m 分辨率密度网格
    grassDensityMap: u8[32 * 32],   // 2m 分辨率密度网格
    rockDensityMap: u8[16 * 16]
  }
  creatorObjects: {
    count: u16,
    objects: PlacedObject[]   // assetId + 变换 + 属性,每个约 40 字节
  }
}

典型大小:

  • 仅高度图 chunk(平地):压缩 2-4 KB
  • 高度图 + 植被:4-8 KB
  • 高度图 + 体积 + 植被(复杂 chunk):20-100 KB
  • 5x5 全细节邻域:合计 50-500 KB

渐进 chunk 加载

chunk 按距离、移动方向和数据类型的优先级顺序加载:

优先级 1(立即,<100ms): 玩家即将进入的 chunk 的高度图几何。地形表面先出现。即使最低分辨率(每 chunk 17x17),地面就在那里。

优先级 2(快,<300ms): Splat map 和地形纹理。地面有颜色。

优先级 3(流送中,<1s): 全分辨率高度图升级。植被密度图。GPU 实例化生成树和草。

优先级 4(后台,<3s): 带洞穴/悬挑的 chunk 的体积 SDF 数据。Marching cubes 在 Web Worker 中生成网格,传输缓冲到主线程。

优先级 5(延迟,<10s): 创作者放置的物体。结构的高分辨率纹理。细节物体如花、小石、碎屑。

预测预取

不要等到玩家进入 chunk 才加载。基于速度预测他们去哪并提前加载:

  • 步行速度(5 km/h): 预取前方 2 chunk(128m)。在典型宽带延迟下,这是 200-400ms 提前量。
  • 跑/骑(15 km/h): 预取前方 4 chunk。加载环随速度方向偏移。
  • 飞行/快速旅行: 过渡期暂停渲染。以最高优先级流送目的地 chunk。当存在足够数据出首帧时恢复渲染。

预取系统跟踪哪些 chunk 在缓存中、哪些在飞行中(已请求但未到达)、哪些需要。优先队列按紧迫度排序待处理请求。取消玩家已经走远的 chunk 的请求。

内存预算和驱逐

浏览器标签在桌面上得到 2-4 GB。地形系统需要在其一小部分内(其余用于渲染、物理、网络和 JS 堆)。

目标预算:所有地形数据 256 MB。

按典型 chunk 大小:

  • 全细节缓存 chunk:约 100 个(10x10 邻域),每个 5-100 KB = 原始数据 5-10 MB
  • GPU 地形几何:约 50 MB(可见地形的顶点缓冲、索引缓冲)
  • 地形纹理:约 100 MB(KTX2 压缩,atlas 打包)
  • 植被实例缓冲:约 50 MB(GPU 实例化的位置、旋转、缩放)
  • SDF 体和缓存的 marching cubes 网格:约 50 MB

可见范围外的 chunk 先从 GPU 内存驱逐(纹理、顶点缓冲),然后从 CPU 缓存。原始高度图数据是最后被驱逐的,因为保留它最便宜,玩家转身时它最重要。

群落过渡和抗瓦片

平滑的群落边界

真实景观在群落间没有硬边。森林不在一条线停止然后变沙漠。有一个渐变:密林稀疏成散乱树木,然后是灌木地、然后是稀疏沙漠植被。处理好这点让世界感觉连续而不是瓦片。

AutoBiomes(Kötter 等,论文)把程序化地形生成与简化气候模拟组合。温度、湿度和海拔决定每点的群落类型。群落之间,材质权重和植被密度在过渡区上插值(通常 50-100 米宽)。过渡宽度随群落对而变:森林到草原宽且渐变,崖到水窄而突变。

对创作者世界,群落分配在粗网格上运行(每 16x16 米一个群落样本)。地形着色器读当前片元及其邻居的群落值,在过渡区插值材质权重,并相应混合纹理。植被散布使用相同插值密度值,所以树密度在林缘渐变。

创作者控制:让创作者在其地块上绘制群落覆盖。系统从地形属性生成默认群落,但创作者可覆盖。在低地绘制「沼泽」,材质转向浑水、苔藓和枯树。群落绘制图是每 chunk 的 16x16 群落 ID 网格(256 字节),覆盖程序化分配。

Hex-Tiling:消除纹理重复

地形渲染最常见的视觉伪影是纹理重复。1m 草纹理平铺在 100m 草甸上产生可见网格图案。两种技术修复:

Hex-tiling(Mikkelsen,Demo)把方形平铺网格替换为六边形。每个六边形 tile 在随机偏移和旋转处采样纹理。六边形边界被混合以隐藏接缝。结果是看起来均匀随机而不是瓦片化的表面。成本:每片元约 3 次额外纹理采样。该技术在生产游戏中广泛使用,在任何片元着色器中运行。

随机纹理过滤(Pharr 等,NVIDIA,2024,论文)在着色之后而不是之前应用过滤,使用随机采样。随机采样的误差很小,由时空去噪很好地处理。这产生更准确的过滤结果,且适用于压缩/稀疏纹理。对地形,它消除瓦片伪影和 hex-tiling 有时在过渡处引入的过滤伪影。

对浏览器世界,hex-tiling 是实际选择(在任何着色器中工作)。随机过滤需要更多基础设施,但如果有时间去噪可用(在带 TAA 的 WebGPU 路径中会有)则产生更好结果。

地形材质系统

Triplanar 映射

标准 UV 映射纹理在陡坡上拉伸严重,因为 UV 坐标被压缩。Triplanar 映射沿三个轴(X、Y、Z)投影纹理,并基于表面法线混合:

glsl
vec3 blending = abs(normal);
blending = normalize(max(blending, 0.00001));
blending /= (blending.x + blending.y + blending.z);

vec4 xaxis = texture(material, worldPos.yz * scale);
vec4 yaxis = texture(material, worldPos.xz * scale);
vec4 zaxis = texture(material, worldPos.xy * scale);

vec4 color = xaxis * blending.x + yaxis * blending.y + zaxis * blending.z;

崖面得到 X 或 Z 投影(无拉伸)。平地得到 Y 投影。混合平滑且自动。无需 UV 展开。

Babylon.js 有内置的 TriPlanar Material。Three.js 需要自定义着色器,但实现约 30 行 GLSL。

对 PBR 地形,对所有通道应用 triplanar 映射:反射率、法线、粗糙度和环境光遮蔽。相同混合权重应用于每个通道。

基于坡度和海拔的材质分配

不是手绘 splat map,而是基于地形属性程序化分配材质:

glsl
float slope = acos(dot(normal, vec3(0, 1, 0)));
float altitude = worldPos.y;

float grassWeight = smoothstep(0.3, 0.0, slope) * smoothstep(2000.0, 1500.0, altitude);
float rockWeight = smoothstep(0.2, 0.5, slope);
float snowWeight = smoothstep(2500.0, 3000.0, altitude) * smoothstep(0.4, 0.1, slope);
float sandWeight = smoothstep(5.0, 0.0, altitude) * smoothstep(0.15, 0.0, slope);

低海拔平地得到草。陡坡得到岩石。高海拔得到雪(但只在平到能积雪的表面)。海平面附近得到沙。过渡平滑且物理动机化。

对创作者世界,把海拔阈值和混合区作为每 chunk 可绘制参数暴露。创作者可上下移动林线、扩展雪覆盖,或通过调整其地块的材质规则把草丘变成沙漠。

GPU 友好的拉普拉斯纹理混合

标准纹理混合(层间线性插值)产生可见接缝或苍白低对比度结果。拉普拉斯金字塔混合解决了这个问题,但传统上需要昂贵预计算。

Wronski(NVIDIA,2025,JCGT)提出一种 GPU 友好变体,在实时着色器中工作,无需预计算、无额外内存。该技术使用标准 mipmap 链作为拉普拉斯金字塔近似:在当前 mip 等级和更粗等级采样纹理,计算差值(拉普拉斯),混合每层的拉普拉斯贡献。

结果保留尖锐局部特征(单个草叶、岩石裂纹),同时在更大尺度平滑混合。代价是每片元几次额外纹理采样。对每像素混合 4+ 材质层的地形,这比线性混合产生明显更好结果,尤其在草、岩石和沙之间的过渡。

用于侵蚀细节的 Phasor 噪声

标准地形在近距离常看起来平,因为侵蚀模拟在高度图分辨率(1m 网格)上工作。真实地形在厘米尺度有细侵蚀图案(细沟、冲沟、风化裂纹)。

Grenier 等(2024,CGF)使用 phasor 噪声实时为地形添加微细节。Phasor 噪声通过定义喂给周期函数的随机相位场来合成结构化图案。应用到地形,它创建空间变化的侵蚀图案:

  • 跨尺度把窄细沟级联为更大冲沟
  • 自动对齐地形坡度(侵蚀图案沿坡向)
  • 实现最高 32x 放大(在 32x 高度图分辨率添加细节)
  • 完全在片元着色器中以交互帧率运行

对浏览器世界,phasor 噪声在地形着色器中作为细节层运行。高度图提供大尺度形状。Phasor 噪声在片元着色器中添加令人信服的微侵蚀,不增加几何复杂度。参数(图案频率、振幅、朝向)可按群落变化:裸岩上的深细沟、沙丘上的轻微波纹、干泥上的粗糙树皮般纹理。

地形的虚拟纹理

在大尺度上,地形纹理 atlas 变得臃肿。4 km x 4 km 世界以每厘米 1 texel 需要 40 万 x 40 万像素纹理。显然不可能。

虚拟纹理(也叫 megatexture,来自 id Software 的 Rage)通过把地形纹理视为分页结构来解决。完整纹理在概念上存在,但只有屏幕可见的瓦片加载到 GPU 内存。

流水线:

  1. 反馈 pass: 用一个着色器渲染地形,输出每像素需要哪个纹理瓦片(瓦片 ID 和 mip 等级)。把它读回 CPU(或用 compute shader 处理)。
  2. 瓦片加载: 从 CDN 加载请求的瓦片,或从 splat map 数据程序化生成。
  3. 间接纹理: 一张小纹理把虚拟瓦片坐标映射到纹理 atlas 中的物理瓦片坐标。
  4. 渲染 pass: 地形着色器查间接纹理找正确物理瓦片,然后从 atlas 采样材质纹理。

WebGPU 的 compute shader 可完全在 GPU 上处理反馈分析和页表管理。CPU 只管理瓦片 I/O。

结果:地形在任意分辨率下有独特纹理,无纹理内存爆炸。远离相机的瓦片在低分辨率加载。近处瓦片在高分辨率加载。总内存使用保持在固定预算内(通常 128-256 MB 纹理 atlas)。

动态地形效果

水洼和湿润

雨不只下落。它积累。在洼处形成水洼。在表面创造湿润感。在陡坡上流走。模拟这点让天气感觉与地形连接,而不只是视觉叠加。

基于着色器的方法不模拟流体动力学。它用地形高度图确定水积处:

glsl
float concavity = heightCenter * 4.0 - heightLeft - heightRight - heightUp - heightDown;
float puddleDepth = max(0.0, concavity * rainIntensity - evaporationRate * timeSinceRain);
float wetness = smoothstep(0.0, 0.02, puddleDepth);

vec3 wetColor = baseColor * 0.7;
float wetRoughness = baseRoughness * 0.3;
vec3 finalColor = mix(baseColor, wetColor, wetness);
float finalRoughness = mix(baseRoughness, wetRoughness, wetness);

凹陷区域(高度图的负拉普拉斯)积水。凹陷越深,水洼越大。湿表面变暗且反射性增强(粗糙度更低)。效果在雨停后随时间淡去。

对完整水洼反射,在水洼表面加平面反射 pass。或用更便宜且在 Three.js 和 Babylon.js 后处理栈中可用的屏幕空间反射(SSR)。

水洼表面的雨滴用反馈纹理中的简单 2D 波方程(Saurel,2026,博客)。每个雨滴产生向外传播并衰减的涟漪。波纹理调制水洼法线贴图,以 60fps 创造令人信服的涟漪图案。

脚印与地形形变

当玩家走在软地形上(沙、雪、泥)时,脚印增加物理存在感。技术:维护每 chunk 的小形变纹理(64x64 像素 = 4 KB),存储高度偏移。当角色踩到软地形时,将脚印形状盖到形变纹理。

地形顶点着色器读形变纹理并从高度减去偏移。地形片元着色器变暗脚印区域(压实土壤更暗)并增加粗糙度(扰动表面)。

脚印随时间淡去(雪填回、雨冲刷泥印)通过逐渐归零形变纹理。淡去率取决于天气:雨中快,干燥时慢。

对多人世界,脚印数据是短暂和本地的。每个客户端为可见玩家生成脚印。形变纹理不需跨客户端同步(每个人都看到他们自己版本的瞬态脚印)。这避免了广播每一步的网络成本。

程序化天空和昼夜循环

天空是任何开放世界中最大的可见表面。它为整个地形设定氛围。

Three.js 有一个 完整天空系统,包括程序化太阳/月亮、昼夜循环、云、星和镜头光晕。Three.js 内置的 Sky 例子(也有 WebGPU)实现 Preetham 解析天空模型。

对物理上更准确的结果,webgpu-sky-atmosphere 把 Hillaire 的大气模型实现为 WebGPU 后处理。它支持多重散射相函数,从第一原理产生正确的空气透视(远地形看起来更朦胧)、太阳/日落颜色和天空梯度。

TerrainView7 演示了 WebGPU 中带预计算大气散射的全尺度行星渲染,证明物理准确的大气渲染在浏览器中运行。

对创作者世界,天空参数(太阳位置、云覆盖、雾密度)从服务器世界时钟跨所有客户端同步。天空着色器在每个客户端本地运行,跨所有玩家产生一致光照。

地形光照:间接照明

直射阳光由阴影贴图处理。但地形在阴影中的颜色和亮度(环境/间接光)对视觉质量同样重要。纯黑阴影看起来不对。阴影应被天空颜色着色(晴天蓝色,阴天灰色)。

对浏览器世界,实用方法:

带可见性位掩码的屏幕空间间接光照(Jimenez 等,2023,论文)通过跟踪每像素 32 个方向可见性扇区,改进标准 SSAO。这不仅捕捉点被遮挡的程度,还捕捉遮挡的方向性。薄表面正确地让光从另一侧穿过。结果是反应附近几何而无需全局照明基础设施的间接照明。

成本与 SSAO 相当(1-2ms)。视觉提升显著:峡谷中的地形从峡谷壁捕捉反弹光。悬挑的下侧被地面反射照亮。该效果与天空着色器的大气散射结合,产生物理动机化的环境光照。

地形物理集成

Rapier 高度场碰撞体

Rapier 的 WASM 物理引擎为地形提供原生高度场碰撞体优化。创建地形碰撞体很简单:

typescript
const heights = new Float32Array(65 * 65);
// 用高度图数据填充...
const groundCollider = RAPIER.ColliderDesc.heightfield(
  64, 64, heights, new RAPIER.Vector3(64.0, 100.0, 64.0)
);
world.createCollider(groundCollider);

高度场碰撞体使用结构化网格进行高效粗筛查询。对高度场的光线投射是 O(log n),而三角网格是 O(n)。对 65x65 chunk,碰撞查询在微秒内解析。

对带体积地形的 chunk(SDF 叠加),从 marching cubes 输出生成三角网格并用 trimesh 碰撞体。这比高度场碰撞体昂贵,但处理任意几何。只为离玩家最近的 3-5 个 chunk 生成 trimesh 碰撞体。远 chunk 不需要物理。

性能: Rapier 的 65x65 chunk 高度场碰撞体为角色控制器查询每物理步增加约 0.1ms。5 个活动 chunk 带高度场碰撞体:0.5ms。体积 chunk 的一个 trimesh 碰撞体:0.2-0.5ms。地形物理总预算:1ms 以下,远低于整个世界 2-3ms 的物理预算。

地形感知角色控制器

角色控制器需要响应地形属性:

  • 坡度限制: 角色可走最高 45 度坡。更陡的坡导致滑动。这使用角色位置的地形法线(从高度图梯度便宜地计算)。
  • 表面材质响应: 走在岩石上产生不同的脚步声和移动速度,与沙或泥不同。地形的 splat map 提供任意点的表面材质。
  • 台阶攀登: 角色可踏上最高 0.5 米的凸缘。Rapier 的 KinematicCharacterController 用可配置台阶高度自动处理这点。

浏览器中的交互式地形编辑

对创作者世界,地形不只是生成的。它由玩家雕塑、修改和重塑。编辑工具需要响应(即时视觉反馈)和网络化(其他玩家几秒内看到变化)。

WebGPU SDF Editor

Reinder Nijhoff 的 WebGPU SDF Editor 演示了全功能 SDF 建模今天在浏览器中工作。编辑器支持:

  • 六种原始形状(球、盒、锥、圆柱、胶囊、环面),带位置、旋转和缩放
  • 布尔操作(并、差、交),带平滑混合和可配置混合半径
  • 分层场景图,带组和嵌套操作
  • 实时渲染,使用多 GPU compute shader 阶段、跨 16,384 个网格 cell 的基于八叉树的空间划分,以及通过 marching cubes 或 surface nets 的表面提取
  • 时间反走样和环境光遮蔽,通过阴影贴图

每个原始体作为 28 个浮点(112 字节)存储在单个 GPU 缓冲中。这种紧凑表示意味着复杂地形编辑(数十个 SDF 原始体定义洞口、拱门或雕刻崖面)不到 5 KB,瞬间同步给其他玩家。

对创作者世界,SDF 编辑工作流如下:

  1. 创作者选择雕塑工具(加球、减盒、平滑混合)
  2. 在世界中点击/拖动以放置和调整 SDF 原始体
  3. 客户端立即在修改的 SDF 上运行 marching cubes 更新本地网格(反馈 <16ms)
  4. SDF 编辑(原始体类型 + 变换 + 混合模式,约 100 字节)发送到服务器
  5. 服务器验证编辑(在创作者地块内、不与保护区相交)并广播给附近玩家
  6. 其他玩家的客户端应用 SDF 编辑并重新生成其本地网格

编辑对他人可见的总往返:取决于网络延迟 100-300ms。创作者立即看到自己的编辑,因为它在服务器确认前已本地应用。

基于笔刷的高度图编辑

对高度图层(不需体积特征的 90% 地形),更简单的编辑模型可行。创作者用笔刷绘制高度修改:

  • 隆起/降低: 在带衰减的半径内加或减高度
  • 平滑: 在半径内平均高度,移除尖锐特征
  • 压平: 把半径内所有高度设为目标值
  • 侵蚀笔刷: 在笔刷半径内本地应用几步水力侵蚀

高度图编辑是一个增量:覆盖在基础地形上的高度变化小补丁。增量补丁很小(32x32 网格的 16 位高度偏移 = 2 KB)作为单条消息同步给其他玩家。多个增量补丁在每 chunk 累积,并定期服务端合并到 chunk 的持久高度图。

协作编辑约束

当多个创作者同时编辑同一 chunk 时,系统需要规则:

  • 空间锁定: 任一时刻只有一个创作者可编辑给定 8x8 米子区域。创作者开始编辑笔画时获得锁,抬起笔刷时释放。锁在 10 秒不活动后超时。
  • 非重叠编辑: 如果两个创作者编辑同一 chunk 的不同部分,两个编辑都应用无冲突(修改不同高度图 cell 或 SDF 区域)。
  • 重叠编辑: 如果两个创作者编辑同一位置,服务器按到达顺序序列化编辑。两个客户端在协调后看到相同最终结果。

这比放置物体的完整 CRDT 方法简单,因为地形编辑是对连续场(高度、SDF 距离)的加性操作,而不是离散物体状态。

WebGPU 中的 Nanite 风格虚拟几何

虚幻引擎 5 的 Nanite 通过在构建时构建集群 DAG(有向无环图)并在运行时基于屏幕空间误差按集群选择正确 LOD 渲染数十亿三角形。整个流水线在 GPU 上运行。这种方法已移植到 WebGPU。

Nanite WebGPU

Nanite WebGPU 在浏览器中使用 meshlet LOD 层级和软件光栅化器渲染复杂多物体场景
Nanite WebGPU 在 Chrome 中使用 meshlet LOD、WGSL compute shader 中的软件光栅化、每 meshlet 的视锥和遮挡剔除渲染完整场景。无原生插件——纯 WebGPU。

Scthe 的 Nanite WebGPU(GitHub 995+ 星)是 Nanite 核心架构的完整浏览器实现:

  • Meshlet LOD 层级用 meshoptimizer 的集群生成离线构建
  • 软件光栅化器在 WGSL compute shader 中实现(在硬件光栅化不能高效做每集群绘制的 WebGPU 约束内工作)
  • 每实例和每 meshlet 剔除,使用视锥和遮挡测试
  • 广告板假体用于极远物体
  • 纹理和每顶点法线支持

流水线:网格分成约 128 三角形的集群。相邻集群分组,每组(使用 meshoptimizer)简化同时保留共享边界。这递归直到整个网格塌缩为单个集群。运行时,compute shader 遍历 DAG 并按组选择在当前屏幕分辨率产生小于 1 像素误差的最粗集群。

THREE-Nanite 是一个新兴的 Three.js 实现,在集成显卡硬件上达到 20-40fps,同时处理数十万三角形。它演示 Nanite 风格渲染甚至在低端浏览器硬件上可行。

meshoptimizer:LOD 流水线基础

meshoptimizer(Arseny Kapoulkine)是大多数浏览器兼容 LOD 流水线背后的库。1.0 版(2025)提供:

  • 网格简化带误差度量(形状改变多少,用于 LOD 选择)
  • 集群生成用于 Nanite 风格 meshlet 层级
  • 顶点缓存优化用于 GPU 友好的三角形排序
  • 过度绘制优化减少像素着色器成本
  • 顶点量化和压缩用于更小下载

对我们的地形流水线,meshoptimizer 把 SDF 地形的 marching cubes 输出处理为带 LOD 层级的优化集群网格。离线处理在服务端运行。浏览器接收预集群网格并在运行时执行 GPU 驱动 LOD 选择。

meshoptimizer 用于 LOD 生成 + WebGPU compute 用于运行时选择的组合,给浏览器地形与 Nanite 相同的架构模式,适配 Web 约束。

地形感知关卡设计

地形不只是走的表面。它的形状引导玩家移动、指引注意力、创造探索的情绪节奏。最好的开放世界把地形作为设计工具。

视线和地标

The Level Design Book 的 寻路章节 记录了地形高程如何控制玩家看到什么和去哪。山脊隐藏其后的东西,创造好奇心。河谷把移动漏到最低点。从远处可见的高地标(塔、山峰、不寻常的树)给玩家一个走向的目标。

对创作者世界,这意味着地形生成应产生自然寻路特征。山脊线应打破视线,创造玩家越过山头看到新区域时的「揭示时刻」。河谷应汇聚到有趣位置。应有创作者可放置远处可见地标的高点。

好奇心驱动的探索

普渡大学的研究(论文)识别了四个空间探索触发点:

  1. 到达极端点(最高峰、最远边缘、最深洞穴)。地形应有明显极端来奖励到达。
  2. 解开视觉遮挡(那个崖后面有什么?洞里有什么?)。阻挡视线的地形激励移动去发现隐藏物。
  3. 格格不入的物体(荒野中的建筑、黑暗中的光)。创作者放置的物体对自然地形产生对比,吸引注意。
  4. 理解空间连接(这个河谷如何连到那个海岸?)。创建清晰地理的地形鼓励读图和路线规划。

PlotMap:AI 辅助 POI 放置

PlotMap(arXiv:2309.15242)通过接受叙事需求(这个任务需要河边的村庄,那个任务需要山顶的废墟)并找到满足空间约束的地形位置来自动化兴趣点布局。对创作者世界,类似系统可基于地形属性建议结构位置:「这个山头视线好,适合瞭望塔」、「这个有遮蔽的河谷适合村庄」。

流动的水和瀑布

河流和瀑布是结合视觉吸引、环境音和玩法功能(水作为屏障、资源或路径)的地形特征。

河流渲染

开放世界中的河流通常渲染为沿地形表面的纹理条。条带网格从河流样条(存储为控制点)生成并投影到地形高度图。河流着色器应用:

  • 沿流向的 UV沿河流方向滚动,创造流水外观
  • 边缘泡沫在河流与岸交界处(基于深度,类似海岸线泡沫)
  • 速度变化基于河道宽度(窄段流得快,宽段慢)
  • 带基于深度颜色的透明度(浅清深暗)

对浏览器世界,河流数据紧凑:样条(每河段 20-50 控制点,约 400 字节)加宽度和流速参数。客户端通过把样条投影到其地形表面本地生成河流网格。

瀑布渲染

河流从崖面落下处,瀑布粒子系统替换平的河流表面。来自实时水模拟研究的混合方法(EG):不能用高度场表示的区域(瀑布、飞溅)转换为与流体模拟交换质量和动量的喷雾、飞溅和泡沫粒子。

对浏览器世界,瀑布更简单:检测河流样条跨越地形高度间断的位置,在该点生成向下速度的粒子系统,并在底部加泡沫飞溅。粒子是带滚动 alpha 纹理的 GPU 实例化四边形。每瀑布 500 颗粒子,一次绘制调用。落水声使用 Web Audio API 带距离衰减。

远距离地形特征的广告板

树、岩石、建筑和其他地形特征在远处变得很小。把它们渲染为完整 3D 网格浪费 GPU。广告板用面向相机的预渲染平图替换远物体。

八面体广告板 atlas

八面体广告板从多个视角捕捉 3D 物体的外观,存储在纹理 atlas 中。运行时,着色器基于当前视角方向采样 atlas,在两个最近捕捉角度间插值。

半八面体 atlas(仅上半球视角,因为你很少从下方看树)以相同纹理大小提供完整八面体 atlas 两倍的角度分辨率。Unity 的广告板系统报告,当 1,600 树实例从真实网格(每个 14 万三角形)切换到广告板时,帧时间从 111ms 降到 5.78ms。

对浏览器世界,广告板流水线:

  1. 服务端:从 16-32 视角渲染每个资产,捕捉颜色、法线和深度
  2. 打包到 atlas 纹理(每个资产一个 atlas,约 256x256 像素,KTX2 下 <100 KB)
  3. 运行时:广告板距离外的实例(通常 100-200m)渲染为采样 atlas 的广告板
  4. 在 20m 过渡区淡入淡出网格和广告板,隐藏切换

广告板泼溅(BBSplat)

广告板泼溅(2024,arXiv:2411.08508)通过使用可学习纹理平面原始体更进一步。不是预渲染视角,BBSplat 优化广告板位置和纹理以最好地从任意角度表示 3D 物体。这相比 3D Gaussian Splatting 实现最高 17x 压缩,同时保持视角相关外观。对浏览器世界中远距地形特征,BBSplat 可减少每资产广告板存储,同时改善角度覆盖。

专业地形工具及其启示

在从零构建地形流水线之前,了解专业离线工具做什么很有价值。这些工具代表数十年地形生成研究蒸馏到生产工作流。

Gaea(QuadSpinner)是 GPU 加速的,对变化提供近乎瞬时的反馈。它支持每边最高 200 万像素的瓦片构建、自动 LOD 网格导出,以及基于节点的图,每个节点是一个物理过程(侵蚀、沉积、抬升、热风化)。Gaea 的侵蚀节点产生看起来手雕的地形,因为它们建模具体物理过程而不是通用噪声。关键洞见:Gaea 不使用单一侵蚀算法。它为河流侵蚀(河道开凿)、热侵蚀(崖面崩塌)、海岸侵蚀(波浪作用)和风蚀(沙丘形成)提供独立节点。在图中组合它们产生具有特定气候地质特征的地形。

World Machine 采用类似图方法,专注地形宏观结构。其「布局生成器」让艺术家草绘地形特征的粗略形状(这里山、那里河谷、这边海岸线),系统填入物理合理细节。这正是我们想要的创作者工作流:草绘意图,得到地质。

World Creator 以编辑期间实时预览和内置河流生成(分析地形并基于排水分析自动计算流路径)来区分自己。

我们从这些工具中拿走什么: 组合物理过程的节点图方法比任何单一算法更强大。我们的服务端生成流水线应支持链式:噪声基础 > 构造抬升 > 水力侵蚀 > 热风化 > 海岸侵蚀 > 植被。创作者控制每阶段的参数。流水线在服务端几秒内运行,产生高度图、splat map 和植被密度图。

SoilMachine:开源地貌学

SoilMachine:开源模块化地貌模拟器,展示带耦合水力、热和风蚀的地形
SoilMachine 在单一分层地形模型中耦合水力、热和风蚀。多层数据结构支持高度图无法表示的特征:洞穴、悬挑、方山和地下水分布。

SoilMachine 是一个开源模块化地貌模拟器,把多种侵蚀系统(水力、热、风)与沉积运输和沉积耦合。用 C++ 配合 GPU compute 构建,它提供专业工具使用的多过程侵蚀方法的参考实现。

相关的 soillib(C++20,MIT 许可)把底层地貌模拟原始体作为可复用库。hydro-gen 在 OpenGL compute shader 中实现基于网格(浅水)和基于粒子(雨滴)的水力侵蚀,带实时参数调整。

这些开源工具可适配我们的服务端生成流水线。compute shader 实现直接翻译到 WebGPU,如果我们想在浏览器中运行侵蚀做实时创作者反馈。

多层地形材质

真实地形不是单一表面。它是层:底部基岩、上面土壤、雪或沙在表面累积。动态分层随季节、天气和创作者动作改变地形视觉特征。

分层高度场表示

不是单个高度图,每个网格 cell 使用多个高度层:

Cell {
  bedrock_height: f16,    // 永久岩石表面
  soil_height: f16,       // 基岩之上累积的土壤/沉积
  snow_height: f16,       // 动态雪累积
  water_height: f16       // 站立水深
}

合计:每 cell 8 字节(vs 单一高度图的 2 字节)。对 65x65 chunk,压缩前 34 KB。仍紧凑。

视觉表面是 bedrock + soil + snow。地形着色器读所有层并相应混合材质:土薄处岩石露出。雪累积处表面白。水积处得到水洼或湖。

动态累积

雪在降雪期间在平的、朝上表面累积。累积率取决于表面法线(陡坡不留雪)、温度(与海拔相关)和遮蔽(悬挑下区域保持清洁)。Compute shader pass 每个天气 tick 更新雪层(几秒一次)。

沙累积类似工作,带风驱动沉积。风从暴露表面带走颗粒,沉积在障碍物后面和遮蔽区域。

对创作者世界,动态累积意味着地形在不同天气下看起来不同。雪在暴风雪期间覆盖世界,在晴朗期间融化。雨填洼地。这让世界感觉响应,无需创作者做任何事。

多层侵蚀

2024 年论文「3D Real-Time Hydraulic Erosion Simulation using Multi-Layered Heightmaps」(EG)把侵蚀扩展到跨层工作。水侵蚀土壤比基岩快。沉积物作为新土壤层沉积。模拟保持层完整(基岩在土壤之下),同时启用复杂特征如悬挑(基岩悬于下方侵蚀土壤)。

性能:在 RTX 3070 上 2048x2048 分辨率每模拟步约 6ms。这对服务端生成足够快,但对每帧浏览器模拟太慢。分层表示适合静态地形生成,动态雪/水累积作为更便宜的每帧着色器运行。

草、岩石和细节渲染

景观需要的不只是地形几何和纹理。它需要在风中摇曳的草叶、散布坡上的岩石,以及让近距离视图看起来自然的小细节如花、卵石和落枝。

GPU 实例化草

通过 GPU 实例化在单次绘制调用中渲染一百万草叶。同样技术在 Three.js 和 WebGPU 中工作:每实例变换、顶点着色器风动画,以及从地形数据散布草叶的密度图。

基于浏览器的草渲染在 Three.js 中很成熟,通过 GPU 实例化工作。al-ro 的草演示 的方法使用 InstancedBufferGeometry 在单次绘制调用中渲染 10 万草叶。

每个草叶是简单四边形(4-8 三角形)。每实例属性定义位置、高度、弯曲方向、颜色变化和风相位。顶点着色器:

  1. 读取每实例变换
  2. 使用与世界位置和时间相关的正弦波应用风动画
  3. 基于风力弯曲草叶(尖端弯曲更多,基部不弯)
  4. 应用颜色梯度(基部更暗,尖端更亮表示次表面散射)

Codrops 的蓬松草教程(2025,教程)演示了壳纹理方法:以递增偏移多次渲染地面,每层采样噪声纹理以创造密集草体积外观。这对非常密集的覆盖比单独草叶实例化便宜,但近距离不够真实。

对创作者世界,草密度来自每 chunk 的植被密度图。GPU 在渲染时从密度图散布草叶位置。不存储或流送每叶数据。密度图是每 chunk 32x32 网格(1 KB),GPU 从中生成数千草叶实例。

程序化岩石和崖面细节

崖面和岩石地形需要基础高度图或 SDF 在合理分辨率下无法提供的几何细节。两种方法互补:

GPU mesh shader 重建表面(Raad 等,Eurographics 2025,论文)在渲染时从粗控制网格生成程序化几何。mesh shader 读基础地形表面并添加位移、裂纹和凸起,无需在内存中存储细节几何。这减少 VRAM 使用并启用动态 LOD。

实例化岩石散布使用 GPU 实例化在陡坡和崖边放置预制岩石网格。Compute shader 读地形法线和坡度,并在坡度超阈值处散布岩石实例。每实例是带随机旋转和缩放的小网格(200-500 三角形)。1 万散布岩石带实例化增加可忽略的渲染成本。

道路和路径

创作者放置的道路、小径和路径需要顺地形并修改表面材质(用泥或石替换草)。

每个主要游戏引擎使用的方法:把路径定义为样条(一系列控制点)。把样条投影到地形表面。生成跟随样条且略高于地形的条带网格。把路纹理应用到条带。在地形着色器中,用投影纹理或贴花把地形材质混合到样条宽度内的路材质。

对浏览器世界,创作者在地形上画路径。客户端生成控制点并发送到服务器(几十个 vec3 值)。服务器存储样条。所有客户端通过把样条投影到其地形网格本地渲染路条带。路数据微小(路径样条点,约 200 字节),但视觉影响大:连接创作者建筑的路径让世界感觉有人居住。

地形阴影

地形阴影对可读性(理解地形形状)和氛围(一天中的时间情绪)至关重要。在开放世界中,太阳在整个可见地形上投射阴影。

级联阴影贴图(CSM)

CSM 把视锥分成 3-4 个距离范围(级联)。每级联从太阳视角以合适距离的分辨率渲染阴影贴图。近级联:高分辨率(树和建筑下的详细阴影)。远级联:低分辨率(宽阔的山脉阴影)。

Three.js 和 Babylon.js 都支持 CSM。地形的关键优化:只在阴影贴图中渲染地形,不渲染单独的草叶或小细节。草使用地形的阴影贴图自我阴影,不用自己的。

性能预算: 3-4 个 1024x1024 阴影级联。在阴影贴图中渲染地形成本 0.5-1ms(地形几何已在 GPU 内存)。在地形着色器中采样 4 个级联增加 0.2-0.3ms。

从高度图的地形自阴影

对于 CSM 变昂贵的非常大地形,预计算地平线图:对每个地形 cell,存储 8 个罗盘方向的最大高程角度。渲染时,比较太阳角度与地平线图以确定点是否在阴影中。这是 Skyrim 处理远地形自阴影(CSM 范围外)的方法。

地平线图从高度图在服务端计算(几秒处理),作为 128x128 每 chunk 纹理流送(16 KB 压缩)。视觉影响显著:山谷在极端视距下也真实变暗。

用于流送的地形数据压缩

网络是浏览器世界的瓶颈。地形数据中保存的每个字节都是更快的加载时间。

高度图压缩

原始 16 位高度图压缩得好,因为相邻 cell 有相似值。流水线:

  1. Delta 编码: 存储每个 cell 与其预测值(邻居平均)的差。Delta 值小,聚集在零附近。
  2. 量化: 对远 chunk,把精度从 16 位减到 12 位或 8 位。500 米外,8 位高度精度(100m 高度范围上 0.4m 分辨率)与 16 位无差。
  3. 熵编码: 对 delta 编码流应用 zlib 或 brotli 压缩。典型压缩率:4-8x。

结果:65x65 chunk 在 16 位下从 8.4 KB 原始变为 1-2 KB 压缩。在 8 位降精度下:0.5-1 KB。

渐进高度图流送

先以低分辨率发送地形,然后细化。17x17 高度图(64m chunk 带 4m cell 间距的最小值)原始 578 字节,压缩 200 字节以下。地形立即可见。然后流送 33x33 细化(增加奇数行/列样本)。然后 65x65 全分辨率。每级增加细节而不替换之前的数据。

这映射到 geometry clipmap LOD 环:远地形用低分辨率版本(17x17),中距用中(33x33),近用全(65x65)。流送优先级匹配渲染 LOD。

SDF 体压缩

稀疏 SDF 体压缩得极好,因为大部分体素远离表面(空间)。选项:

游程编码: 编码相同值的游程(空体素)。典型 SDF 体 95%+ 是空的,所以 RLE 实现 10-50x 压缩。

稀疏八叉树: 只存储包含表面跨越体素的八叉树节点。空间无节点。带单个洞隧道的 64^3 SDF 体可能只有 2,000-5,000 个占用节点(vs 总共 262,144 体素),每个存储 1-2 字节。

熵驱动渐进压缩(2024,HAL)适用于 3D 空间数据,通过用熵优化平面和自适应量化递归划分空间。这产生为速率-失真权衡优化的细化流,在网络流送的低比特率下特别有益。

综合:浏览器地形流水线

文章顶部的战略概览给出了快速决策框架和分阶段构建计划。本节为服务端生成流水线和浏览器渲染流水线提供完整技术细节。

生成流水线(服务端)

生成流水线作为物理过程的有向图运行,灵感来自 Gaea 和 World Machine 的节点图方法。每阶段接受上阶段输出并细化。创作者控制每阶段的参数。

阶段输入过程输出时间
1. 基础地形种子或文本提示Terrain Diffusion / MESA / 噪声 + fBm16 位高度图1-5s
2. 侵蚀高度图解析 stream power + 热侵蚀侵蚀高度图、流量累积图、沉积图0.5-2s
3. 河流侵蚀高度图、流量图排水网络提取、河道开凿河流样条、水位图0.5s
4. 海岸海平面附近高度图NEWTS 风格波浪侵蚀海岸线特征(崖、海滩、海蚀柱)1-3s
5. 体积高度图 + 创作者意图Arenite 侵蚀 / 洞穴生成 / SDF 雕刻受影响 chunk 的稀疏 SDF 体1-60s
6. 材质高度图 + 侵蚀图TerraFusion / Geodiffussr / 程序化规则Splat 图、地形纹理1-5s
7. 植被高度图 + 流量图 + 材质生态系统竞争模拟每群落每 chunk 的密度图1-3s
8. 地平线图最终高度图8 方向最大高程角度每 chunk 自阴影纹理2-5s
9. 分块所有输出切片、delta 编码、压缩、哈希CDN 上的 chunk 包5-10s
总计15-90s

新的 4x4 km 世界在 15-90 秒生成。创作者编辑(雕塑、参数变化)只为受影响 chunk 重跑受影响阶段,通常 5 秒内完成。

渲染流水线(浏览器)

步骤WebGPU 路径WebGL 2 回退帧预算
1. 流送优先队列、预测预取不适用(异步)
2. 高度图地形GPU 驱动 CDLOD 四叉树、compute 剔除、间接绘制Geometry clipmap、CPU 环更新0.5-1ms
3. 体积网格Compute marching cubes + Transvoxel来自 Web Worker 的预生成网格、2-3 缓存 LOD0.5-2ms
4. LOD 过渡顶点着色器中的 geomorphing包含以上
5. 材质Triplanar PBR + 拉普拉斯混合 + phasor 噪声细节 + 虚拟纹理Triplanar PBR + 线性混合 + 预烘焙 splat 图1-1.5ms
6. 植被ComputeInstanceCulling + IndirectBatchedMesh、hex-tiled 地被CPU 视锥剔除 + InstancedMesh1-1.5ms
7. 水沿流向河流条、基于深度的海岸泡沫同(更简单反射)0.5ms
8. 阴影3-4 级联 CSM + 地平线图自阴影2 级联 CSM0.5-1ms
9. 大气Hillaire 天空模型 + 体积雾 + 天气粒子Preetham 天空 + 距离雾0.5ms
10. 动态效果水洼累积、脚印形变、雪/雨水洼累积、雨粒子0.3ms
地形总计3.5-6.5ms

在 60fps(每帧 16.6ms),地形系统在 WebGPU 上使用 21% 的帧预算,WebGL 2 上 39%。其余可用于玩家头像、创作者物体、UI、网络和后处理。

为什么这在浏览器中工作

整条流水线围绕三个浏览器约束设计:

内存(最大 2-4 GB): 256 MB 地形预算适用,因为高度图 chunk 每个 2-8 KB(delta 编码),SDF 体稀疏(每体积 chunk 100-500 KB),植被在运行时从 1 KB 密度图生成,纹理使用 KTX2 压缩(每 1024x1024 150 KB)。任意时刻,浏览器中可见世界合计 50-200 MB。

无磁盘访问: 一切通过网络流送。渐进加载意味着玩家在 <100ms 看到地形(低分辨率高度图)、<300ms 看到带纹理地形、<3s 看到全细节。基于速度的预取在正常探索期间隐藏加载时间。

GPU 差异大: WebGPU 路径处理高端桌面。WebGL 2 回退处理其他一切,包括移动。同一 chunk 数据驱动两条路径。差异是渲染技术,不是数据格式。运行 WebGL 2 的 Chromebook 看到与运行 WebGPU 的 RTX 4090 相同的世界,只是细节更低、视距更短。

研究论文

地形表示和网格生成

「Marching Cubes: A High Resolution 3D Surface Construction Algorithm」 —— Lorensen 与 Cline(SIGGRAPH 1987)。DOI。从体积数据提取三角网格的基础算法。38 年后仍是最广泛使用的等值面提取方法。GPU 并行实现在 WebGPU compute shader 中实时运行。

「Dual Contouring of Hermite Data」 —— Ju, Losasso, Schaefer, Warren(SIGGRAPH 2002)。DOI。产生保留 marching cubes 磨圆的尖锐特征(崖边、岩石角点)的网格。除距离值外还需要表面法线。

「Neural Dual Contouring」 —— Chen 等(2022)。arXiv:2202.01999。用学习的预测器替换 dual contouring 中的最小二乘顶点放置。复杂自然特征的表面质量更佳。

「The Transvoxel Algorithm」 —— Lengyel(2009,2024 更新)。transvoxel.org。体素地形的无缝 LOD 过渡。使用 73 种过渡单元类型消除分辨率边界裂缝。免专利,为实时应用设计。

地形 LOD 和渲染

「Geometry Clipmaps: Terrain Rendering Using Nested Regular Grids」 —— Losasso 与 Hoppe(SIGGRAPH 2004)。论文。带同心 LOD 环的恒成本地形渲染。在交互速率处理 40 GB 地形。大多数浏览器地形渲染器的基础。

「CDLOD: Hybrid LOD for Terrain Rendering」 —— Strugar(2014)。论文。geometry clipmap 的四叉树自适应改进。基于地形复杂度而不仅基于距离分配分辨率。

「GPU-Driven Rendering Pipelines」 —— Ubisoft(SIGGRAPH 2015),Wihlidal 和 Hoppe。形式化了 compute shader 处理剔除、LOD 选择和绘制调用生成的 GPU 驱动方法。我们 WebGPU 地形流水线的架构模式。

物理地形生成

「Physically-Based Analytical Erosion for Fast Terrain Generation」 —— Cordonnier 等(2024)。HAL。避免迭代模拟的解析 stream power law 侵蚀。毫秒内生成物理可信地形。

「Fast Hydraulic Erosion Simulation and Visualization on GPU」 —— Mei, Decaudin, Hu(2007)。HAL。使用浅水模拟的 GPU 并行水力侵蚀。大多数游戏引擎侵蚀实现的基础。

「Arenite: A Physics-Based Sandstone Simulator」 —— SIGGRAPH 2025。项目。从应力和侵蚀模拟生成拱门、土柱和壁龛的多物理侵蚀。在桌面 GPU 上 5 分钟内运行。

「Efficient Debris-flow Simulation for Steep Terrain Erosion」 —— 普渡 CGVLAB(2024)。论文。产生真实山地地形特征的 GPU 加速碎屑流和陡坡侵蚀。

「Flexible Terrain Erosion」 —— IRIT-STORM(2024)。Springer。带统一接口跨高度场、体素网格、隐式表面和分层材质工作的基于粒子侵蚀。启用混合地形表示的单一侵蚀系统。

地形细节和纹理

「GPU-Friendly Laplacian Texture Blending」 —— Wronski(NVIDIA,2025)。JCGT。无预计算的地形材质实时拉普拉斯金字塔混合。保留尖锐特征同时消除接缝伪影。每片元几次额外纹理采样。

「Real-time Terrain Enhancement with Controlled Procedural Patterns」 —— Grenier 等(2024)。CGF。最高 32x 高度图分辨率的基于 phasor 噪声的微侵蚀细节。沿坡向图案完全在片元着色器中运行。

自适应细分

「Concurrent Binary Trees for Large-Scale Game Components」 —— Benyoub 和 Dupuy(Intel,HPG 2024)。论文。用于自适应地形细分的 GPU 友好二叉树数据结构。0.2ms 内渲染行星级几何。从方形域扩展到任意多边形网格。

洞穴和地下生成

「PLUME: Procedural Layer Underground Modeling Engine」 —— 2024。arXiv:2508.20926。用分层程序化规则生成真实洞穴和熔岩管环境的开源框架。最初为太空探索机器人构建。

神经地形合成

「Terrain Diffusion: A Diffusion-Based Successor to Perlin Noise」 —— Goslin(2025)。arXiv:2512.08309。使用带拉普拉斯编码的分层扩散模型的无限、种子一致地形生成。在消费级 GPU 上比基线快 9 倍。

「TerraFusion: Joint Generation of Terrain Geometry and Texture」 —— 2025。arXiv:2505.04050。带草图条件的同时高度图和纹理合成的潜变量扩散。

「MESA: Text-Driven Terrain Generation」 —— CVPR 2025 Workshop。arXiv:2504.07210。使用 Copernicus 遥感训练数据的文本到地形。

「Geodiffussr: Generative Terrain Texturing with Elevation Fidelity」 —— 2025。arXiv:2511.23029。尊重高程数据的文本引导地形纹理生成,使用流匹配。

「Sketch2Terrain: AI-Driven Real-Time Terrain Sketch Mapping」 —— 2025。项目。增强现实中的草图到地形。比手动映射效率提升 38%。

植被和生态系统模拟

「GPU-Based Real-Time Procedural Distribution of Vegetation on Large-Scale Virtual Terrains」 —— SBGames 2018。论文。在 GPU 上使用生物/非生物因素的基于四叉树的植被散布。

「Procedural Generation and Rendering of Forests」 —— 2022。论文。L-system 树生成与生态系统竞争模拟组合,用于真实森林分布。

「Real-Time Procedural Generation with GPU Work Graphs」 —— AMD GPUOpen 2024。论文。GPU work graph 在 4ms 内生成 7.9 万+ 植被实例。

浏览器 GPU 技术

「GSWT Renderer」 —— SIGGRAPH Asia 2025。GitHub。使用高斯泼溅 Wang Tiles 的带动态 LOD 和流送的无限 3D 地形 WebGPU + Rust/Wasm 渲染器。

「GPU Compute in the Browser at the Speed of Native: WebGPU Marching Cubes」 —— Usher(2024)。博客。演示 WebGPU compute 对并行网格生成算法达到原生速度性能。

体素渲染和大规模场景

「Aokana: A GPU-Driven Voxel Rendering Framework for Open World Games」 —— 2025。arXiv:2505.02017。带 LOD 和流送的稀疏体素 DAG,用于带数百亿体素的场景。相比之前最先进的 9x 内存减少和 4.8x 更快渲染。为游戏引擎集成设计。

程序化几何和重建表面

「Real-time Procedural Resurfacing using GPU Mesh Shaders」 —— Raad 等(Eurographics 2025)。论文。在渲染时从粗控制网格生成详细几何表面,使用 mesh shader。启用不存储高分辨率几何的动态 LOD。

地形阴影

「Optimizing Terrain Shadows」 —— AMD GPUOpen。博客。大规模地形的实用 CSM 优化。覆盖级联分割、GPU 高效阴影贴图渲染和地形特定优化。

虚拟几何和网格优化

「Nanite WebGPU」 —— Scthe(2024)。GitHubDemo。UE5 Nanite 架构的完整浏览器实现:meshlet LOD 层级、WGSL 中的软件光栅化器、每 meshlet 剔除、广告板假体。

「Billions of Triangles in Minutes」 —— Kapoulkine(2025)。博客。Meshoptimizer v1.0 用于分层集群 LOD 生成。高效处理大规模网格为 Nanite 风格集群 DAG。

「Billboard Splatting(BBSplat)」 —— 2024。arXiv:2411.08508。用于新视角合成的可学习纹理平面原始体,相比 3D Gaussian Splatting 实现 17x 压缩。

地形光照和全局照明

「Global Illumination in Once Human」 —— GDC 2025。Session。16km 开放世界的混合 GI:神经网络压缩探针(69:1 比率)、基于 ML 的室内/室外漏光解决、动态探针反应。

「GI with AMD FidelityFX Brixelizer」 —— GDC 2024。论文。带屏幕空间探针的基于 compute 的稀疏距离场级联。无需硬件光线追踪。

「Radiance Cascades」 —— 2024。博客。使用级联辐射结构的无噪实时全局照明,无时间累积。

关卡设计和探索

「PlotMap: Automated Layout Design for Building Game Worlds」 —— 2023。arXiv:2309.15242。在地形上满足叙事空间约束的 AI 辅助 POI 放置。

「Spatial Exploration Triggers」 —— 普渡大学(FDG 2022)。论文。驱动玩家探索的四种设计模式:极端点、视觉遮挡、格格不入物体、空间连接。

数据压缩和流送

「Entropy-driven Progressive Compression of 3D Point Clouds」 —— SGP 2024。论文。使用带自适应量化的递归空间划分的速率-失真优化渐进压缩。产生适合可变带宽网络流送的细化流。

交互式编辑

「WebGPU SDF Editor」 —— Nijhoff(2026)。项目。带实时 marching cubes、布尔操作、平滑混合和八叉树空间划分的浏览器全功能 SDF 建模。每原始体 112 字节。

河流和海岸生成

「Procedural River Drainage Basins」 —— Patel(Red Blob Games)。项目。使用 Voronoi/三角网格边分类的排水优先河流生成。在分配地形高程前构建河流层级。

「NEWTS1.0: Numerical Model of Coastal Erosion by Waves and Transgressive Scarps」 —— MIT(2024)。论文。使用均匀后退和波驱动侵蚀的简化海岸侵蚀模型。生成匹配真实地貌的海岬、海湾、海蚀柱和拱门。

延伸阅读