GLSL Mat3 troubles

Started by
1 comment, last by wcassella 7 years, 2 months ago

Having recently gotten tangent vectors working, I wanted to try out normal mapping. I'm constructing a TBN matrix in my vertex shader like so (including the whole thing for clarity):


// basic.vert
#version 430 core

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

in vec3 v_position;
in vec3 v_normal;
in vec3 v_tangent;
in vec2 v_texcoord;

out VS_OUT {
	vec3 position;
	vec2 texcoord;
	vec3 tangent;
	vec3 bitangent;
	vec3 normal;
	mat3 TBN;
} vs_out;

void main()
{
	gl_Position = projection * view * model * vec4(v_position, 1);
	vs_out.position = (model * vec4(v_position, 1)).xyz;

	// Compute TBN matrix
        // Not using bitangent sign, I was *going* to add that next
	vec3 v_bitangent = cross(v_normal, v_tangent);
	vec3 T = normalize(vec3(model * vec4(v_tangent,   0.0)));
   	vec3 B = normalize(vec3(model * vec4(v_bitangent,  0.0)));
   	vec3 N = normalize(vec3(model * vec4(v_normal,    0.0)));
	vs_out.tangent = T;
	vs_out.bitangent = B;
	vs_out.normal = N;
        vs_out.TBN = mat3(T, B, N);
}

You may have noticed that some of my shader outputs are redundent with the TBN matrix, I'll get to that.

So just to test this out, I wrote my fragment shader like so:


// basic.frag
#version 430 core

uniform sampler2D diffuse;

in VS_OUT {
    vec3 position;
    vec2 texcoord;
    vec3 tangent;
    vec3 bitangent;
    vec3 normal;
    mat3 TBN;
} fs_in;

layout (location = 0) out vec3 out_position;
layout (location = 1) out vec3 out_normal;
layout (location = 2) out vec4 out_diffuse;
layout (location = 3) out float out_specular;

void main()
{
    out_position = fs_in.position;
    out_normal = fs_in.TBN[2];
    out_diffuse = texture(diffuse, fs_in.texcoord);
    out_specular = 0.3;
}

Finally, the viewport shader just outputs the normal buffer instead of doing any shading. However, I just get a black screen, with no errors.

So I changed the out_normal assignment line in my fragment shader to:


out_normal = fs_in.normal;

And it works. After a lot of head scratching, I ended up with this.


// basic.vert
//...
out VS_OUT {
        //...
	mat4 TBN;
} vs_out;

//...
vs_out = mat4(vec4(T, 0), vec4(B, 0), vec4(N, 0), vec4(0, 0, 0, 1));


// basic.frag
//...
in VS_OUT {
        //...
        mat4 TBN;
} fs_in;

//...
out_normal = TBN[2].xyz;

And it works. That obviously isn't really what I'd want, but I have no idea what to believe anymore. Is this a driver bug, or am I doing something stupid (it wouldn't be the first time)?

Edit - Some additional notes

Using (when TBN is a mat3):


out_normal = fs_in.TBN[0];

Outputs the bitangent vector, and:


out_normal = fs_in.TBN[1];

Outputs the normal vector.

fs_in.tangent/bitangent/normal always returns the expected result, so I may end up just constructing the TBN matrix in the fragment shader.

Advertisement

Don't have a direct answer but a side note: you need to normalize your t,b,n vectors in the fragement shader, or they will give you incorrect lighting results.

NBA2K, Madden, Maneater, Killing Floor, Sims http://www.pawlowskipinball.com/pinballeternal

Thanks for the heads up. Is that due to OpenGL doing interpolation between vertices to get the values for the fragment shader?

Anyway, ultimately I've come to the conclusion that this is a driver bug. I'm developing on a Surface Book with that wacky hybrid GPU thing, and when I run my game with the integrated GPU it works, but when I run it with the dedicated Nvidia GPU it does not. I"ll just stick to constructing the TBN matrix in the fragment shader.

This topic is closed to new replies.

Advertisement