1、如下圖,我們的地形是640x640大小
2、我們要在這個地形上使用一個紋理進行填充
這個layer的設置Tiling Settings是320x320
那麼也就是地板磚的大小是320x320的,而我們的地形是640x640的,那麼需要幾塊地板磚呢?
(640/320)*(640/320)=4
對的,就是4塊,我們看上圖左,就可以看到四個金泰熙思密達的頭像了。
如果我們把這個地板磚改爲640x640的大小,那麼,我們只需要一塊地板磚:
不出我們所料。
ok,我們知道了,這個Tiling Settings的意思之後,就需要在代碼中取得:
public class SplatInfo
{
public string texturePath;
public float sizeX; //我們假設每塊地板磚的大小長寬相等,所以只記錄一個x即可。並且offset都是0
}
TerrainLayer[] layers = m_terrainData.terrainLayers;
SplatInfo[] m_splatInfos = new SplatInfo[layers.Length];
for (int i = 0; i < layers.Length; ++i)
{
Texture2D diffuseTex = layers[i].diffuseTexture;
string texPath = string.Empty;
if (diffuseTex != null)
{
texPath = AssetDatabase.GetAssetPath(diffuseTex);
}
m_splatInfos[i].texturePath = texPath;
m_splatInfos[i].sizeX = layers[i].tileSize.x;
}
然後就是編寫自己的地形shader,然後用這個tileSize了。
關於地形的shader,還有大地形的處理,我會單獨抽出巨大篇幅來說明,這裏只是簡單的介紹titleSize的使用。
右圖是unity原始的地形,左圖是我們分隔之後的地形mesh,這裏分隔單位是一塊128x128的,地形是640x640,所以是分割成爲5x5=25個塊。
然後我們的shader是這樣的:
Shader "Unlit/TerrainShader"
{
Properties
{
_SplatTex0("_SplatTex0", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
};
struct v2f
{
float4 vertex : SV_POSITION;
float4 worldPosition:TEXCOORD2;
};
sampler2D _SplatTex0;
float range;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.worldPosition = mul(unity_ObjectToWorld, v.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
float2 uv0 = i.worldPosition.xz * (1.0f / 320);
return tex2D(_SplatTex0, uv0);
}
ENDCG
}
}
}
這行代碼:
float2 uv0 = i.worldPosition.xz * (1.0f / 320);
是注意了是地板磚大小的導數,變換uv。
上面基本沒用問題了,但是,但是,如果我們移動了整體的mesh,如下:
可以看到,這個左圖的mesh,人物頭像偏移了,這是爲啥呢?因爲我們使用的是頂點的世界座標進行採樣貼圖的。
而我們原始地形是放在零點位置:
而我們的導出的mesh,我們整體移動到一個地方,所以此時uv會有偏移,採樣自然會偏移。有什麼辦法可以正確解決呢?
答案是移動地板磚大小的整數倍,如下:
這樣就正確了。
我們也可以更改貼圖的offset來實現,但是這裏取了討巧的方法。
到此結束了嘍,我們下篇博客見。