title: How to achieve normal/bump map on surface shader (Unity C#)?
body: <p>I have problems with the following CG surface shader. My goal is to have a NORMAL MAP used on the terrain the shader belongs to. When I apply the shader it doesn't throw any errors, but my terrain becomes black instead of having it's Main Texture and I cannot see any Normal Map effect on it. (check images attached). My question is: <strong>How can I add a normal map on my custom (terrain) shader?</strong></p>
  
  <pre><code>Shader "Custom/Terrain" {
  Properties {
  // Zexture und Scale-Slot im Material erzeugen
      testTexture("Texture", 2D) = "white"{}
      testScale("Scale", Float) = 1
      _NormalMap ("Normal Map", 2D) = "bump" {}
  }
  SubShader {
      Tags { "RenderType"="Opaque" }
      LOD 200
  
      // SHADER-Language = CG 
  
      CGPROGRAM
      // 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
  
      const static int maxLayerCount = 8; // Max Amount of colors the terrain can have
      const static float epsilon = 1E-4; 
  
      int layerCount; 
      float3 baseColours[maxLayerCount]; 
      float baseStartHeights[maxLayerCount]; // ZONES FOR COLORS OF TERRAIN
      float baseBlends[maxLayerCount]; // BLENDS FoR COLORS/TEXTUREN
      float baseColourStrength[maxLayerCount];
      float baseTextureScales[maxLayerCount]; // Texture size
      float minHeight; //min. Hight of Map
      float maxHeight; //max. Hight of Map
  
      sampler2D testTexture; // Textur Slot
      float testScale; // Scale of the texture
  
      sampler2D _NormalMap;
  
      UNITY_DECLARE_TEX2DARRAY(baseTextures); // Texture-Array from TextureData(another Script) definieren
  
      struct Input {
          float3 worldPos; // Position on Map
          float3 worldNormal; // Normales of Map 
          float2 uv_Diffuse;
          INTERNAL_DATA
      };
  
  
      float inverseLerp(float a, float b, float value) // a = min.value, b = max.value, value = surrent value
      {  
         return saturate((value - a)/(b-a));
      }
  
      // --&gt; TRIPLANAR MAPPING
      float3 triplanar (float3 worldPos, float scale, float3 blendAxes, int textureIndex)
      {
          float3 scaledWorldPos = worldPos/ scale;
  
          float3 xProjection = UNITY_SAMPLE_TEX2DARRAY(baseTextures, float3(scaledWorldPos.y,scaledWorldPos.z, textureIndex)) * blendAxes.x; 
          float3 yProjection = UNITY_SAMPLE_TEX2DARRAY(baseTextures, float3(scaledWorldPos.x,scaledWorldPos.z, textureIndex)) * blendAxes.y; 
          float3 zProjection = UNITY_SAMPLE_TEX2DARRAY(baseTextures, float3(scaledWorldPos.x,scaledWorldPos.y, textureIndex)) * blendAxes.z; 
          return xProjection + yProjection + zProjection; // Mix textures
      }
  
      // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
      // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
      // #pragma instancing_options assumeuniformscaling
      UNITY_INSTANCING_CBUFFER_START(Props)
          // put more per-instance properties here
      UNITY_INSTANCING_CBUFFER_END
  
  
      void surf (Input IN, inout SurfaceOutputStandard o) {
  
  
      float heightPercent = inverseLerp(minHeight, maxHeight, IN.worldPos.y);
  
      float3 blendAxes = abs(IN.worldNormal); 
      blendAxes /= blendAxes.x + blendAxes.y + blendAxes.z;  
  
          for (int i = 0; i &lt; layerCount; i++)
          {
  
              float drawStrenght = inverseLerp(-baseBlends[i]/2 - epsilon, baseBlends[i]/2, heightPercent - baseStartHeights[i]); 
  
              float3 baseColour = baseColours[i] * baseColourStrength[i]; 
              // Textur
              float3 textureColour = triplanar(IN.worldPos, baseTextureScales[i], blendAxes, i) * (1-baseColourStrength[i]);
  
              o.Albedo = o.Albedo * (1 - drawStrenght) + (baseColour + textureColour) * drawStrenght;
              o.Normal = UnpackNormal( tex2D(_NormalMap, IN.uv_Diffuse));
          }
  
      }
      ENDCG
  }
  FallBack "Diffuse"}
  </code></pre>
  
  <p>The image:
  <a href="https://i.stack.imgur.com/9X5Ha.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/9X5Ha.png" alt="enter image description here"></a></p>
  
  <p>The material with texture in Unity Editor:</p>
  
  <p><a href="https://i.stack.imgur.com/TFInE.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/TFInE.png" alt="enter image description here"></a></p>
  
  <p>I am trying hard to understand CG but I also appreciate any help.
  Credits to Sebastian Lague</p>