移動平臺大地圖+水效果

weixin_34185560發表於2018-07-10

這個Shader適用於不斷載入的大世界地圖,因為製作地形的話太大,划動螢幕載入手機會卡


6718063-f8c4cb154ae7a5e8.jpg
地形.jpg

6718063-9c075bfd68f7845d.jpg
地形shader皮膚.jpg

四張紋理+四張法線通過Global來進行混合,+一個大的法線來模擬大的坑窪,支援高光效果,也可擴充套件成高光貼圖,新增水選項,不用的話可以關掉,用mask控制水的範圍

以下是原始碼分享

Shader "Artist/Scene/Terrain Bump Water"
{  
    Properties
    {
        _tile0Control("tile0Control (RGB)", 2D) = "red" {}
        _tile0Normal("tile0Normal", 2D) = "bump" {}
        _tile0Splat0("tile0Splat0 (R)", 2D) = "white" {}
        _tile0Splat1("tile0Splat1 (G)", 2D) = "white" {}
        _tile0Splat2("tile0Splat2 (B)", 2D) = "white" {}
        _tile0Splat3("tile0Splat3 (B)", 2D) = "white" {}
        _tile0Splat0Normal("tile0Splat0Normal (R)", 2D) = "white" {}
        _tile0Splat1Normal("tile0Splat1Normal (G)", 2D) = "white" {}
        _tile0Splat2Normal("tile0Splat2Normal (B)", 2D) = "white" {}
        _tile0Splat3Normal("tile0Splat3Normal (B)", 2D) = "white" {}
        _Specular ("Specular Color", Color) = (1, 1, 1, 1)
        _Gloss ("Gloss", Range(8.0, 256)) = 20
        [Toggle] _UseWater("UseWater", Int) = 0
        _WaterTex("WaterTex", 2D) = "white" {}
        _WaterColor ("Water Color", Color) = (0.0, 0.15, 0.22, 1)
        _WaterSpecColor ("WaterSpecColor", Color) = (0.0, 0.15, 0.22, 1)
        _FrenelColor ("Frenel Color", Color) = (0.0, 0.15, 0.22, 1) 
        _WaterTexMask("WaterTexMask", 2D) = "white" {}
        _Skybox("skybox", Cube)="white"{}
        //_FresnelTex("Fresnel Texture", 2D) = "white" {}
        _Smoothness("Smoothness", Range(1, 30)) = 8
        _Frenel ("Bump Strength", Range(0, 10)) = 0.5
        _BumpDirection ("Bump Direction", Vector)=(0.35,0.35,-0.1,-0.12)
        _BumpTiling ("Bump Tiling", Vector)=(0.25,0.25,0.3,0.3)
        //_SunDir("Light Direction", Vector)=(0,0,0,0)
    }

    SubShader
    {
        Tags { "RenderType"="Opaque" "LightMode" = "ForwardBase" }
        LOD 200
        
        Pass
        {
            CGPROGRAM
            #pragma multi_compile_fwdbase
            #pragma target 2.0
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fog
            #pragma shader_feature _USEWATER
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            #include "AutoLight.cginc"
            struct appdata
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float4 tangent : TANGENT;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float4 dataForNormalMap0 : TEXCOORD0;
                float4 dataForNormalMap1 : TEXCOORD1;
                float4 dataForNormalMap2 : TEXCOORD2;
                half4 uv_tile0ControlSplat0 : TEXCOORD3;
                half4 uv_tile0Splat1Splat1 : TEXCOORD4;
                half2 uv_tile0Splat1Splat2 : TEXCOORD5;
                half4 uv_tile0Splat1Splat3 : TEXCOORD6;
                half2 uv_tile0Normal : TEXCOORD8;
                UNITY_FOG_COORDS(7)
            };

            sampler2D _tile0Control;
            float4 _tile0Control_ST;
            sampler2D _tile0Splat0;
            float4 _tile0Splat0_ST;
            sampler2D _tile0Splat1;
            float4 _tile0Splat1_ST;
            sampler2D _tile0Splat2;
            float4 _tile0Splat2_ST;
            sampler2D _tile0Splat3;
            float4 _tile0Splat3_ST;
            sampler2D _tile0Normal;
            float4 _tile0Normal_ST;
            sampler2D _WaterTex;
            float4 _WaterTex_ST;
            sampler2D _tile0Splat0Normal;
            sampler2D _tile0Splat1Normal;
            sampler2D _tile0Splat2Normal;
            sampler2D _tile0Splat3Normal;
            fixed3 _Specular;
            float _Gloss;
            float _Smoothness;
            float _Frenel;
            fixed3 _WaterColor;
            fixed3 _FrenelColor;
            sampler2D _WaterTexMask;
            fixed3 _WaterSpecColor;
            samplerCUBE _Skybox;
            sampler2D _FresnelTex;
            half4 _BumpDirection;
            half4 _BumpTiling;
            //half4 _SunDir;
            v2f vert(appdata v)
            {
                v2f o;
                UNITY_INITIALIZE_OUTPUT(v2f, o);
                o.vertex = UnityObjectToClipPos(v.vertex);
                float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;  
                half3 wNormal = UnityObjectToWorldNormal(v.normal);
                half3 wTangent = UnityObjectToWorldDir(v.tangent.xyz);
                half3 wBitangent = cross(wNormal, wTangent) * v.tangent.w;
                o.dataForNormalMap0 = float4(wTangent.x, wBitangent.x, wNormal.x, worldPos.x);
                o.dataForNormalMap1 = float4(wTangent.y, wBitangent.y, wNormal.y, worldPos.y);
                o.dataForNormalMap2 = float4(wTangent.z, wBitangent.z, wNormal.z, worldPos.z);
                o.uv_tile0ControlSplat0.xy = TRANSFORM_TEX(v.uv, _tile0Control);
                o.uv_tile0ControlSplat0.zw = TRANSFORM_TEX(v.uv, _tile0Splat0);
                o.uv_tile0Splat1Splat1.xy = TRANSFORM_TEX(v.uv, _tile0Splat1);
                o.uv_tile0Splat1Splat1.zw = TRANSFORM_TEX(v.uv, _tile0Splat2);
                o.uv_tile0Splat1Splat2.xy = TRANSFORM_TEX(v.uv, _tile0Splat3);
                o.uv_tile0Splat1Splat3.xyzw = (worldPos.xzxz + _Time.yyyy * _BumpDirection.xyzw) * _BumpTiling.xyzw;
                o.uv_tile0Normal = TRANSFORM_TEX(v.uv, _tile0Normal);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            fixed4 frag(v2f i) : SV_Target
            {
                fixed4 c = tex2D(_tile0Control, i.uv_tile0ControlSplat0.xy);
                fixed4 c0 = tex2D(_tile0Splat0, i.uv_tile0ControlSplat0.zw);
                fixed4 c1 = tex2D(_tile0Splat1, i.uv_tile0Splat1Splat1.xy);
                fixed4 c2 = tex2D(_tile0Splat2, i.uv_tile0Splat1Splat1.zw);
                fixed4 c3 = tex2D(_tile0Splat3, i.uv_tile0Splat1Splat2.xy);
                fixed4 c5 = c0 * c.r + c1 * c.g + c2 * c.b + c3 * c.a;
                half4 n0 = tex2D(_tile0Splat0Normal, i.uv_tile0ControlSplat0.zw);
                half4 n1 = tex2D(_tile0Splat1Normal, i.uv_tile0Splat1Splat1.xy);
                half4 n2 = tex2D(_tile0Splat2Normal, i.uv_tile0Splat1Splat1.zw);
                half4 n3 = tex2D(_tile0Splat3Normal, i.uv_tile0Splat1Splat2.xy);
                half4 n5 = n0 * c.r + n1 * c.g + n2 * c.b + n3 * c.a;
                c5/= c.r+c.g+c.b+c.a;
                half3 n6 = UnpackNormal(n5);
                half3 tnormal = UnpackNormal(tex2D(_tile0Normal, i.uv_tile0Normal));
                half3 worldNormal;
                worldNormal.x = dot(i.dataForNormalMap0.xyz, n6.x);
                worldNormal.y = dot(i.dataForNormalMap1.xyz, n6.y);
                worldNormal.z = dot(i.dataForNormalMap2.xyz, n6.z);
                worldNormal = normalize(worldNormal);
                half3 lightDir = normalize(_WorldSpaceLightPos0.xyz);//平行光座標點
                half3 viewDir = normalize(UnityWorldSpaceViewDir(half3(i.dataForNormalMap0.w,i.dataForNormalMap1.w,i.dataForNormalMap2.w)));
                //half3 Ambient  = UNITY_LIGHTMODEL_AMBIENT.rgb * c5;   
                half3 Ambient = ShadeSH9(half4(tnormal, 1.0)) * c5;
                half nl = max(0, dot(worldNormal,lightDir ));
                half nnl = max(0, dot(tnormal,lightDir ));
                c5.rgb *= (nl + nnl)*_LightColor0.rgb;
                //c5 *= nl;
                half3 halfDir = normalize(lightDir + viewDir);
                half3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate( dot(worldNormal, halfDir)), _Gloss);  

                #ifdef _USEWATER
                half2 offset = UnpackNormal(tex2D(_WaterTex, i.uv_tile0Splat1Splat3.xy)) + UnpackNormal(tex2D(_WaterTex, i.uv_tile0Splat1Splat3.zw)) *0.5;//雙水紋理取樣偏移速度不一
                float3 worldNormal1 = float3(0,0,0);
                worldNormal1.xz = offset.xy * _Frenel;
                worldNormal1.y = 1;
                half3 normalDir = normalize(worldNormal1);
                half2 fresnelUV = half2( saturate(dot(viewDir, normalDir)), 0.5);
                half4 WaterTexMask = tex2D(_WaterTexMask, i.uv_tile0ControlSplat0.xy);
                
                //half fresnel1 = tex2D(_FresnelTex, fresnelUV).r;
                half fresnel1 = WaterTexMask.g;
                if(IsGammaSpace())
                {
                    fresnel1 = pow(fresnel1, 2.2);
                }
                half3 specLight = _LightColor0.rgb * _WaterSpecColor;
                half3 hd = normalize(lightDir+viewDir);
                half d = pow(max(0,(dot(normalDir, hd  ))), _Smoothness);
                half3 specColor = specLight * d;
                
                half3 reflUV = reflect( viewDir, normalDir);
                half3 reflectColor1 = texCUBE(_Skybox, reflUV);
                //half4 rgbm = UNITY_SAMPLE_TEXCUBE_LOD(unity_SpecCube0, reflUV, 0);
                //half3 reflectColor1 = DecodeHDR(rgbm, unity_SpecCube0_HDR);
                half3 finalreflect = lerp(_FrenelColor, reflectColor1, fresnel1);       
                //UNITY_APPLY_FOG(i.fogCoord, c5.rgb); 
                return fixed4((c5.rgb + Ambient + specular )*(1-WaterTexMask.r)+(finalreflect + specColor ) * _WaterColor * WaterTexMask.r, 1.0);
                //return fixed4(c5.rgb + Ambient + specular, 1.0);
                //return fixed4(finalreflect,1.0);
                #endif
                 
                //UNITY_APPLY_FOG(i.fogCoord, c5.rgb); 
                return fixed4(c5.rgb , 1.0);
                //return fixed4(1,1,1, 1.0); 
                }
            ENDCG
        }
    }

    CustomEditor "TerrainShaderGUI"
}
using System;
using UnityEngine;

namespace UnityEditor
{
    internal class TerrainShaderGUI : ShaderGUI
    {
        private static class Styles
        {
            public static GUIContent tile0Splat0Text = new GUIContent("tile0Splat0", "");
            public static GUIContent tile0Splat1Text = new GUIContent("tile0Splat1", "");
            public static GUIContent tile0Splat2Text = new GUIContent("tile0Splat2", "");
            public static GUIContent tile0Splat3Text = new GUIContent("tile0Splat3", "");
            public static GUIContent tile0Splat0NormalText = new GUIContent("tile0Splat0Normal", "");
            public static GUIContent tile0Splat1NormalText = new GUIContent("tile0Splat1Normal", "");
            public static GUIContent tile0Splat2NormalText = new GUIContent("tile0Splat2Normal", "");
            public static GUIContent tile0Splat3NormalText = new GUIContent("tile0Splat3Normal", "");
            public static GUIContent tile0NormalText = new GUIContent("Global Normal", "Global Normal");
            public static GUIContent tile0ControlText = new GUIContent("Global Control", "Global Control");
            public static GUIContent specularColorText = new GUIContent("Specular Color", "");
            public static GUIContent glossText = new GUIContent("Gloss", "");
            public static GUIContent waterTexText = new GUIContent("WaterTex", "");
            public static GUIContent waterColorText = new GUIContent("Water Color", "");
            public static GUIContent waterSpecColorText = new GUIContent("Water Spec Color", "");
            public static GUIContent frenelColorText = new GUIContent("Frenel Color Color", "");
            public static GUIContent waterTexMaskText = new GUIContent("Water Tex Mask", "");
            public static GUIContent skyboxText = new GUIContent("Skybox", "");
            public static GUIContent fresnelTextureText = new GUIContent("Fresnel Texture", "");
            public static GUIContent smoothnessText = new GUIContent("Smoothness", "");
            public static GUIContent bumpStrengthText = new GUIContent("Bump Strength", "");
            public static GUIContent bumpDirectionText = new GUIContent("BumpDirection", "");
            public static GUIContent bumpTilingText = new GUIContent("Bump Tiling", "");
            public static GUIContent lightDirectionText = new GUIContent("Light Direction", "");
        }
        MaterialProperty tile0Splat0 = null;
        MaterialProperty tile0Splat1 = null;
        MaterialProperty tile0Splat2 = null;
        MaterialProperty tile0Splat3 = null;
        MaterialProperty tile0Splat0Normal = null;
        MaterialProperty tile0Splat1Normal = null;
        MaterialProperty tile0Splat2Normal = null;
        MaterialProperty tile0Splat3Normal = null;
        MaterialProperty tile0Normal = null;
        MaterialProperty tile0Control = null;
        MaterialProperty specularColor = null;
        MaterialProperty gloss = null;
        MaterialProperty waterTex = null;
        MaterialProperty waterColor = null;
        MaterialProperty waterSpecColor = null;
        MaterialProperty frenelColor = null;
        MaterialProperty waterTexMask = null;
        MaterialProperty skybox = null;
        MaterialProperty fresnelTexture = null;
        MaterialProperty smoothness = null;
        MaterialProperty bumpStrength = null;
        MaterialProperty bumpDirection = null;
        MaterialProperty bumpTiling = null;
        MaterialProperty lightDirection = null;
        MaterialProperty useWater = null;
        MaterialEditor m_MaterialEditor;
        
        //private const float kMaxfp16 = 65536f; 
        //ColorPickerHDRConfig m_ColorPickerHDRConfig = new ColorPickerHDRConfig(0f, kMaxfp16, 1 / kMaxfp16, 3f);
        //bool m_FirstTimeApply = true;
        public void FindProperties(MaterialProperty[] props)
        {
            tile0Splat0 = FindProperty("_tile0Splat0", props);
            tile0Splat1 = FindProperty("_tile0Splat1", props);
            tile0Splat2 = FindProperty("_tile0Splat2", props);
            tile0Splat3 = FindProperty("_tile0Splat3", props);
            tile0Splat0Normal = FindProperty("_tile0Splat0Normal", props);
            tile0Splat1Normal = FindProperty("_tile0Splat1Normal", props);
            tile0Splat2Normal = FindProperty("_tile0Splat2Normal", props);
            tile0Splat3Normal = FindProperty("_tile0Splat3Normal", props);
            tile0Normal = FindProperty("_tile0Normal", props);
            tile0Control = FindProperty("_tile0Control", props);
            specularColor = FindProperty("_Specular", props);
            gloss = FindProperty("_Gloss", props);
            useWater = ShaderGUI.FindProperty("_UseWater", props);
            waterTex = FindProperty("_WaterTex", props);
            waterColor = FindProperty("_WaterColor", props);
            waterSpecColor = FindProperty("_WaterSpecColor", props);
            frenelColor = FindProperty("_FrenelColor", props, false);
            waterTexMask = FindProperty("_WaterTexMask", props, false);
            skybox = FindProperty("_Skybox", props, false);
            fresnelTexture = FindProperty("_FresnelTex", props, false);
            smoothness = FindProperty("_Smoothness", props, false);
            bumpStrength = FindProperty("_Frenel", props, false);
            bumpDirection = FindProperty("_BumpDirection", props, false);
            bumpTiling = FindProperty("_BumpTiling", props, false);
            lightDirection = FindProperty("_SunDir", props, false);
           }

        public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)
        {
            FindProperties(props); 
            m_MaterialEditor = materialEditor;
            Material material = materialEditor.target as Material;       
            ShaderPropertiesGUI(material);
        }

        public void ShaderPropertiesGUI(Material material)
        {
            EditorGUIUtility.labelWidth = 0f;
                      
            EditorGUI.BeginChangeCheck();
            {                                             
                m_MaterialEditor.TexturePropertySingleLine(Styles.tile0Splat0Text, tile0Splat0);
                m_MaterialEditor.TexturePropertySingleLine(Styles.tile0Splat0NormalText, tile0Splat0Normal);
                m_MaterialEditor.TextureScaleOffsetProperty(tile0Splat0);
                m_MaterialEditor.TexturePropertySingleLine(Styles.tile0Splat1Text, tile0Splat1);
                m_MaterialEditor.TexturePropertySingleLine(Styles.tile0Splat1NormalText, tile0Splat1Normal);
                m_MaterialEditor.TextureScaleOffsetProperty(tile0Splat1);
                m_MaterialEditor.TexturePropertySingleLine(Styles.tile0Splat2Text, tile0Splat2);
                m_MaterialEditor.TexturePropertySingleLine(Styles.tile0Splat2NormalText, tile0Splat2Normal);
                m_MaterialEditor.TextureScaleOffsetProperty(tile0Splat2);
                m_MaterialEditor.TexturePropertySingleLine(Styles.tile0Splat3Text, tile0Splat3);
                m_MaterialEditor.TexturePropertySingleLine(Styles.tile0Splat3NormalText, tile0Splat3Normal);
                m_MaterialEditor.TextureScaleOffsetProperty(tile0Splat3);
                m_MaterialEditor.TexturePropertySingleLine(Styles.tile0NormalText, tile0Normal);
                m_MaterialEditor.TextureScaleOffsetProperty(tile0Normal);
                m_MaterialEditor.TexturePropertySingleLine(Styles.tile0ControlText, tile0Control);
                m_MaterialEditor.ColorProperty(specularColor, Styles.specularColorText.text);
                m_MaterialEditor.RangeProperty(gloss, Styles.glossText.text);
                EditorGUILayout.Space();
                m_MaterialEditor.ShaderProperty(useWater, useWater.displayName);          
                EditorGUILayout.Space();
                DoWater(material);
                EditorGUI.BeginChangeCheck();                  
            }                   
        }
      
        void DoWater(Material material)
        {
            if (useWater.floatValue == 1)
            {
                m_MaterialEditor.TexturePropertySingleLine(Styles.waterTexText, waterTex);
                m_MaterialEditor.ColorProperty(waterColor, Styles.waterColorText.text);
                m_MaterialEditor.ColorProperty(waterSpecColor, Styles.waterSpecColorText.text);
                m_MaterialEditor.ColorProperty(frenelColor, Styles.frenelColorText.text);
                m_MaterialEditor.TexturePropertySingleLine(Styles.waterTexMaskText, waterTexMask);
                m_MaterialEditor.TexturePropertySingleLine(Styles.skyboxText, skybox);
                m_MaterialEditor.TexturePropertySingleLine(Styles.fresnelTextureText, fresnelTexture);
                m_MaterialEditor.RangeProperty(smoothness, Styles.smoothnessText.text);
                m_MaterialEditor.RangeProperty(bumpStrength, Styles.bumpStrengthText.text);
                m_MaterialEditor.VectorProperty(bumpDirection, Styles.bumpDirectionText.text);
                m_MaterialEditor.VectorProperty(bumpTiling, Styles.bumpTilingText.text);
                m_MaterialEditor.VectorProperty(lightDirection, Styles.lightDirectionText.text);
                material.EnableKeyword("_USEWATER");
            }
            else
            {
                material.DisableKeyword("_USEWATER");
            }
        } 
           }
}



相關文章