Normal/Reflection Problem

Hey guys. I have a question that hopefully one of you experts will be able to help on. I have the following shader that I’m working on but for some reason the cubemap reflection is having some issues. It gets rotated and I can’t seem to figure out why. I believe I’m calculating the world normal and world view direction correctly but perhaps not. Any help would be very much appreciated. Thanks.

Shader "test" {
	Properties {
		_Highlight ("Highlight Color", Color) = (0.5,0.5,0.5,1.0)
		_MainTex ("Diffuse(RGB), Gloss(A)", 2D) = "white" {}
		_BumpMap ("Normal", 2D) = "bump" {}
		_BumpStrength ("Bump Strength", Range(0.0, 1.5)) = 1
		_LightMap ("Lighting(RGB)", 2D) = "black" {}
		_Cube ("Reflection Cubemap", Cube) = "_Skybox" {TexGen CubeReflect}
		_ReflStrength ("Reflection Strength", Range(0.0, 10)) = 1
		_ReflFresnal ("Reflection Fresnal", Range(0.0,2.0)) = 0
		_SpecColor ("Specular Color", Color) = (1.0,1.0,1.0,1.0)
		_Shininess ("Specular Spread", Range(.25, 100)) = 10
		_SpecStrength ("Specular Strength", Range (0, 20)) = 1
	}
	
	SubShader {
		Tags { "RenderType" = "Opaque" }
		
		Pass {  
		
			Tags { "LightMode" = "forwardbase" }
			
			CGPROGRAM
			#pragma only_renderers d3d9
			#pragma vertex vert
			#pragma fragment frag
			#pragma multi_compile_fwdbase
			#pragma fragmentoption ARB_precision_hint_fastest 
			#include "UnityCG.cginc"
           			 #include "AutoLight.cginc"
         						
			//User Defined Variables
			uniform fixed4 _Highlight;
			uniform sampler2D _MainTex;
			uniform sampler2D _LightMap;
			uniform half _EmitStrength;
			uniform sampler2D _BumpMap;
			uniform half _BumpStrength;
			uniform samplerCUBE _Cube;
			uniform fixed _ReflStrength;
			uniform half _ReflFresnal;
			uniform fixed4 _SpecColor;
			uniform fixed _Shininess;
			uniform fixed _SpecStrength;

			
			//Unity Defined Variables
			uniform half4 _LightColor0;
			
			//Input Struct
			struct v2f{
				half4 pos : SV_POSITION;
				half4 uv : TEXCOORD0;
				half3 viewDir : TEXCOORD1;
   				half3 lightDir : TEXCOORD2; 
   				half4 normal : TEXCOORD3;
	   			half3 viewDirW : TEXCOORD4;
	   			half4 normalW : TEXCOORD5;
	   			half4 tangentW : TEXCOORD6;
   				LIGHTING_COORDS(7,8)
			};
			
			//Vertex Function
			v2f vert(appdata_full v){
				v2f o;
				o.pos = mul( UNITY_MATRIX_MVP, v.vertex);
				o.uv.xy = v.texcoord.xy;
				o.uv.zw = v.texcoord1.xy;
				float3 binormal = cross( v.normal, v.tangent.xyz ) * v.tangent.w;
			  	  float3x3 rotation = float3x3( v.tangent.xyz, binormal, v.normal );
			   	 o.viewDir = mul ( rotation  , ObjSpaceViewDir ( v.vertex ) );
			  	  o.lightDir = mul ( rotation  , ObjSpaceLightDir ( v.vertex ) );
			  	  o.normal.xyz = mul (rotation, v.normal);
			    
		
				  o.viewDirW = WorldSpaceViewDir(v.vertex);
				 o.normalW.xyz = normalize( mul( half4( v.normal, 0.0 ), _World2Object ).xyz );
				o.tangentW.xyz = normalize( mul( _Object2World, v.tangent ).xyz );
				  half3 binormalW = normalize( cross( o.normalW.xyz, o.tangentW.xyz) * v.tangent.w );
				 o.normal.w = binormalW.x;
				  o.normalW.w = binormalW.y;
				 o.tangentW.w = binormalW.z;	    
			
			    
			    TRANSFER_VERTEX_TO_FRAGMENT(o);
			    return o;
			}
			
			//Fragment Function
			fixed4 frag(v2f i) : Color
			{
				fixed4 colorMap = tex2D(_MainTex, i.uv.xy);
				fixed3 lightMap = tex2D(_LightMap, i.uv.zw);

				float atten = LIGHT_ATTENUATION(i);
				i.lightDir = normalize ( i.lightDir );
				i.viewDir = normalize ( i.viewDir );
	
				

				fixed3 normalDirection = normalize( fixed3( UnpackNormal ( tex2D (_BumpMap, i.uv.xy) ).xy, (2.0 - _BumpStrength) ) );
			
				
				fixed3 lighting = _LightColor0 * saturate( dot (normalDirection, i.lightDir )) * (atten * 2) * saturate(lightMap.rgb + 0.5);// * 0.5 + 0.5;
				
			
					fixed3x3 local2WorldTranspose = fixed3x3(i.tangentW.xyz, fixed3(i.normal.w, i.normalW.w, i.tangentW.w), i.normalW.xyz);
					fixed3 normalDirectionW = normalize( mul( normalDirection, local2WorldTranspose));
					float rim = 1.0 - saturate(dot( normalDirection, i.viewDir ));
					fixed3 reflection = texCUBE(_Cube, reflect(-i.viewDirW, normalDirectionW)) * colorMap.a * lightMap.rgb * _ReflStrength * pow( rim, _ReflFresnal );
			
				
		
					fixed3 spec = lighting * _SpecColor.rgb * pow(saturate(dot(reflect(-i.lightDir.xyz, normalDirection), i.viewDir)), _Shininess) * colorMap.a * _SpecStrength ;
 			
 				
 				fixed3 result = colorMap.rgb * (lighting + lightMap.rgb) + (_Highlight.rgb - 0.5) + spec + reflection;
 				

 				
				return  fixed4(result, spec);
			}
			ENDCG		
		}
	}
	
	FallBack "Diffuse"

}

1221360--50397--$problem.jpg

Currently you’re outputting binormalW to your normalW, tangentW and binormalW. That’ll screw things up.

For getting tangent-to-world in your fragment shader, I’m not sure what you’re trying will work.

This should do it…

struct v2f
{
    float4  pos : SV_POSITION;
    float2  uv : TEXCOORD0;
    float3  normal : TEXCOORD1;
    float3  tangent : TEXCOORD2;
    float3  binormal : TEXCOORD3;
    float3  viewDir : TEXCOORD4;
}; 
 
v2f vert (appdata_tan v)
{
    v2f o;
    o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    o.uv = v.texcoord.xy;
    o.normal = mul((float3x3)_Object2World, v.normal).xyz;
    o.tangent = v.tangent;
    o.binormal = cross(o.normal, o.tangent) * v.tangent.w;
    o.viewDir = WorldSpaceViewDir(v.vertex);
    return o;
}
 
sampler2D _BumpMap;
samplerCUBE _CubeMap;
 
float4 frag(v2f IN) : COLOR
{
    float3 normal = UnpackNormal(tex2D(_BumpMap, IN.uv));
    float3 normalO = (IN.tangent * normal.x) + (IN.binormal * normal.y) + (IN.normal * normal.z);
    float3 normalW = mul((float3x3)_Object2World, normalO);
    fixed4 reflection = texCUBE(_CubeMap, reflect(normalize(-IN.viewDir), normalW));
}