Better look at the screenshots (angles are all correct without normal mapping, directional light source (0, 0, 1))

without normal mapping front:

http://cl.ly/image/051a3g140a0z

with normal mapping front:

http://cl.ly/image/2E3X0Y3b1s2c

with normal mapping back:

http://cl.ly/image/2g2Y1D3n360P

As you can see here also on the specular only picture (from the back of the cube):

http://cl.ly/image/0d0G3P0s252T

The NdotL product here is wrong as it can not possibly be > 0.0f.

Everything except the front face of the cube should essentially be lit and the rest completely black as it is the case when not using normal mapping.

All sides of the cube seem to have a final normal that does make the side faces lit a little bit except the face in the back, which makes the whole image look odd.

Why is this ? Is there some angle check that I'm missing ?

Here's how I calculate the tangent/bitangent in my application:

// Calculate bitangent for(int i = 0; i < 24; i++) { XMVECTOR normal = XMVectorSet(this->texturedNormalVertices[i].normal.x, this->texturedNormalVertices[i].normal.y, this->texturedNormalVertices[i].normal.z, 0); XMVECTOR tangent = XMVector3Cross(normal, forward); XMFLOAT4 tang; XMStoreFloat4(&tang, tangent); float magnitude = sqrt(tang.x * tang.x + tang.y * tang.y + tang.z * tang.z); if( magnitude == 0 ) { tangent = XMVector3Cross(normal, up); } XMVECTOR biTangent = XMVector3Cross(normal, tangent); // Calculate tangent XMVECTOR dot = XMVector3Dot(XMVector3Cross(normal, tangent), biTangent); if (XMVectorGetX(dot) < 0.0f) { tangent = tangent * -1.0f; } XMStoreFloat3(&this->texturedNormalVertices[i].tangent, tangent); XMStoreFloat3(&this->texturedNormalVertices[i].biTangent, biTangent); }

And here's the shader code:

**VS part:**

// Calculate View-space Tangent-BiTangent-Normal matrix output.TBN[0] = mul(input.Tangent, (float3x3)WorldView); output.TBN[1] = mul(input.BiTangent, (float3x3)WorldView); output.TBN[2] = mul(input.Normal, (float3x3)WorldView);

**PS part:**

// Normal Mapping float4 NormalMapped = (2.0f * NormalMap.Sample(LinearSampler, input.UV)) - 1.0f; NormalMapped = normalize(NormalMapped); float3 N = normalize(mul(NormalMapped.xyz, (float3x3)input.TBN));

**the BRDF:**

float4 Gaussian(in float3 Normal, in float3 LightDir, in float3 ViewDir, in float SpecularPower, in float3 SpecularAlbedo, in float SpecularIntensity) { const float kPI = 3.1415926536f; float3 N = normalize(Normal); float3 L = normalize(LightDir); float3 V = normalize(ViewDir); float3 H = normalize(-L - V); float4 Lr = float4(0, 0, 0, 1); float4 Ls = float4(0, 0, 0, 1); // Incident irradiance float4 Ei = _LightColor * _LightIntensity; // Lambert float NdotL = saturate(dot(N, -L)); float kd = NdotL; // diffuse constant Lr = (kd / PI) * Ei; // outgoing radiance // Gaussian Specular [Mittring12] float normalizationFactor = 0.17287429f + 0.01388682f * SpecularPower; // approximation by Krzysztof Narkowicz float NdotH = saturate(dot(N, H)); float Threshold = 0.04f; float cosAngle = pow(Threshold, 1 / SpecularPower); float normAngle = (NdotH - 1) / (cosAngle - 1); float Specular = exp(-normAngle * normAngle) * NdotL; Specular *= normalizationFactor; Ls = float4(Specular, Specular, Specular, 1.0f); Ls.rgb *= SpecularAlbedo * SpecularIntensity; return float4(Lr + Ls); }

**Edited by lipsryme, 11 October 2012 - 09:18 AM.**