fix: flip normals when facing away from light/view — fixes cube lighting

Root cause: cube.obj has inconsistent winding order. Many faces have
normals pointing inward (e.g. back face normal = +Z instead of -Z).
With cullMode=None, both sides render, but inward normals cause:
- No diffuse lighting (NdotL < 0 → max() = 0)
- Wrong shadow bias (slope-dependent bias uses wrong NdotL)
- Inconsistent shadow edges on cube faces

Fix: in fragment shader, flip normal if dot(N,L) < 0 or dot(N,V) < 0
This is the standard approach for double-sided rendering with
non-watertight geometry or inconsistent winding order.
This commit is contained in:
emil28092005
2026-06-18 21:53:15 +03:00
parent 203c22fa98
commit 2f7430e3b1
3 changed files with 16 additions and 4 deletions
+3 -3
View File
@@ -19,12 +19,12 @@ Size=300,425
Collapsed=0
[Window][Cortex Engine Debug]
Pos=60,60
Pos=1,1
Size=226,196
Collapsed=0
[Window][Shadow Parameters]
Pos=60,60
Size=318,263
Pos=772,456
Size=507,263
Collapsed=0
@@ -17,7 +17,7 @@ layout(push_constant) uniform PC {
vec4 lightPos;
vec4 lightColor;
mat4 lightViewProj;
vec4 shadowParams; // x=bias, y=sampleRadius, z=farPlane, w=unused
vec4 shadowParams;
} pc;
const vec3 AMBIENT = vec3(0.01, 0.01, 0.02);
@@ -138,6 +138,18 @@ void main()
float dist = length(toLight);
vec3 L = toLight / max(dist, 0.001);
// Flip normal if it faces away from light (fixes inward normals from bad winding)
if (dot(N, L) < 0.0)
{
N = -N;
}
// Also flip for view direction if needed
if (dot(N, V) < 0.0)
{
N = -N;
}
float attenuation = pow(clamp(1.0 - dist / max(lightRange, 0.001), 0.0, 1.0), 2.0);
vec3 radiance = lightColor * lightIntensity * attenuation;
Binary file not shown.