Having problems with Phong Lighting + Normal/Parallax mapping

Started by
1 comment, last by dsoltyka 13 years, 2 months ago
I've been having some serious issues getting a shader which handles a single point light combined with Normal + Parallax mapping to work correctly. It appears that the normal and parallax are both fine, however the lighting is seriously wrong. I've been through this for a few hours now and at this point I'm assuming it's something really simple that I'm just not catching.

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.

63114663.png
Advertisement
At a quick glance the first two things that pop out to me are: you aren't actually attenuating your diffuse (look at your calculation for the attenuation factor it works out to 1), and you are adding the diffuse lighting you calculate to the base texture color (modulated by the ambient) - generally I think you would want it to look more like (baseColor * (diffuse + ambient) + specular).

At a quick glance the first two things that pop out to me are: you aren't actually attenuating your diffuse (look at your calculation for the attenuation factor it works out to 1), and you are adding the diffuse lighting you calculate to the base texture color (modulated by the ambient) - generally I think you would want it to look more like (baseColor * (diffuse + ambient) + specular).


Thanks for the input. I ended up ditching code I had there as it didn't make enough sense to me. I went through the wiki article on Phong-Blinn lighting line for line to get a better handle on the process. In doing so, it appears I fixed up a few other broken parts as well. It's funny what happens when you have a better understanding on the subject matter :)





This topic is closed to new replies.

Advertisement