分割爲mesh之後的地形shader編寫——1

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來實現,但是這裏取了討巧的方法。
到此結束了嘍,我們下篇博客見。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章