[LWJGL] Normalmapping issues!

Hello! :slight_smile:

I have been trying to implement Normal Mapping into my engine for quite awhile now, but I can not seem to get it to work properly. There has to be something simple I am missing…

Here is the current GLSL code for my normal mapping:

// Vertex
#version 330

uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
uniform mat4 modelMatrix;
uniform mat3 normalMatrix;
uniform mat3 normalModelMatrix;
uniform vec4 modelColor;

layout (location = 0) in vec3 in_position;
layout (location = 1) in vec3 in_normal;
layout (location = 2) in vec2 in_texCoords;
layout (location = 3) in vec4 in_Color;

out vec3 vNormal;
out vec2 vTexCoords;
out vec4 vColor;
out vec3 vEyePosition;

void main(){
	vEyePosition = (viewMatrix * modelMatrix * vec4(in_position, 1.0)).xyz;
    gl_Position = projectionMatrix * vec4(vEyePosition, 1.0);
    
	vNormal = normalMatrix * normalModelMatrix * in_normal;
	
	vTexCoords = in_texCoords;
	vColor = in_Color * modelColor;
}

// Fragment
#version 150

uniform sampler2D sampler;
uniform sampler2D normalMap;
uniform float specular;
uniform float gloss;

in vec3 vNormal;
in vec2 vTexCoords;
in vec4 vColor;
in vec3 vEyePosition;

mat3 cotangentFrame( vec3 N, vec3 p, vec2 uv ) {
    // get edge vectors of the pixel triangle
    vec3 dp1 = dFdx(p);
    vec3 dp2 = dFdy(p);
    vec2 duv1 = dFdx(uv);
    vec2 duv2 = dFdy(uv);
 
    // solve the linear system
    vec3 dp2perp = cross( dp2, N );
    vec3 dp1perp = cross( N, dp1 );
    vec3 T = dp2perp * duv1.x + dp1perp * duv2.x;
    vec3 B = dp2perp * duv1.y + dp1perp * duv2.y;
 
    // construct a scale-invariant frame
    float invmax = inversesqrt(max(0.00000000000000001, max(dot(T, T), dot(B, B))));
    return mat3( T * invmax, B * invmax, N );
    
}
 
vec3 perturbNormal( vec3 N, vec3 V ) {
    vec3 map = texture( normalMap, vTexCoords ).xyz;
    map = (map * (255.0/127.0)) - (128.0/127.0);
    map.z = sqrt( 1.0 - dot( map.xy, map.xy ) );
    
    mat3 TBN = cotangentFrame( N, V, vTexCoords );
    return normalize( TBN * map );
}

void write(vec3 diffuse, vec3 normal, float specular, float glossiness, vec3 emissive);

void main(){

	vec4 textureSample = texture(sampler, vTexCoords) * vColor;
	
	if(textureSample.a < 0.5){
		discard;
	}
	
	vec3 normalNormalized = normalize(vNormal);
	vec3 normalPerturbed  = perturbNormal(normalNormalized, normalize(vEyePosition));
	
	write(textureSample.xyz, normalPerturbed, specular, gloss, vec3(0, 0, 0));
}

The problem is that when I rotate my camera the normal map changes its shading… I am almost 100% sure that all my matrices are correct, as if I use a texture with color (128, 128, 255) the normal shading works fine.

I believe the issue lies in the fact that my game uses the z axis for height, instead of the y axis, which could cause the TBN to be incorrectly calculated…

Also it causes seams like this:

My artist is absolutely certain that his normal map is correct. He’s tested it in Blender, and marmoset toolbag.

I have tried the obvious tests, both negating and swizzling the x and y component on the “map” variable in the perturb normal function.
I have tried a few different perturb normal methods from google, none seem to work.
I have tried swizzling the TBN matrix.

Does anyone have any ideas? :c