I previously posted about normal calcualtion in this shader.
I really want to know if I am doing it correctly.
Can anyone look over the code and just verify?
// Green Gandalf's Blended Normal Mapping Shader
//
// designed for use with terrain objects
//
//
// Created 7 March 2007, edited 8 March 2007.
//
float4x4 World;
float4x4 View;
float4x4 Projection;
float4 lightDir = {0.707107f, -0.707107f, 0.0f, 1.0f};
float4 ambiColor = {0.5f, 0.5f, 0.5f, 1.0f};
float4 lightColor = {1.0f, 1.0f, 1.0f, 1.0f};
float2 UVTiling = {12, 12};
float vertScale = 0.003; // reciprocal of maximum height of terrain
float contrast = 2.0; // higher values increase the contrast between textures
texture detailMap1 < string ResourceName = ""; >;
texture detailMap2 < string ResourceName = ""; >;
texture detailMap3 < string ResourceName = ""; >;
texture detailMap4 < string ResourceName = ""; >;
texture normalMap1 < string ResourceName = ""; >;
texture normalMap2 < string ResourceName = ""; >;
texture normalMap3 < string ResourceName = ""; >;
texture normalMap4 < string ResourceName = ""; >;
sampler2D detail1 = sampler_state
{ texture = <detailMap1>;
MinFilter = Linear;
MagFilter = Linear;
MipFilter = Linear;
};
sampler2D detail2 = sampler_state
{ texture = <detailMap2>;
MinFilter = Linear;
MagFilter = Linear;
MipFilter = Linear;
};
sampler2D detail3 = sampler_state
{ texture = <detailMap3>;
MinFilter = Linear;
MagFilter = Linear;
MipFilter = Linear;
};
sampler2D detail4 = sampler_state
{ texture = <detailMap4>;
MinFilter = Linear;
MagFilter = Linear;
MipFilter = Linear;
};
sampler2D nMap1 = sampler_state
{ texture = <normalMap1>;
MinFilter = Linear;
MagFilter = Linear;
MipFilter = Linear;
};
sampler2D nMap2 = sampler_state
{ texture = <normalMap2>;
MinFilter = Linear;
MagFilter = Linear;
MipFilter = Linear;
};
sampler2D nMap3 = sampler_state
{ texture = <normalMap3>;
MinFilter = Linear;
MagFilter = Linear;
MipFilter = Linear;
};
sampler2D nMap4 = sampler_state
{ texture = <normalMap4>;
MinFilter = Linear;
MagFilter = Linear;
MipFilter = Linear;
};
struct VS_INPUT
{ float4 Pos : POSITION;
float2 Tex : TEXCOORD0;
float3 Normal : NORMAL;
float3 Tangent : TANGENT;
float3 Binormal : BINORMAL;
};
struct VS_OUTPUT
{ float4 Pos : POSITION;
float2 Tex : TEXCOORD0;
float Diffuse : TEXCOORD1;
float4 Blender : TEXCOORD2;
float2 Depth : TEXCOORD3;
float3x3 tangentToWorld : TEXCOORD4;
//float3 Normal : TEXCOORD5;
};
VS_OUTPUT GGBlendVShader(VS_INPUT In, VS_OUTPUT Out)
{ //float4 tempPos = mul(In.Pos, mw);
//Out.Pos = mul(In.Pos, wvp);
float4 worldPosition = mul(float4(In.Pos.xyz,1), World);
float4 viewPosition = mul(worldPosition, View);
Out.Pos = mul(viewPosition, Projection);
Out.Tex = In.Tex;
Out.Diffuse = saturate(dot(normalize(In.Normal), -normalize(lightDir.xyz)));
Out.Depth.x = Out.Pos.z;
Out.Depth.y = Out.Pos.w;
// calculate tangent space to world space matrix using the world space tangent,
// binormal, and normal as basis vectors
Out.tangentToWorld[0] = mul(In.Tangent, World);
Out.tangentToWorld[1] = mul(In.Binormal, World);
Out.tangentToWorld[2] = mul(In.Normal, World);
//calculate the blend factors
float2 hn = float2 (In.Pos.y * vertScale, In.Normal.y);
hn = saturate(0.5.xx + contrast * (hn - 0.5.xx));
Out.Blender = float4 (hn.x * hn.y, hn.x * (1 - hn.y),
(1 - hn.x) * hn.y, (1 - hn.x) * (1 - hn.y));
// e.g. blends = grass, rock, sand, gravel
return Out;
}
struct PS_INPUT
{ float2 Tex : TEXCOORD0;
float Diffuse : TEXCOORD1;
float4 Blender : TEXCOORD2;
float2 Depth : TEXCOORD3;
float3x3 tangentToWorld : TEXCOORD4;
//float3 Normal : TEXCOORD5;
};
struct PS_OUTPUT
{
float4 Color : COLOR0;
float4 Normal : COLOR1;
float4 Depth : COLOR2;
};
PS_OUTPUT GGBlendPShader(PS_INPUT In, PS_OUTPUT Out)
{
float4 base1 = tex2D(detail1, In.Tex * UVTiling ) * In.Blender.x;
float4 base2 = tex2D(detail2, In.Tex * UVTiling ) * In.Blender.y;
float4 base3 = tex2D(detail3, In.Tex * UVTiling ) * In.Blender.z;
float4 base4 = tex2D(detail4, In.Tex * UVTiling ) * In.Blender.w;
//float4 detail = tex2D(nMap1,(In.Tex * UVTiling*20));
float4 base = (base1 + base2 + base3 + base4);// * (detail*2);
Out.Color = base * (ambiColor + In.Diffuse * lightColor );
//specular Intensity
//float4 specularAttributes = tex2D(specularSampler, input.TexCoord);
// Out.Color.a = specularAttributes.r; //output the specular color to the alpha channel
// read the normal from the normal map
//float4 normal1 = tex2D(nMap1, In.Tex * UVTiling ) * In.Blender.x;
//float4 normal2 = tex2D(nMap2, In.Tex * UVTiling ) * In.Blender.y;
//float4 normal3 = tex2D(nMap3, In.Tex * UVTiling ) * In.Blender.z;
//float4 normal4 = tex2D(nMap4, In.Tex * UVTiling ) * In.Blender.w;
float4 normal1 = (2 * (tex2D(nMap1,In.Tex * UVTiling))) - 1.0 * In.Blender.x;
float4 normal2 = (2 * (tex2D(nMap2,In.Tex * UVTiling))) - 1.0 * In.Blender.y;
float4 normal3 = (2 * (tex2D(nMap3,In.Tex * UVTiling))) - 1.0 * In.Blender.z;
float4 normal4 = (2 * (tex2D(nMap4,In.Tex * UVTiling))) - 1.0 * In.Blender.w;
float4 normalFromMap = (normal1 + normal2 + normal3 + normal4)/4;
//tranform to [-1,1]
//normalFromMap = 2.0f * normalFromMap - 1.0f;
//transform into world space
normalFromMap = mul(normalFromMap, (In.tangentToWorld[2],1.0));
//normalize the result
normalFromMap = normalize(normalFromMap);
//output the normal, in [0,1] space
//float4 map = 0.5f * (normalFromMap + 1.0f);
float3 modelNormal = normalize(In.tangentToWorld[2]); //transform normal domain
Out.Normal.rgb = modelNormal += normalFromMap.rgb;
//specular Power
//Out.Normal.a = specularAttributes.a;
//Out.Normal = 1.0;
Out.Depth = In.Depth.x / In.Depth.y;
return Out;
}
technique t1 // use this for blending only
{ pass p0
{
//NORMALIZENORMALS = TRUE;
VertexShader = compile vs_2_0 GGBlendVShader();
PixelShader = compile ps_2_0 GGBlendPShader();
}
}