王者荣耀地表用的Terrain Splatting技术,简单说就是合并多层贴图,平滑融合边缘。
这个技术由Charles Bloom发明的,他有一篇文章介绍说明,另外wiki上也有一些基本原理介绍。
整个地表没有用高度图,直接用 分割粒度适中的Mesh 做的,下图是战斗地图右直道,uv是路边缘草(_Splat0),uv2是石块(_Splat1)。colors是用于做二层融合,alpha没有单独使用贴图直接存在mesh中,节省的小技巧。很多年前一位美女让我帮忙做个地形编辑器,我居然用了八层地表,逃~~~~~
下图屏蔽石块层后渲染效果,可看出alpha层实际就是一个简单的渐变,没有用笔刷刷。
如下脑洞分析后人工重写的shader,可能与原始游戏效果有些差异。
Shader "S_Game_Scene/TerrainVertexUV2Tiling"
{
Properties
{
_Splat0 ("Layer1(uv1)", 2D) = "black" {}
_Splat1 ("Layer2(uv2)", 2D) = "white" {}
}
SubShader
{
Tags{ "Queue" = "Geometry+110" }
Pass
{
Tags{"LightMode" = "ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 2.0
#include "UnityCG.cginc"
sampler2D _Splat0;
sampler2D _Splat1;
float4 _Splat0_ST;
float4 _Splat1_ST;
struct v2f
{
float4 pos : SV_POSITION;
half2 uv_Tex0:TEXCOORD0;
half2 uv_Tex1:TEXCOORD1;
float4 color : COLOR;
};
struct appdata
{
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0;
float4 color : COLOR;
};
v2f vert (appdata v)
{
float4 worldPos = mul(unity_ObjectToWorld, v.vertex);
v2f o;
o.uv_Tex0 = TRANSFORM_TEX(v.texcoord ,_Splat0);
o.uv_Tex1 = TRANSFORM_TEX(v.texcoord ,_Splat1);
o.color = v.color;
o.pos = UnityObjectToClipPos(float4(v.vertex.xyz, 1));
return o;
}
fixed4 frag(v2f i) : COLOR
{
fixed4 color = fixed4(1,1,1,1);
fixed4 Tex0Color = tex2D(_Splat0, i.uv_Tex0);
fixed4 Tex1Color = tex2D(_Splat1, i.uv_Tex1);
color = lerp(Tex0Color,Tex1Color, i.color.a);
return color;
}
ENDCG
}
}
FallBack "Diffuse"
}
另外还有基于高度的融合,融合效果更自然,下篇再介绍吧~