title: Normal Mapping on Texture Splatted Terrain
body: <p>I have developed a terrain generation system with texture splatting in Three.js and I am having trouble applying normal mapping to it. How should I go about it? This code is fully functional as of now.</p>
  
  <p>I have looked at some tutorials of WebGL shading and normal mapping and I could not find one to accurately fit my code.</p>
  
  <pre><code>FRAGMENT_SHADER: `
      uniform sampler2D albedoA;
      uniform sampler2D albedoB;
      uniform sampler2D albedoC;
      uniform sampler2D albedoD;
      uniform sampler2D albedoE;
  
      uniform sampler2D normalA;
      uniform sampler2D normalB;
      uniform sampler2D normalC;
      uniform sampler2D normalD;
      uniform sampler2D normalE;
  
      uniform float repeatScale;
  
      uniform vec3 sunPosition;
  
      varying vec2 vUV;
      varying float vAmount;
  
      varying vec3 vNormal;
      varying vec3 vWorldPosition;
  
      void main()
      {
          vec3 diffA = (smoothstep(0.01, 0.25, vAmount) - smoothstep(0.25, 0.35, vAmount)) * texture2D(albedoA, vUV * repeatScale).rgb;
          vec3 diffB = (smoothstep(0.24, 0.27, vAmount) - smoothstep(0.27, 0.37, vAmount)) * texture2D(albedoB, vUV * repeatScale).rgb;
          vec3 diffC = (smoothstep(0.28, 0.32, vAmount) - smoothstep(0.32, 0.42, vAmount)) * texture2D(albedoC, vUV * repeatScale).rgb;
          vec3 diffD = (smoothstep(0.30, 0.60, vAmount) - smoothstep(0.40, 0.70, vAmount)) * texture2D(albedoD, vUV * repeatScale).rgb;
          vec3 diffE = (smoothstep(0.50, 0.85, vAmount))                                   * texture2D(albedoE, vUV * repeatScale).rgb;
          vec3 albedoVector = diffA + diffB + diffC + diffD + diffE;
  
          vec3 normA = (smoothstep(0.01, 0.25, vAmount) - smoothstep(0.25, 0.35, vAmount)) * texture2D(normalA, vUV * repeatScale).rgb;
          vec3 normB = (smoothstep(0.24, 0.27, vAmount) - smoothstep(0.27, 0.37, vAmount)) * texture2D(normalB, vUV * repeatScale).rgb;
          vec3 normC = (smoothstep(0.28, 0.32, vAmount) - smoothstep(0.32, 0.42, vAmount)) * texture2D(normalC, vUV * repeatScale).rgb;
          vec3 normD = (smoothstep(0.30, 0.60, vAmount) - smoothstep(0.40, 0.70, vAmount)) * texture2D(normalD, vUV * repeatScale).rgb;
          vec3 normE = (smoothstep(0.50, 0.85, vAmount))                                   * texture2D(normalE, vUV * repeatScale).rgb;
          vec3 normalVector = normA + normB + normC + normD + normE;
  
          float diffuseFloat = max(dot(normalize(sunPosition - vWorldPosition), vNormal), 0.0);
          if (diffuseFloat &lt; 0.25) { diffuseFloat = 0.25; }
          if (diffuseFloat &gt; 1.0) { diffuseFloat = 1.0; }
  
          gl_FragColor = vec4(diffuseFloat * albedoVector, 1.0);
      }
  `,
  VERTEX_SHADER: `
      uniform sampler2D heightTexture;
  
      varying vec2 vUV;
      varying float vAmount;
  
      varying vec3 vNormal;
      varying vec3 vWorldPosition;
  
      void main()
      {
          vUV = uv;
          vAmount = texture2D(heightTexture, uv).r;
  
          vec4 worldPosition = modelViewMatrix * vec4(position, 1.0);
  
          vWorldPosition = worldPosition.xyz;
          vNormal = vec3(normal);
  
          gl_Position = projectionMatrix * worldPosition;
      }
  `
  </code></pre>
  
  <p>I am using the THREE.ShaderMaterial and as of now the code splats the textures and accounts for lighting and shadows, but not the normal maps.</p>