I'm hoping that someone can possibly take a look and let me know where I've gone wrong.
/*
Portions of this code related to normal mapping
and tangent space calculations derived from
http://www.gamedev.net/community/forums/topic.asp?topic_id=504221
Portions of this code related to parallax mapping derived from
http://www.gamedev.net/community/forums/topic.asp?topic_id=387447
*/
cbuffer Variables
{
matrix WVPMatrix : WorldViewProjection;
matrix WorldMatrix : World;
matrix WorldITMatrix : WorldInverseTranspose;
matrix ViewITMatrix : ViewInverseTranspose;
}
extern Texture2D DiffuseTexture;
extern Texture2D NormalMapTexture;
extern Texture2D HeightMapTexture;
SamplerState samLinear
{
Filter = MIN_MAG_MIP_LINEAR;
AddressU = Wrap;
AddressV = Wrap;
};
struct VS_INPUT
{
float4 Pos : POSITION;
float4 Normal : NORMAL;
float4 Tangent : TANGENT;
float4 Binormal : BINORMAL;
float2 Tex : TEXCOORD;
};
struct PS_INPUT
{
float4 Pos : SV_POSITION;
float2 Tex : TEXCOORD0;
float3 ToView : TEXCOORD1;
float3 ToLight : TEXCOORD2;
};
float3 LightPosition = float3( 0.0f, 0.0f, 0.0f );
float3 DiffuseColor = float3( 1.0f, 1.0f, 1.0f );
float3 AmbientLightColor = float3( 0.35f, 0.35f, 0.35f );
float3 SpecularColor = float3( 1.0f, 1.0f, 1.0f );
float SpecularPower = 4.0;
float3 EyeFromViewIT(){
return float3(ViewITMatrix[0].w,ViewITMatrix[1].w,ViewITMatrix[2].w);
}
////////////////////////////////////////////////
// Vertex Shader - Main Function
///////////////////////////////////////////////
PS_INPUT VS( VS_INPUT vsInput )
{
PS_INPUT psInput;
// transform vertex pos to homogeneous coordinates
psInput.Pos = mul( vsInput.Pos, WVPMatrix );
// pass texture coords
psInput.Tex = float2( vsInput.Tex.x, vsInput.Tex.y );
// world space to tangent space matrix
float3x3 worldToTangentSpace = float3x3(
mul( vsInput.Tangent, WorldITMatrix ).xyz,
mul( vsInput.Binormal, WorldITMatrix ).xyz,
mul( vsInput.Normal, WorldITMatrix ).xyz
);
// vertex position in world space
float3 posWorld = mul( vsInput.Pos, WorldMatrix );
// vector to light and view in world space
float3 toLight = LightPosition - posWorld;
float3 toViewer = EyeFromViewIT() - posWorld;
// world to tangent space
psInput.ToLight = mul( worldToTangentSpace, toLight );
psInput.ToView = mul( worldToTangentSpace, toViewer );
return psInput;
}
float2 ParallaxMap(PS_INPUT psInput)
{
float3 vEye = psInput.ToView;
float fBumpScale = 0.05f;
float2 vCoord = psInput.Tex;
float fDepth = HeightMapTexture.Sample( samLinear, vCoord ).rgb;
float2 vHalfOffset = normalize(vEye) * (fDepth) * fBumpScale;
fDepth = (fDepth + HeightMapTexture.Sample( samLinear, vCoord + vHalfOffset) ) * 0.5;
vHalfOffset = normalize(vEye) * (fDepth) * fBumpScale;
fDepth = (fDepth + HeightMapTexture.Sample( samLinear, vCoord + vHalfOffset) ) * 0.5;
vHalfOffset = normalize(vEye) * (fDepth) * fBumpScale;
return vCoord + vHalfOffset;
}
///////////////////////////////////////////////
// Pixel Shader
///////////////////////////////////////////////
float4 PS(PS_INPUT psInput) : SV_Target
{
float2 vParallaxCoords = ParallaxMap( psInput );
float4 baseColor = DiffuseTexture.Sample( samLinear, vParallaxCoords );
float3 viewDir = normalize( psInput.ToView );
float3 normal = normalize( 2 * NormalMapTexture.Sample( samLinear, vParallaxCoords ).rgb - 1 );
// Phong relfection is ambient + light-diffuse + spec highlights.
// I = Ia*ka*Oda + fatt*Ip[kd*Od(N.L) + ks(R.V)^n]
// Ref: http://www.whisqu.se/per/docs/graphics8.htm
// and http://en.wikipedia.org/wiki/Phong_shading
// Get light direction for this fragment
float3 lightDir = normalize(psInput.ToLight);
float diffuseLighting = DiffuseColor * saturate(dot(normal, lightDir));
// Introduce fall-off of light intensity
float LightDistanceSquared = length(psInput.ToLight) * length(psInput.ToLight);
diffuseLighting *= (LightDistanceSquared / dot(psInput.ToLight, psInput.ToLight));
float3 vReflect = reflect(-lightDir, normal);
float specLighting = pow(saturate(dot(vReflect, viewDir)), SpecularPower);
specLighting *= SpecularColor;
return float4(saturate(
(AmbientLightColor * baseColor) +
(diffuseLighting * 0.6) +
(specLighting * 0.5)
), 1);
}
// Define the technique
technique10 Render
{
pass P0
{
SetVertexShader( CompileShader( vs_4_0, VS() ) );
SetGeometryShader( NULL );
SetPixelShader( CompileShader( ps_4_0, PS() ) );
}
}
Hopefully the image below helps as well.
I'm placing the light at 0, 0, 0 , the ground plane origin at 0, -10, 0, and the cube at 0, 10, 0. With the light at 0, 0, 0 and acting as a point light, I don't believe the top op the cube should be being lit the way it is. In general the lighting just doesn't appear to be the way it should at all, and my head hurts.