【URP】Unity[内置Shader]地形光照TerrainLit

【从UnityURP开始探索游戏渲染】专栏-直达

TerrainLit Shader是Unity URP(通用渲染管线)中专为地形系统设计的内置着色器,主要用于高效渲染大规模地形表面并支持多纹理混合。

作用与原理

‌核心功能‌:

  • 支持最多8层纹理混合,通过高度图 或遮罩图 控制混合过渡
  • 采用基于物理的渲染(PBR)模型处理光照和材质反射
  • 优化了LOD(细节层次)系统,适应远距离地形渲染

发展历史

  • ‌2018年‌:随URP首次推出,仅支持4层纹理混合
  • ‌2019年‌:升级至支持8层混合,增加PBR支持
  • ‌2020年‌:优化GPU实例化,提升大规模地形渲染性能

‌技术原理‌:

  • 使用SplatMap技术混合多张纹理,通过RGBA通道存储混合权重
  • 在顶点着色阶段计算地形高度和法线,片段着色阶段进行纹理采样混合

SplatMap技术

SplatMap技术通过纹理的RGBA通道存储多层纹理权重信息,在片段着色器中实现动态混合。

存储机制

  • ‌通道分配 ‌:
    • 每个RGBA通道对应一个纹理层的权重值(0-1范围),例如R通道存储第1层权重,G通道存储第2层权重,依此类推。当需要超过4层时,会使用多张SplatMap(如第二张SplatMap的R通道存储第5层权重)。
  • ‌数据编码 ‌:
    • 权重值通常以8位精度存储(0-255映射到0.0-1.0),在着色器中通过归一化还原。例如,R通道值0.5表示第1层权重为50%。

着色器实现示例

以下是一个基于Unity的片段着色器代码片段,演示如何采样并混合4层纹理:

c 复制代码
hlsl
half4 frag(v2f input) : SV_Target {
    // 采样SplatMap获取权重
    half4 splat = SAMPLE_TEXTURE2D(_SplatMap, sampler_SplatMap, input.uv);

    // 采样各层纹理
    half4 tex1 = SAMPLE_TEXTURE2D(_Layer1, sampler_Layer1, input.uv);
    half4 tex2 = SAMPLE_TEXTURE2D(_Layer2, sampler_Layer2, input.uv);
    half4 tex3 = SAMPLE_TEXTURE2D(_Layer3, sampler_Layer3, input.uv);
    half4 tex4 = SAMPLE_TEXTURE2D(_Layer4, sampler_Layer4, input.uv);

    // 动态混合(权重归一化处理)
    half sumWeights = splat.r + splat.g + splat.b + splat.a;
    half3 finalColor = (tex1.rgb * splat.r + tex2.rgb * splat.g +
                       tex3.rgb * splat.b + tex4.rgb * splat.a) / sumWeights;

    return half4(finalColor, 1.0);
}

性能优化

  • ‌纹理数组替代‌:

    • 使用Texture2DArray将多张纹理合并为单一资源,通过索引值(存储在SplatMap的R/G通道)选择纹理,减少采样次数。例如:

      c 复制代码
      hlsl
      half4 var_Main = SAMPLE_TEXTURE2D_ARRAY(_TexArray, sampler_TexArray, uv, splat.r * 255) * splat.b;
      half4 var_Sec = SAMPLE_TEXTURE2D_ARRAY(_TexArray, sampler_TexArray, uv, splat.g * 255) * (1 - splat.b);
      half4 finalRGB = var_Main + var_Sec;
  • ‌高度混合增强‌:

    • 结合高度图(存储在SplatMap的B通道)实现更自然的过渡效果,通过比较各层高度值动态调整权重。

限制与改进

  • ‌通道限制‌:传统SplatMap每张仅支持4层,超过时需要多张纹理,增加带宽压力。
  • ‌混合精度‌:8位通道可能导致可见的带状伪影,可通过16位浮点纹理或抖动技术缓解。

具体使用示例

‌基础配置‌

  • 创建Terrain对象
  • 在Inspector面板选择Material为"Custom"
  • 指定Shader为"Universal Render Pipeline/Terrain/Lit"

通过SplatMap控制纹理混合时,需在Terrain Layers中配置各层纹理的金属度/光滑度等PBR参数

  • ‌脚本控制混合‌:

    csharp 复制代码
    csharp
    // 动态修改第2层纹理权重
    Terrain terrain = GetComponent<Terrain>();
    float[,,] map = terrain.terrainData.GetAlphamaps(0, 0, 1, 1);
    map[0,0,1] = 0.5f;// 设置权重为50%
    terrain.terrainData.SetAlphamaps(0, 0, map);

Shader Graph应用

  • ‌扩展案例 ‌(雪地效果):
    • 创建Unlit Shader Graph,添加Height节点检测地形高度5
    • 使用Lerp节点混合雪地纹理和基础纹理:最终输出到Base Color和Normal通道
      • Height → Step → Lerp(T) 基础纹理 → Lerp(A) 雪地纹理 → Lerp(B)
  • ‌溶解效果移植 ‌:
    • 复制TerrainLit的混合逻辑到Shader Graph
    • 添加Noise节点连接Alpha通道实现地形局部溶解
    • 关键节点链:
      • Noise → Step → Alpha Clipping Color → Emission(边缘发光)

该着色器通过模块化设计平衡了性能与效果,在URP 12.x版本后已完全支持Shader Graph的自定义扩展


【从UnityURP开始探索游戏渲染】专栏-直达 (欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,🙏)

相关推荐
SmalBox5 天前
02-07-原理篇-文件系统与跨平台适配
unity3d·游戏开发
只睡四小时5 天前
Canvas 弹道联机实战:700 行 + 固定时间步长
python·websocket·html5·游戏开发·canvas
SmalBox6 天前
02-06-原理篇-热更新与版本管理
unity3d·游戏开发
SmalBox7 天前
02-05-原理篇-资源加载与缓存机制
unity3d·游戏开发
SmalBox8 天前
02-04-原理篇-资源组织与依赖分析
unity3d·游戏开发
Huanzhi_Lin8 天前
从0搭建ECS:跨品类评估
架构·游戏开发·ecs·ecs跨品类评估
甲维斯8 天前
《钢铁洪流》开发笔记:AI策略升级!
人工智能·游戏开发
贾伟康8 天前
【HarmonyOS 7新能力|038】游戏快启工程封装:把接入逻辑放进可维护的分层结构
性能优化·harmonyos·arkts·游戏开发·软件架构
SmalBox9 天前
02-03-原理篇-资源打包流程详解
unity3d·游戏开发
UWA9 天前
让UE性能分析真正穿透指标:GPU看堆栈,Texture拆到Group
性能优化·游戏开发