I am trying to do normal mapping in a lagged renderer and I don't know how to implement normal maps anymore. I have a bool that tells whether a normal mapped value should be used or not, and thus whether the TBN matrix should be calculated. My vertex code for the geometry run looks like this:

```
#version 410 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;
layout (location = 3) in vec3 aTangent; // Optional Texture coordinates
layout (location = 4) in vec3 aBitangent; // Optional Texture coordinates
out vec3 FragPos;
out vec2 TexCoords;
out vec3 Normal;
out mat3 TBN;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform bool hasNormalMap;
void main()
{
vec4 worldPos = model * vec4(aPos, 1.0);
FragPos = worldPos.xyz;
TexCoords = aTexCoords;
Normal = transpose(inverse(mat3(model))) * aNormal;
if(hasNormalMap)
{
vec3 T = normalize(vec3(model * vec4(aTangent, 0.0)));
vec3 N = normalize(vec3(model * vec4(aNormal, 0.0)));
// re-orthogonalize T with respect to N
T = normalize(T - dot(T, N) * N);
// then retrieve perpendicular vector B with the cross product of T and N
vec3 B = cross(N, T);
mat3 TBN = mat3(T, B, N);
}
gl_Position = projection * view * worldPos;
}
```

Here I am confused:

In my calculation, I multiplied T and N by the model matrix that should have moved it into space. Now the transpose (T, B, N) should bring me back to the model space (I think I'm not sure). How can I use the TBN in the fragment shader to calculate the normals in space?

If there are better approaches, they are welcome. Thank you very much.

To update:

I removed the transposition of the TBN as there is no reason to turn into a tangent space if we want to pass it in space. How do we apply the TBN matrix in the fragment shader so that the normal lighting value is correct? I have currently done:

```
#version 410 core
layout (location = 0) out vec3 gPosition;
layout (location = 1) out vec3 gNormal;
layout (location = 2) out vec4 gAlbedoSpec;
in vec2 TexCoords;
in vec3 FragPos;
in vec3 Normal;
in mat3 TBN;
struct Material {
sampler2D diffuseMap;
sampler2D specularMap;
sampler2D normalMap;
float shininess;
};
uniform Material material;
uniform bool hasNormalMap;
void main()
{
// store the fragment position vector in the first gbuffer texture
gPosition = FragPos;
// also store the per-fragment normals into the gbuffer
gNormal = normalize(Normal);
if(hasNormalMap)
{
gNormal = texture(material.normalMap, TexCoords).rgb * TBN;
gNormal = normalize(gNormal);
}
// and the diffuse per-fragment color
gAlbedoSpec.rgb = texture(material.diffuseMap, TexCoords).rgb;
// store specular intensity in gAlbedoSpec's alpha component
gAlbedoSpec.a = texture(material.specularMap, TexCoords).r;
}
```

but it doesn't feel right. I imagine that I would transform the sampled value from the normal map through the TBN matrix to get it in space. Do I miss something?