Problem with Normal Maps

Hey,

So I’m working on a procedural terrain and Standard Shader simply doesn’t work for me. Instead I have created my own shader (evaluated from standard surface shader) that doesn’t require UV and It works great with textures, however, when I try to add normal maps (more accurately I add “o.Normal = stuff”) everything breaks (e.g. object becomes perfect black) so how do I add normal map support?

Here is shader in the albedo state:

   Shader "Custom/Terrain" {
    	Properties {
    		_TopTexture ("Top Texture", 2D) = "white" {}
    		_TopNormal ("Top NormalMap", 2D) = "bump" {}
    		_TopTexScale ("Top Texture Scale", float) = 0
    		_Glossiness ("Smoothness", Range(0,1)) = 0.0
    		_Metallic ("Metallic", Range(0,1)) = 0.0
    	}
    	SubShader {
    		Tags { "RenderType"="Opaque" }
    		LOD 200
    		
    		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
    
    		struct Input {
    			float3 worldPos;
    			float3 worldNormal; INTERNAL_DATA
    		};
    
    		half _Glossiness;
    		half _Metallic;
    		float _TopTexScale;
    		sampler2D _TopTexture;
    		sampler2D _TopNormal;
    
    		void surf (Input IN, inout SurfaceOutputStandard o) {
    
    			float3 scaledWorldPos = IN.worldPos / _TopTexScale;
    			float3 blendAxes = abs(IN.worldNormal);
    			blendAxes /= blendAxes.x + blendAxes.y + blendAxes.z;
    			float3 xProjection = tex2D(_TopTexture, scaledWorldPos.yz) * blendAxes.x;
    			float3 yProjection = tex2D(_TopTexture, scaledWorldPos.xz) * blendAxes.y;
    			float3 zProjection = tex2D(_TopTexture, scaledWorldPos.xy) * blendAxes.z;
    			o.Albedo = xProjection + yProjection + zProjection;
    
    			o.Metallic = _Metallic;
    			o.Smoothness = _Glossiness;
    		}
    		ENDCG
    	}
    	FallBack "Diffuse"
    }

There are some problems with using triplanar texturing for normal maps, although from memory the shader I created for this works perfectly fine;

Shader "Custom/Triplanar" {
	Properties {
		_Color ("Color", Color) = (1,1,1,1)
		_MainTex ("Albedo (RGB)", 2D) = "white" {}
		_BumpMap ("Normal Map", 2D) = "bump" {}
		_Glossiness ("Smoothness", Range(0,1)) = 0.5
		_Metallic ("Metallic", Range(0,1)) = 0.0
		_Scale ("Scale", Float) = 2.0
	}
	SubShader {
		Tags { "RenderType"="Opaque" }
		LOD 200
		
		CGPROGRAM
		// Physically based Standard lighting model, and enable shadows on all light types
		#pragma surface surf Standard fullforwardshadows vertex:vert

		// Use shader model 3.0 target, to get nicer looking lighting
		#pragma target 3.0

		sampler2D _MainTex;
		sampler2D _BumpMap;

		struct Input {
			float3 coords;
			float3 normal;
		};

		half _Glossiness;
		half _Metallic;
		half _Scale;
		fixed4 _Color;

		void vert (inout appdata_full v, out Input o) {
			UNITY_INITIALIZE_OUTPUT (Input, o);
			o.coords = mul (unity_ObjectToWorld, v.vertex) * _Scale;
			o.normal = mul ((float3x3)unity_ObjectToWorld, v.normal);
		}

		void surf (Input IN, inout SurfaceOutputStandard o) {
			float3 blend = abs (IN.normal);
			blend /= dot (blend, 1.0);

			fixed4 bx = tex2D (_BumpMap, IN.coords.zy);
			fixed4 bz = tex2D (_BumpMap, IN.coords.xy);
			fixed4 by = tex2D (_BumpMap, IN.coords.xz);
			fixed4 b = bx * blend.x + bz * blend.z + by * blend.y;
			o.Normal = UnpackNormal (b);
			// Albedo comes from a texture tinted by color
			fixed4 cx = tex2D (_MainTex, IN.coords.zy);
			fixed4 cz = tex2D (_MainTex, IN.coords.xy);
			fixed4 cy = tex2D (_MainTex, IN.coords.xz);
			fixed4 c = cx * blend.x + cz * blend.z + cy * blend.y;
			o.Albedo = c.rgb;
			// Metallic and smoothness come from slider variables
			o.Metallic = _Metallic;
			o.Smoothness = _Glossiness;
			o.Alpha = c.a;
		}
		ENDCG
	}
	FallBack "Diffuse"
}

I think it’s down to using the default surface shader normal value. From memory you have to pass your own values in order for it to work, because the default values are overwritten when you write to o.Normal.