I tried to implement normal mapping in my opengl application but I can't get it to work.
This is the diffuse map (which I add a brown color to) and this is the normal map.
In order to get the tangent and bitangent (in other places called binormals?) vectors, I run this function for every triangle in my mesh:
void getTangent(const glm::vec3 &v0, const glm::vec3 &v1, const glm::vec3 &v2,
const glm::vec2 &uv0, const glm::vec2 &uv1, const glm::vec2 &uv2,
std::vector<glm::vec3> &vTangents, std::vector<glm::vec3> &vBiangents)
{
    // Edges of the triangle : postion delta
    glm::vec3 deltaPos1 = v1-v0;
    glm::vec3 deltaPos2 = v2-v0;
    // UV delta
    glm::vec2 deltaUV1 = uv1-uv0;
    glm::vec2 deltaUV2 = uv2-uv0;
    float r = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV1.y * deltaUV2.x);
    glm::vec3 tangent = (deltaPos1 * deltaUV2.y   - deltaPos2 * deltaUV1.y)*r;
    glm::vec3 bitangent = (deltaPos2 * deltaUV1.x   - deltaPos1 * deltaUV2.x)*r;
    for(int i = 0; i < 3; i++) {
        vTangents.push_back(tangent);
        vBiangents.push_back(bitangent);
    }
}
After that, I call glBufferData to upload the vertices, normals, uvs, tangents and bitangents to the GPU. The vertex shader:
#version 430
uniform mat4 ProjectionMatrix;
uniform mat4 CameraMatrix;
uniform mat4 ModelMatrix;
in vec3 vertex;
in vec3 normal;
in vec2 uv;
in vec3 tangent;
in vec3 bitangent;
out vec2 fsCoords;
out vec3 fsVertex;
out mat3 TBNMatrix;
void main()
{
    gl_Position = ProjectionMatrix * CameraMatrix * ModelMatrix * vec4(vertex, 1.0);
    fsCoords = uv;
    fsVertex = vertex;
    TBNMatrix = mat3(tangent, bitangent, normal);
}
Fragment shader:
#version 430
uniform sampler2D diffuseMap;
uniform sampler2D normalMap;
uniform mat4 ModelMatrix;
uniform vec3 CameraPosition;
uniform struct Light {
    float ambient;
    vec3 position;
} light;
uniform float shininess;
in vec2 fsCoords;
in vec3 fsVertex;
in mat3 TBNMatrix;
out vec4 color;
void main()
{
    //base color
    const vec3 brownColor = vec3(153.0 / 255.0, 102.0 / 255.0, 51.0 / 255.0);
    color = vec4(brownColor * (texture(diffuseMap, fsCoords).rgb + 0.25), 1.0);//add a fixed base color (0.25), because its dark as hell
    //general vars
    vec3 normal = texture(normalMap, fsCoords).rgb * 2.0 - 1.0;
    vec3 surfacePos = vec3(ModelMatrix * vec4(fsVertex, 1.0));
    vec3 surfaceToLight = normalize(TBNMatrix * (light.position - surfacePos)); //unit vector
    vec3 eyePos = TBNMatrix * CameraPosition;
    //diffuse
    float diffuse = max(0.0, dot(normal, surfaceToLight));
    //specular
    float specular;
    vec3 incidentVector = -surfaceToLight; //unit
    vec3 reflectionVector = reflect(incidentVector, normal); //unit vector
    vec3 surfaceToCamera = normalize(eyePos - surfacePos); //unit vector
    float cosAngle = max(0.0, dot(surfaceToCamera, reflectionVector));
    if(diffuse > 0.0)
        specular = pow(cosAngle, shininess);
    //add lighting to the fragment color (no attenuation for now)
    color.rgb *= light.ambient;
    color.rgb += diffuse + specular;
}
The image I get is completely incorrect. (light positioned on camera)

What am I doing wrong here?



