I'm implementing normal/bump mapping in world space coordinates (I find those easier to work with) and my lighting worked fine without normal mapping, but when introducing normal mapping (and the new vectors calculated with the TBN matrix) the specular component of my lighting is off.
The specular component is not between the camera and the light where it should be so something is wrong. However, looking at my code I could not find any issues. The tangent and bitangent come from the ASSIMP object loader and the eyePos and lightPos are in world coordinates as well.
Since the lighting seems to look correct at the specular section (with the bump mapping shown) I assume it has something to do with the tangent space transformation?
Here is a picture demonstrating the issue:
Vertex shader:
#version 330
layout (location = 0) in vec4 vertex;
layout(location = 1) in vec3 normal;
layout(location = 2) in vec3 tangent;
layout(location = 3) in vec3 bitangent;
layout(location = 5) in vec2 texCoord;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
uniform vec3 lightPos;
uniform vec3 eyePos;
out vec3 Position;
out vec2 TexCoord;
out vec3 tangentLightDir;
out vec3 tangentViewDir;
void main()
{
gl_Position = projection * view * model * vertex;
// Position
Position = vec3(model * vertex);
// Normal
mat3 normalMat = transpose(inverse(mat3(model)));
Normal = normalize(normalMat * normal);
// Texture
TexCoord = texCoord;
// Normal mapping
mat3 TBN = mat3(tangent, bitangent, Normal);
TBN = transpose(TBN);
// Get direction vectors:
vec3 lightDir = normalize(lightPos - Position);
vec3 viewDir = normalize(eyePos - Position);
// Now transform them to tangent space
tangentLightDir = TBN * lightDir;
tangentViewDir = TBN * viewDir;
}
Fragment shader:
#version 330
in vec3 Position;
in vec2 TexCoord;
in vec3 tangentLightDir;
in vec3 tangentViewDir;
uniform sampler2D texture0;
uniform sampler2D texture_normal;
out vec4 outColor;
void main()
{
// defaults
vec4 ambient = vec4(0.1);
vec4 diffuse = vec4(0.4);
vec4 specular = vec4(0.5);
vec4 texColor = texture(texture0, TexCoord);
// Phong shading
vec3 LightDir = normalize(tangentLightDir);
vec3 Norm = normalize(texture(texture_normal, TexCoord).xyz * 2.0 - 1.0);
vec3 ViewDir = normalize(tangentViewDir);
vec3 ReflectDir = reflect(-LightDir,Norm);
float specularContribution = pow(max(dot(ViewDir, ReflectDir), 0.0), 32);
// Calculate diffuse component
vec4 I = diffuse * max(dot(LightDir, Norm), 0.0);
diffuse = clamp(I, 0.0, 1.0);
// Calculate specular component
specular = specular * specularContribution;
outColor = texColor * (diffuse + specular + ambient);
}