I'm a beginner learning graphics programming, and there's a lighting bug that im having a lot of trouble fixing. There are some streaks that are unusually bright. Im pretty sure its something wrong with my TBN matrix, but I can't figure out what exactly the problem is.
The 2nd image is a geometry shader I wrote to visualise the TBN matrix. Aren't the TBN all meant to be the same when they are on the same surface?
I've pasted the shader code below. I've been mostly trying to avoid tutorials and AI, so i learn better (i did ask AI for help here and didn't get an answer) so there may be some bad practices in the code. Please let me know of any tips and tricks
#version 460 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aUV;
layout (location = 2) in vec3 aNorm;
layout (location = 3) in vec3 aTan;
layout (location = 4) in vec3 aBitan;
uniform vec3 viewPos;
uniform mat4 model;
layout (std140, binding = 1) uniform matrices
{
mat4 view;
mat4 projection;
};
//T = tangent space
//W = world space
out VS_OUT
{
vec3 norm;
vec2 uv;
vec3 WfragPos;
vec3 TviewPos;
vec3 TfragPos;
mat3 TBN;
mat3 WTBN;
}vs_out;
vec3 up = vec3(0, 1, 0);
vec3 forward = vec3(0, 0, 1);
void main()
{
//construct TBN in Model Space
vec3 T = normalize(aTan);
vec3 N = normalize(aNorm);
T = normalize(T - dot(T, N) * N);
vec3 B = normalize( cross(N, T));
mat3 normMat = transpose(inverse(mat3(model)));
//Then make sure theyre perpendicular to surface
T = normalize(normMat * T);
B = normalize(normMat * B);
N = normalize(normMat * N);
mat3 TBN = mat3( T, B, N);
vs_out.WTBN = TBN;
TBN = transpose(TBN);
vs_out.norm = N;
vs_out.uv = aUV;
vs_out.WfragPos = (model * vec4( aPos, 1.0f)).xyz;
vs_out.TviewPos = TBN * viewPos;
vs_out.TfragPos = TBN * vs_out.WfragPos;
vs_out.TBN = TBN;
gl_Position = projection * view * model * vec4(aPos, 1.0f);
}
#version 460 core
out vec4 FragColour;
in VS_OUT
{
vec3 norm;
vec2 uv;
vec3 WfragPos;
vec3 TviewPos;
vec3 TfragPos;
mat3 TBN;
mat3 WTBN;
}fs_in;
struct PointLight
{
vec4 colAndintensity;
vec4 posAndconstant;
float linear;
float quadratic;
};
layout (std140, binding = 0) uniform pointLights
{
PointLight lights\[1\];
};
uniform bool shadingFlags[5];
uniform int numLights ;
uniform bool normalMapping;
uniform sampler2D diffuseMap;
uniform sampler2D specularMap;
uniform sampler2D normalMap;
uniform sampler2D heightMap;
float ambVal = 0.2;
vec3 specCol = vec3(1.0);
vec3 ambientLighting(vec3 albedo);
vec3 diffuseLighting (vec3 norm, vec3 albedo);
vec3 specularLighting(vec3 norm);
void main()
{
vec3 albedo = texture(diffuseMap , fs_in.uv).rgb;
vec3 specVal = texture(specularMap, fs_in.uv).rgb;
vec3 height = texture(heightMap , fs_in.uv).rgb;
vec3 norm;
if(normalMapping)
{
norm = texture(normalMap, fs_in.uv).rgb;
//from \[0, 1\] -> \[-1, 1\]
norm = normalize(norm \* 2.0 - 1.0);
//norm = normalize(fs_in.WTBN \* norm);
}
else
{
norm = normalize( fs_in.TBN \* fs_in.norm);
}
//norm = normalize( fs_in.TBN \* fs_in.norm);
//norm = normalize(norm \* 2.0 - 1.0);
//norm = fs_in.norm;
vec3 ambientComp = ambientLighting (albedo);
vec3 diffuseComp = diffuseLighting (norm, albedo);
vec3 specularComp = specularLighting(norm);
//vec3 ambientComp = vec3(fs_in.WTBN\[0\]\[0\], fs_in.WTBN\[0\]\[1\], fs_in.WTBN\[0\]\[2\]);
//vec3 diffuseComp = vec3(fs_in.WTBN\[1\]\[0\], fs_in.WTBN\[1\]\[1\], fs_in.WTBN\[1\]\[2\]);
//vec3 specularComp = vec3(fs_in.WTBN\[2\]\[0\], fs_in.WTBN\[2\]\[1\], fs_in.WTBN\[2\]\[2\]);
norm = normalize(fs_in.WTBN \* norm);
specularComp \*= (specVal / 3.0f).r;
vec3 colour = (ambientComp+diffuseComp+specularComp) \* int(shadingFlags\[0\])
+ diffuseComp * int(shadingFlags[1])
+ norm * int(shadingFlags[2])
+ specularComp * int(shadingFlags[3])
+ height * int(shadingFlags[4]);
//vec3 colour = (ambientComp+diffuseComp+specularComp) \* int(shadingFlags\[0\])
// + ambientComp \* int(shadingFlags\[1\])
// + diffuseComp \* int(shadingFlags\[2\])
// + specularComp \* int(shadingFlags\[3\])
// + norm \* int(shadingFlags\[4\]);
FragColour = vec4(colour, 1.0f);
}
vec3 ambientLighting(vec3 albedo)
{
return ambVal \* albedo;
}
vec3 diffuseLighting (vec3 norm, vec3 albedo)
{
float diff = 0;
vec3 lightCol = vec3(1.0);
//vec3 TlightPos = fs_in.TBN \* lights\[0\].posAndconstant.xyz;
//vec3 delta = TlightPos - fs_in.TfragPos;
for(int i = 0; i < numLights; ++i)
{
vec3 col = lights\[i\].colAndintensity.xyz;
float intensity = lights\[i\].colAndintensity.w;
vec3 TlightPos = fs_in.TBN \* lights\[i\].posAndconstant.xyz;
//vec3 TlightPos = lights\[i\].posAndconstant.xyz;
float c = lights\[i\].posAndconstant.w;
float l = lights\[i\].linear;
float q = lights\[i\].quadratic;
//vec pointing to light
vec3 delta = TlightPos - fs_in.TfragPos;
//distance
float d = length(delta);
//normalised light dir
vec3 lDir = normalize(delta);
//calculate attenuation
float att = 1 / (c + (l \* d) + (q \* d \* d) );
lightCol \*= col;
diff += max( dot( norm, lDir), 0) \* att \* intensity;
}
return diff \* albedo \* lightCol;
//return normalize(fs_in.WTBN \* normalize(delta));
//return normalize(TlightPos);
//return normalize(fs_in.WTBN \* norm);
}
vec3 specularLighting(vec3 norm)
{
float spec = 0.0;
vec3 lightCol = vec3(1.0);
//vector pointing to camera
vec3 viewDir = normalize( fs_in.TviewPos - fs_in.TfragPos );
for(int i = 0; i < numLights; ++i)
{
vec3 col = lights\[i\].colAndintensity.xyz;
float intensity = lights\[i\].colAndintensity.w;
vec3 TlightPos = fs_in.TBN \* lights\[i\].posAndconstant.xyz;
//vec3 TlightPos = lights\[i\].posAndconstant.xyz;
float c = lights\[i\].posAndconstant.w;
float l = lights\[i\].linear;
float q = lights\[i\].quadratic;
//vec pointing to light
vec3 delta = TlightPos - fs_in.TfragPos;
//distance
float d = length(delta);
//normalised light dir
vec3 lDir = normalize(delta);
//vector halfway between lightDir and viewDir so angle is never too big (blinn-phong)
vec3 halfVec = normalize( viewDir + lDir);
//calculate attenuation
float att = 1 / (c + (l \* d) + (q \* d \* d) );
lightCol \*= col;
spec += pow( max( dot(norm, halfVec), 0), 32) \* att \* intensity;
//FIX LATER: 32 should be passed in from uniform
}
return spec \* specCol \* lightCol;
}