Hi,
I am currently implementing per pixel phong shading + normal mapping using DX10 and HLSL. I have the diffuse + normal map component working, but I am having problems with the specular component. First a picture of my result:
As you can see, the specular result is as if the viewer or the light was on the left side of the cube. The diffuse result shows what is correct.
As my diffuse-only result is fine, I assume the tangent space calculations are correct (maybe I am wrong). So I am left with a problem most probably with the reflection vector calculation or the view vector calculation. Below is the relevant code for the sample.
I have generated a cube (but have same results with sphere and plane) where the front face (-z as normal) is generated like this:
// Normal is -Z axis
// Tangent is X axis
// Tangent.w is -1 so that the binormal is correct
//--
pVertex->vPosition = CVector3( fWidth * ( u - 0.5f ), fHeight * ( v - 0.5f ), -0.5f * fDepth );
pVertex->vNormal = CVector3( 0.0f, 0.0f, -1.0f );
pVertex->vTangent = CVector4( 1.0f, 0.0f, 0.0f, -1.0f );
pVertex->vTexCoord = CVector2( u, 1.0f - v );
My vertex shader is the following:
VS_OUTPUT output = (VS_OUTPUT) 0;
// Some vectors in world space
//--
float4 P = mul( float4( input.position, 1), kgfx_matWorld ); // Position in world space
float3 L = normalize( kgfx_vLightPosition.xyz - P.xyz ); // Light in world space
float3 V = normalize( kgfx_vCameraPosition.xyz - P.xyz ); // View in world space
// Build world to tangent space transformation
//--
float3 T = normalize( mul( input.tangent, (float3x3) kgfx_matWorld ) );
float3 N = normalize( mul( input.normal, (float3x3) kgfx_matWorld ) );
float3 B = normalize( input.tangent.w * cross( N, T ) );
float3x3 TBN;
TBN[0] = T;
TBN[1] = B;
TBN[2] = N;
// Build the output
//--
output.position = mul( P, kgfx_matViewProj ); // Position in screen space
output.texCoord = input.texCoord; // Copy tex coords
output.light = normalize( mul( TBN, L ) ); // Light in texture space
output.view = normalize( mul( TBN, V ) ); // View in texture space
return output;
My pixel shader is the following:
float3 L = normalize( input.light ); // Light in tangent space
float3 V = normalize( input.view ); // View in tangent space
float3 N = float3( 0, 0, 1 ); // Default normal in tangent space to compute self shadowing
float fSelfShadow = dot( N, L );
if ( fSelfShadow>=0 )
{
// Get normal from normal map
//--
N = normalize( 2.0 * kgfx_texNormalMap.Sample( linearSampler, input.texCoord ) - 1.0 );
}
fSelfShadow = saturate( 10 * fSelfShadow );
// Light reflection vector
//--
float3 R = normalize( reflect( L, N ) );
float fSpecular = pow( saturate( dot( R, V ) ), 60 );
float fDiffuse = saturate( dot( N, L ) );
float4 colColor = kgfx_texColorMap.Sample( linearSampler, input.texCoord );
output.color = fSelfShadow * ( fDiffuse * colColor + fSpecular * kgfx_colLightColor );