A problem with vertex lighting and NORMAL

Godot Version

4.4.1.stable

Question

I’m using a custom shader but for some reason, on the mesh I made in Blender (exported as gltf 2.0 with default settings which actually may also be the thing causing the issue), anything facing the x or -x axes are pitch black on the front face until the light source goes behind it. This only happens with vertex lighting enabled (and I would prefer it be enabled). I think it has something to do with the normal but I don’t know how to modify it in a way that solves the problem

I only included parts I think are relevant.

shader_type spatial;

render_mode blend_mix, depth_draw_opaque, cull_disabled, vertex_lighting;

void vertex() {
	// removing this line makes the exact same thing happen but with the y and -y axes
	// I don't remember its original purpose so this may or may not be important to keep in
	NORMAL = MODEL_NORMAL_MATRIX * NORMAL;
}

void fragment() {
	ALBEDO = vec3(1.0, 1.0, 1.0);
}

// lighting code that I took and modified from https://github.com/RustyRoboticsBV/GodotStandardLightShader/blob/master/Lambert_SchlickGGX.gdshader
float DistributionGGX(float cos_theta_m, float alpha)
{
	float alpha2 = alpha * alpha;
	float d = 1.0 + (alpha2 - 1.0) * cos_theta_m * cos_theta_m;
	return alpha2 / (PI * d * d);
}

float GeometryGGX(float NdotL, float NdotV, float alpha)
{
	return 0.5 / mix(2.0 * NdotL * NdotV, NdotL + NdotV, alpha);
}

vec3 SchlickBaseReflectivity(float metallic, float specular, vec3 albedo)
{
	float dielectric = 0.04 * specular * specular;
	return mix(vec3(dielectric), albedo, vec3(metallic));
}
	
float SchlickFresnel(float u)
{
	float m = 1.0 - u;
	float m2 = m * m;
	return m2 * m2 * m;
}

void light()
{
	// Calculate some vectors.
	vec3 lightColor = LIGHT_COLOR / PI;
	
	vec3 half = normalize(VIEW + LIGHT);
	
	float NdotL = max(dot(NORMAL, LIGHT), 0.0);
	float NdotV = max(dot(NORMAL, VIEW), 0.0);
	float NdotH = max(dot(NORMAL, half), 0.0);
	float LdotH = max(dot(LIGHT, half), 0.0);
	
	// Diffuse light (Lambert). This line I modified though it doesn't change much
	DIFFUSE_LIGHT += clamp(dot(NORMAL, LIGHT), 1.0, 1.0) * ATTENUATION * lightColor;
	
	// Specular light (Schlick-GGX).
	float ggxAlpha = ROUGHNESS * ROUGHNESS;
	float D = DistributionGGX(NdotH, ggxAlpha);
	float G = GeometryGGX(NdotL, NdotV, ggxAlpha);
	
	vec3 f0 = SchlickBaseReflectivity(METALLIC, SPECULAR_AMOUNT, ALBEDO);
	float LdotH5 = SchlickFresnel(LdotH);
	float f90 = clamp(50.0 * f0.g, 0.0, 1.0);
	vec3 F = f0 + (f90 - f0) * LdotH5;
	
	vec3 specularBRDF = max(NdotL * D * G * F, 0.0);
	SPECULAR_LIGHT += specularBRDF * LIGHT_COLOR * ATTENUATION;
}

While not a perfect solution, I figured out that it somewhat works when diffuse_lambert_wrap is added to render mode

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.