I've been developing a custom terrain shader in Unity. And I've been having problems with my normal maps. Even after hours of fiddling I still haven't fixed it yet. There are 2 noticeable issues: 1. Normal maps don't appear on vertices whose normal points towards the X axis 2. Normals just don't appear "correct", as in they're faint, and don't look as good as standard terrain normals.

The following pictures should help illustrate my point: Standard Shader Unity's standard terrain shader (Stretched normals but they work perfectly) My Shader My shader (Washed out normals, and normals on the x axis are virtually non-existent)

I have stripped my code down to the bare essentials and I still get this result.

My code:

     // Set by terrain engine
        [HideInInspector] _Control ("Control (RGB)", 2D) = "red" {}
        //[HideInInspector] _Splat3 ("Layer 3 (A)", 2D) = "white" {}
        [HideInInspector] _Splat2 ("Layer 2 (B)", 2D) = "white" {}
        [HideInInspector] _Splat1 ("Layer 1 (G)", 2D) = "white" {}
        [HideInInspector] _Splat0 ("Layer 0 (R)", 2D) = "white" {}
        //[HideInInspector] _Normal3 ("Normal 3 (A)", 2D) = "bump" {}
        [HideInInspector] _Normal2 ("Normal 2 (B)", 2D) = "bump" {}
        [HideInInspector] _Normal1 ("Normal 1 (G)", 2D) = "bump" {}
        [HideInInspector] _Normal0 ("Normal 0 (R)", 2D) = "bump" {}
        [HideInInspector] [Gamma] _Metallic0 ("Metallic 0", Range(0.0, 1.0)) = 0.0  
        [HideInInspector] [Gamma] _Metallic1 ("Metallic 1", Range(0.0, 1.0)) = 0.0  
        [HideInInspector] [Gamma] _Metallic2 ("Metallic 2", Range(0.0, 1.0)) = 0.0  
        //[HideInInspector] [Gamma] _Metallic3 ("Metallic 3", Range(0.0, 1.0)) = 0.0
        [HideInInspector] _Smoothness0 ("Smoothness 0", Range(0.0, 1.0)) = 1.0  
        [HideInInspector] _Smoothness1 ("Smoothness 1", Range(0.0, 1.0)) = 1.0  
        [HideInInspector] _Smoothness2 ("Smoothness 2", Range(0.0, 1.0)) = 1.0  
        //[HideInInspector] _Smoothness3 ("Smoothness 3", Range(0.0, 1.0)) = 1.0

        // used in fallback on old cards & base map
        [HideInInspector] _MainTex ("BaseMap (RGB)", 2D) = "white" {}
        [HideInInspector] _Color ("Main Color", Color) = (1,1,1,1)

    SubShader {
        Tags {
            "SplatCount" = "3"
            "Queue" = "Geometry-100"
            "RenderType" = "Opaque"

        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma surface surf Standard fullforwardshadows
        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0
        #pragma multi_compile_fog
        #pragma exclude_renderers gles
        #include "UnityPBSLighting.cginc"
        #include "Tom's Terrain-Helper.cginc"

        // Access the Shaderlab properties
        half _depthThresh;

        uniform sampler2D _Control;

        sampler2D _Splat0,_Splat1,_Splat2;
        //float4 _Splat0_ST;
        //float4 _Splat1_ST;
        //float4 _Splat2_ST;
        sampler2D _Normal0,_Normal1,_Normal2;

        half _Metallic0;
        half _Metallic1;
        half _Metallic2;
        //half _Metallic3;

        half _Smoothness0;
        half _Smoothness1;
        half _Smoothness2;
        //half _Smoothness3;

        half _Height0;
        half _Height1;
        half _Height2;

        float _TextureScale;
        half _NormalStrengh;
        float _TriplanarNormals;

        struct Input {
            float3 worldPos;
            float3 worldNormal;
            float2 uv_MainTex : TEXCOORD0;
            float2 uv_Control : TEXCOORD1;
            float2 uv_Splat0 : TEXCOORD2;
            float2 uv_Splat1 : TEXCOORD3;
            float2 uv_Splat2 : TEXCOORD4;
            //float2 uv_Splat3 : TEXCOORD5;

            //float2 uv_Normal0 : TEXCOORD6;
            //float2 uv_Normal1 : TEXCOORD7;
            //float2 uv_Normal2 : TEXCOORD8;
            //float2 uv_Normal3 : TEXCOORD9;

        void SplatmapVert(inout appdata_full v, out Input data)
            UNITY_INITIALIZE_OUTPUT(Input, data);
            float4 pos = mul (UNITY_MATRIX_MVP, v.vertex);
            //UNITY_TRANSFER_FOG(data, pos);

            v.tangent.xyz = cross(v.normal, float3(0,0,1));
            v.tangent.w = -1;

        half _Glossiness;
        half _Metallic;
        fixed4 _Color;

        void surf (Input IN, inout SurfaceOutputStandard o) {
            fixed4 splatControl = tex2D(_Control, IN.uv_Control);

            fixed4 nrm = 0.0f;
            //nrm += splatControl.r * normal0;
            //nrm += splatControl.g * normal1;
            //nrm += splatControl.b * normal2;
            nrm += splatControl.r * tex2D(_Normal0, IN.uv_Splat0);
            nrm += splatControl.g * tex2D(_Normal1, IN.uv_Splat1);
            nrm += splatControl.b * tex2D(_Normal2, IN.uv_Splat2);
            //nrm /= b1 + b2 + b3;

            nrm.g = nrm.r;

            fixed3 finalNormal = UnpackNormal(nrm);

            //Final output
            o.Normal = finalNormal;
            o.Albedo = 1;
            o.Alpha = 1;
            o.Smoothness =dot(tex2D(_Control, IN.uv_Control), half3(_Smoothness0, _Smoothness1, _Smoothness2));
            o.Metallic = dot(tex2D(_Control, IN.uv_Control), half3(_Metallic0, _Metallic1, _Metallic2));
    Dependency "AddPassShader" = "Hidden/TerrainEngine/Splatmap/Standard-AddPass"
    Dependency "BaseMapShader" = "Hidden/TerrainEngine/Splatmap/Standard-Base"

    Fallback "Nature/Terrain/Diffuse"

You might notice that a lot of this code is very similar to unity's code. And even though this code is so similar it still behaves differently.

So my question is; what am I missing?

Thanks in advance.

Some other images to help understand my problem: Standard shader My Shader


It turns out that I had forgotten to declare my vertex shader in the pragma.

This line:

 #pragma surface surf Standard fullforwardshadows

Becomes, this line:

#pragma surface surf Standard vertex:SplatmapVert fullforwardshadows

Note the addition of:


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.