我们今天学习Unity的地形渲染

​ image-20260609222218244

我们可以看这个shader脚本的前五个属性

​ image-20260609223440526

​ image-20260609223343531

创建地形分层shader

首先创建一个有光照lit的shadergraph

然后添加如下节点

由于这些材质会默然在inspector暴露参数,我们需要取消勾选每一个“Exposed”不再暴露在inspector (注意: 如果你是unity 6 用户,取消勾选 show in inspector) ,然后勾选每一个sprite的 Use Tilling and offset(平铺与偏移),并将Fragment里的smoothness平滑值设为0(这个我们之前说过,当这个不为0时材质表面上会出现一层像陶瓷轴一样的反光,这里我们不需要这个效果)

​ image-20260609224633721

Use Tiling and Offset 用于控制纹理是否自动应用材质面板中的 Tiling(平铺) 和 Offset(偏移) 参数。启用后,Shader 会自动对 UV 执行 UV × Tiling + Offset 计算,使开发者和美术能够直接在材质球中调整纹理的重复次数和偏移位置,而无需修改 Shader Graph。对于普通贴图材质通常建议开启,对于已经手动处理 UV 的效果(如流动纹理、Triplanar、世界空间映射等)则通常关闭以避免重复计算。

我们们首先实现模型的材质的分层,添加一个control层和四个sprite层,这个是对应代码里的Control和四个图层

已复制
[HideInInspector] _Control("Control (RGBA)", 2D) = "red" {}
[HideInInspector] _Splat3("Layer 3 (A)", 2D) = "grey" {}
[HideInInspector] _Splat2("Layer 2 (B)", 2D) = "grey" {}
[HideInInspector] _Splat1("Layer 1 (G)", 2D) = "grey" {}
[HideInInspector] _Splat0("Layer 0 (R)", 2D) = "grey" {}

标准unity地形系统支持四个纹理层,地形系统通过名为Control的首个纹理将数据传输至着色器,也就是我们添加的control纹理,纹理的每个色彩通道都记录了地形对应位置某个图层的强度值,

所以红色通道对应的是第一层,也就是Sprite0

绿色通道对应的是第二层,也就是Sprite1

蓝色通道对应的是第三层,也就是Sprite2

alpha通道对应的是第四层,也就是Sprite3

而这里为了实现这个效果,可以直接用各个sprite层直接乘以control层的各个颜色的通道值,然后依此相加,最后将效果叠加到基础色上

​ image-20260610145110710

目前已经可以实现分层了,但是为了让山体地形更真实,我们需要特殊处理一下

需要获取地形表面的法向量,检测y轴分量,若接近1或者-1就是近乎水平的地面,若接近0表示检测到的是斜坡地形

​ image-20260610150448245

我们添加两个浮点参数:

normal start 用于控制y分量阈值用于判定岩石面的起始位置,设置为默认值为0.5取值范围0-1的slider

normal end 用于控制岩石面的终止边界,默认值设为0.6取值范围0-1的slider

然后使用normal vector法向量节点用split分离出y向量(也就是G通道),并使用smoothstep平滑过渡节点在normal start和normal end之间

这里复习一下这个节点: 当输入值小于第一个边界值时,节点输出0,当数值大于edge2时,节点输出1,当输入值介于两者之间的时候,输出值会呈现为从0-1的平滑过渡曲线

可以看到球体垂直面显示的是黑色,而顶部平坦区域显示为白色,这里不会出现全黑的情况,因为在unity实际地形环境中发现向量的y分量不会出现负值

然后我们把第一层和第二层使用smoothstep传入的参数来线性插值,并和control节点的R通道相乘

​ image-20260610145535261

我们从模型网站下载一个山体的obj免费模型,然后添加合适的材质图通过调整参数来修改山体的效果,这样就可以实现了山体的材质(不过如字面意思,这就是贴图,和无人深空,荒野大镖客,黑神话悟空这些可交互地形这些没法比)

​ image-20260610141153134

​ image-20260610141036656

​ image-20260610141102609

​ image-20260610141248666

扫描地形效果

我们做一个扫描地形的效果 image-20260610152728848

添加一个颜色节点并设置为HDR

​ image-20260610155558083

image-20260610153039280

由于手动控制地形扫描效果过于麻烦,我们可以使用C#脚本

C#已复制
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class WorldScanner : MonoBehaviour
{
    public float scanSpeed;
    public Terrain terrain;

    private Material terrainMaterial;
    private float scanDistance;

    void Start()
    {
        terrainMaterial = terrain.materialTemplate;
        scanDistance = 1000f;
    }


    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Vector3 mousePos = Input.mousePosition;
            if (Physics.Raycast(Camera.main.ScreenPointToRay(mousePos), out RaycastHit hitInfo))
            {
                terrainMaterial.SetVector("_ScanOrigin", hitInfo.point);
                scanDistance = 0.0f;
            }
        }
        scanDistance += scanSpeed * Time.deltaTime;
        terrainMaterial.SetFloat("_ScanDistance", scanDistance);
    }
}

但是之前我们为了节省时间直接从素材网站上下载的山的模型

unity其实自带了地形系统

其实我们可以自己刷一个,首先创建一个terrain

​ image-20260610161121265

然后切换为set height并选择合适的笔刷来绘制地形

​ image-20260610162403233

6个绘图模式说明

1. Set Height(设置高度)

  • 作用:将地形特定区域的高度设置为一个固定值。
  • 用法:先设定目标高度(Height),然后在地形上刷涂,被刷到的区域会被”压平”到该高度。
  • 应用场景:创建平台、湖泊底部、道路基础层,或平整出建筑地基。
  • 关键参数:Height 滑块决定目标高度;配合 Opacity 控制过渡强度。

2. Smooth Height(平滑高度)

  • 作用:柔化地形高度的不规则起伏,消除尖锐的棱角和噪点。
  • 用法:像橡皮擦一样在崎岖区域刷涂,使相邻顶点的高度差异变小。
  • 应用场景:人工雕刻地形后消除锯齿感;让陡峭悬崖过渡更自然;修复笔刷留下的硬边。
  • 注意:过度使用会让地形失去细节,变得”圆滑过度”。

3. Paint Texture(绘制纹理)

  • 作用:在地形表面绘制不同的材质纹理(如草地、泥土、岩石、雪地)。
  • 用法:先在 Terrain 的 Paint Texture 标签页添加纹理图层(Layers),每个图层包含漫反射贴图、法线贴图等,然后选择图层进行绘制。
  • 关键概念:
    • Splat Map( splat 贴图):Unity 使用 RGBA 通道混合最多 4 个纹理作为一个 Terrain Layer,多个 Layer 会自动分配额外的 splat 贴图。
    • Target Strength:控制绘制强度(0-1),实现纹理过渡混合。

4. Paint Holes(绘制孔洞)

  • 作用:在地形网格上”挖洞”,使该区域的 terrain 几何体不渲染。
  • 用法:刷涂后该区域变成透明/空洞,可以看到地形下方的物体。
  • 应用场景:制作洞穴入口、地下通道、地窖、竖井,或让地形与地下场景衔接。
  • 注意:
    • 孔洞是真正的几何缺失,不是透明材质。
    • 需要配合其他几何体(如洞穴模型)填补空洞,否则会看到背面或天空盒。

5. Stamp Terrain(印章地形)

  • 作用:像盖章一样将预设的高度图(Heightmap)印记到现有地形上。
  • 用法:选择一个高度图纹理(通常是灰度图),调整大小、旋转、高度倍数后,点击地形放置。
  • 应用场景:快速生成特定形状的山峰、陨石坑、台地;批量制作重复地貌特征;导入外部软件(如 World Machine)生成的高度图进行局部叠加。
  • 特点:属于非破坏性/半破坏性编辑,可以预览后再确认,适合程序化生成内容。

6. Raise or Lower Terrain(升高或降低地形)

  • 作用:最基本的地形笔刷,增加或减少地形高度。
  • 用法:
    • 左键刷涂:升高地形(Raise)。
    • 按住 Shift + 左键刷涂:降低地形(Lower)。
  • 应用场景:徒手雕刻山脉、山谷、河床;快速搭建地形大形。
  • 关键参数:
    • Brush Size:笔刷半径。
    • Opacity:单次刷涂的强度/高度变化量。
    • Brush Shape:圆形、柔边等笔刷形状影响过渡自然度。

总结对比表

工具 核心功能 破坏性 典型用途
Raise/Lower 自由升降高度 直接修改高度图 大形雕刻、山脉河谷
Set Height 固定到目标高度 强制平整 平台、地基、湖床
Smooth 模糊高度差异 平滑现有高度 消除锯齿、柔化过渡
Paint Texture 绘制地表材质 修改 splat 贴图 草地、岩石、道路
Paint Holes 删除局部网格 产生空洞 洞穴、地窖入口
Stamp 叠加预设高度图 叠加式修改 特定地貌、程序生成

画好地图后来给地图上材质,首先切换为PaintTexture模式

​ image-20260610193756855

我们点击添加图层,添加纹理并绘制,当然没有的话也可以用现有的texture来create一个

image-20260610203726521

​ image-20260610205514247

然后我们的一坨山脉就做好了