本节摘要:高度场把地形表达为规则 2D 网格上的高度值——本质是图像。所有地形操作(噪声、笔刷、侵蚀、掩码)都变成对这张图的逐像素处理,比普通网格快一个量级。本节搭完整流水线:分层噪声起势、水力侵蚀塑理、衍生掩码驱动散布与材质。
第 1~3 章的山用的是普通网格,一切都能做,但两处吃力:
代价是拓扑受限:高度场做不了洞穴、悬挑、真正的 3D 结构。选择标准一句话:表面地形用高度场,内部结构用普通网格/VDB。两者可随时转换(Heightfield Convert 把栅格转成网格继续加工)。
在 obj 层建 Heightfield 节点(grid size 2049、总尺寸 2000 米量级按项目定)。依次:

Erode 节点值得单独说。它模拟雨水冲刷与重力崩落:陡坡被切出沟壑、坡脚堆出冲积扇。要点有三:
到此为止你手里的资产是一张高度图加一堆语义层。出口三路:
⚠️ 常见坑:栅格分辨率与视口预览混淆。2049 的场在视口里看是低模,误以为"精度丢了"——它只是显示代理,Erode 与导出用的都是全分辨率数据。另一坑:把 Heightfield 当万能容器塞进 3D 规则(洞穴、拱桥),做不了再骂工具。
下一节把掩码方法论搬到钢筋水泥上:程序化城市生成。
HeightField 工作流的核心纪律是"每层地质过程一个独立层",合成用乘法与加法各司其职:加法叠构造(隆起+盆地),乘法做遮罩(只在高原加噪声)。一条标准层序:
[地形层序模板] Mask(大尺度大陆形状) × -> HeightNoise(山区, ridged) + HeightNoise(丘陵, 低octaves) + Mask(河道带) × (-下切量) -> 河谷 + Erode(水力/热力, 老地层感) + HeightBlur(Mask=平原区) -> 沉积平原 任何时刻: 每层独立开关/独调参数 -> 地貌学家的"可审计地形"
层序的可回溯性是关键交付:导演说"山再靠西一点",你改的是第一层 Mask 的偏移,而不是重雕整张高度图——程序化地形与手雕地形的分界正在于此。
// Volume Wrangle (Run Over: Volume) —— 坡向光照合成植被带 vector g = volumegradient(0, 0, "height", v@P); // 高度梯度 float slope = length(g); float northness = -normalize(g).z; // 假设 -Z 为北 f@veg_weight = fit(slope, 0.1, 0.6, 1, 0) // 缓坡才有植被 * fit(northness, -0.2, 0.8, 0.2, 1.0) // 北坡湿润加权 * fit01(noise(v@P*0.02), 0.3, 1.0); // 群落边界破碎 // Scatter 的 Density Attribute 填 veg_weight 即完成生态散布
高度场在此兑现了"几何即数据库"的承诺:地形是体积数据库,植被、积雪、路径规划都是对它的查询。
最后说明高度场与 VDB 体积的关系:HeightField 本质是 2D 体积特化(带邻接语义的标量场),所有 Volume 工具可直接用于它,这意味着第三方的体积算法(模糊、重采样、场运算)都是地形工具箱的天然成员。当项目需要真正的 3D 地质(洞穴、悬挑)时,2D 高度场升级为 SDF 体积管线,两者通过 Volume Sample 无缝衔接——环境系统因此拥有从地表到地下的连续数据结构,而非两套割裂的软件世界。