【从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层纹理:
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通道)选择纹理,减少采样次数。例如:
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 // 动态修改第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)
- Height → Step → Lerp(T)
- 溶解效果移植:
- 复制TerrainLit的混合逻辑到Shader Graph
- 添加Noise节点连接Alpha通道实现地形局部溶解
- 关键节点链:
- Noise → Step → Alpha Clipping
Color → Emission(边缘发光)
- Noise → Step → Alpha Clipping
该着色器通过模块化设计平衡了性能与效果,在URP 12.x版本后已完全支持Shader Graph的自定义扩展
【从UnityURP开始探索游戏渲染】专栏-直达
(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,🙏)
TerrainLit Shader是Unity URP(通用渲染管线)中专为地形系统设计的内置着色器,主要用于高效渲染大规模地形表面并支持多纹理混合。 作用与原理 核心功能: 支持最多8层纹理混合