Shader: blending between normals not working

Hi,

in the following shader i try to tone down the bump for the physically based lightning, so the first pass (the refracted “background”) is better visible.

Shader "Custom/WaterRefl" {
	Properties {
		_BumpMap ("Normalmap", 2D) = "bump" {}
		_Refraction  ("Refraction", range (0, 128)) = 10
		_Reflection  ("Reflection", range (0, 1)) = 0.5
		_Glossiness ("Smoothness", Range(0, 1)) = 0.5
		_Metallic ("Metallic", Range(0, 1)) = 0.0
	}
	SubShader {
		Tags { "RenderType"="Opaque" }
		LOD 200
		
		GrabPass { }
		
		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

		sampler2D _BumpMap;
		float _Refraction;
		float _Reflection;
		half _Glossiness;
		half _Metallic;
		sampler2D _GrabTexture;
		float4 _GrabTexture_TexelSize;

		struct Input {
			float2 uv_BumpMap;
			float4 screenPos;
			float3 worldRefl;
		    INTERNAL_DATA
		};

		void surf (Input IN, inout SurfaceOutputStandard o) {
			half3 bump = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
			float2 offset = bump * _Refraction * _GrabTexture_TexelSize.xy;
		    IN.screenPos.xy += offset * IN.screenPos.z;
		    float3 refractColor = tex2Dproj( _GrabTexture, IN.screenPos);
    		
    		half3 origNorm = o.Normal;
    		o.Normal = origNorm * (1-_Reflection) + bump * _Reflection; // this does not work as expected
			o.Albedo = refractColor;
			o.Metallic = _Metallic;
			o.Smoothness = _Glossiness;
		}
		ENDCG
	} 
	FallBack "Diffuse"
}

The problem is this: o.Normal = origNorm * (1-_Reflection) + bump * _Reflection;
It does not work as expected (with _Reflection, I want to control how much the skybox is distorted by the bump texture).

The strange thing is, when I force it to take only the bump OR the original normals, it works as expected (too much distortion or no distortion at all):

o.Normal = origNorm; // skybox is not distorted
OR
o.Normal = bump; // skybox it way too much distorted

With o.Normal = bump * _Reflection, I get just a flat grey plane for low values of _Reflection. I think that’s because it does not matter what size normals have, the direction is important. So I need a way to tone down the strength of the normal map somehow…

A handy thing if you’re not sure what’s going on in a surface shader is to look at the generated code by selecting the shader in your Project and hitting the “Show generated code” button in the Inspector. Skimming around for stuff about o.Normal, you’ll find this line right before the surface shader is called:

o.Normal = IN.worldNormal;

So you’re linearly interpolating between a world space normal and a tangent space normal. (Your unpacked _BumpMap texture). That’s almost surely not what you want.

Just write your scaled tangent space normal into o.Normal. You don’t have to take into account what was there before.