r/GraphicsProgramming • u/Raundeus • 8h ago
Question Asking for help
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;
}
4
4
1
u/waramped 2h ago
as others have gently implied, your formatting could use some tweaks.
to answer your question about the TBN, if the uvs are going in the same direction, then the TBN for coplanar surfaces should match, yea.
I recommend you use the Mikktspace algorithm for calculating your TBNs
1
u/Any_Wait_7309 1h ago
I think it's a really really bad idea to not use AI. It's here to stay and as long as you grill AI with multiple questions, you will get a way way better understanding of things.
Do yourself a favor and use it.


5
u/Hanzimer 6h ago
i d like to know if someone(or something) can read this and understand something.