天天看點

Unity3D動态建立地形網格(二)

上次講了動态生成網格,這次說說怎樣分層顯示紋理。
一般的地形會支援大概4層的紋理,比如草地、岩石之類,然後通過一張遮罩貼圖來區分各自的顯示區域。這裡我做了同樣的事情。我寫了一個shader,支援4層貼圖的顯示。先來看看效果,最後貼上shader源碼:
           
Unity3D動态建立地形網格(二)

這是一張遮罩圖檔

Unity3D動态建立地形網格(二)

導入unity自帶的地形資源,裡面有不同地形紋理的貼圖,使用我這個shader,然後設定前兩個通道和遮罩通道

Unity3D動态建立地形網格(二)

把材質賦予給一個面片,會出現這樣的效果。

這就是2個通道的融合了。紋理通過拾取遮罩圖檔不同的顔色值,來顯示不同的通道混合,最終顯示出來。

這裡對應四個紋理通道,我分别用到了圖檔的RGBA四個值來控制。是以我們可以做一個這樣的試驗,做一張黑色背景的圖檔,前面三個數字1、2、4分别用紅綠藍三種顔色,最後右下角在透明通道寫一個白色的4。

Unity3D動态建立地形網格(二)

指定紋理和遮罩:

Unity3D動态建立地形網格(二)
Unity3D動态建立地形網格(二)

最後會看到這樣的效果。

最後我們結合第一節的生成地形網格,做一個效果測試:

Unity3D動态建立地形網格(二)

用ps随便畫一張高度圖,或者你用其他三維軟體生成也行

Unity3D動态建立地形網格(二)

用上一節的腳本,生成了這樣一個地形

Unity3D動态建立地形網格(二)

然後根據地形畫出了一張遮罩圖檔,指定在遮罩的通道

Unity3D動态建立地形網格(二)

這時候可以看到地形的效果是這樣的

Unity3D動态建立地形網格(二)

再改變一下各個通道的平鋪重複次數

Unity3D動态建立地形網格(二)

一個地形的效果就出來了。

這裡由于是使用RGBA四個通道來控制,是以限定最多隻能用4個不同的紋理。其實這個是可以自己擴充的,也可以把顔色分成不同的範圍,然後逐個範圍來指定對應的紋理。這個就自由發揮了。不過我覺得4層紋理應該也夠用了。

下面是shader的源碼:

Shader “Custom/MyTerrainShader” {

Properties {

_MainTex (“Base (RGB)”, 2D) = “white” {}

_SecondTex(“Second (RGB)”,2D) = “white”{}

_ThirdTex(“ThirdTex (RGB)”,2D) = “white”{}

_FourthTex(“FourthTex (RGB)”,2D) = “white”{}

_Mask(“Mask(RG)”,2D) = “white”{}

//_Color(“Color”,Color) = (1,1,1,1)

}

SubShader {

Tags { “RenderType”=”Opaque” }

LOD 200

CGPROGRAM
    #pragma surface surf Lambert
    sampler2D _MainTex;
    sampler2D _SecondTex;
    sampler2D _ThirdTex;
    sampler2D _FourthTex;
    sampler2D _Mask;
    struct Input {
        float2 uv_MainTex;
        float2 uv_SecondTex;
        float2 uv_ThirdTex;
        float2 uv_FourthTex;
        float2 uv_Mask;
    };
    void surf (Input IN, inout SurfaceOutput o) {
        half4 c1 = tex2D (_MainTex, IN.uv_MainTex);
        half4 c2 = tex2D (_SecondTex, IN.uv_SecondTex);
        half4 c3 = tex2D (_ThirdTex, IN.uv_ThirdTex);
        half4 c4 = tex2D (_FourthTex, IN.uv_FourthTex);
        half4 cm = tex2D (_Mask, IN.uv_Mask);
        o.Albedo = c1.rgb*cm.r+c2.rgb*cm.g+c3.rgb*cm.b+c4.rgb*cm.a;
        o.Alpha = c1.a;
    }
    ENDCG
} 
FallBack "Diffuse"
           

}