Summary
Uneven directional shading in a WebGPU 3D renderer using Gouraud shading was caused by missing or incorrect vertex normals in the OBJ file loader. This resulted in flat shading across mesh faces instead of smooth interpolation.
Root Cause
- Missing Normals Calculation: The OBJ loader provided zero-initialized normals (
normals.push(0.0);) instead of calculating them from face geometry. - Gouraud Shading Dependency: Gouraud shading relies on per-vertex normals for interpolation, which were absent, leading to artifacting.
Why This Happens in Real Systems
- OBJ File Limitations: OBJ files may lack precomputed normals, requiring runtime calculation.
- Loader Oversights: Tutorials/examples often omit normal handling for simplicity, leading to production issues.
- Shading Model Constraints: Gouraud shading amplifies normal inaccuracies compared to per-pixel shading.
Real-World Impact
- Visual Artifacts: Meshes appear faceted instead of smooth, degrading visual quality.
- User Experience: Distracting shading issues reduce immersion in 3D applications.
- Debugging Overhead: Requires cross-system verification (loader, shaders, rendering pipeline).
Example or Code
// Corrected normal transformation in vertex shader
var n:vec3 = normalize((normalMatrix * vec4(inNormal, 0.0)).xyz);
// Corrected OBJ loader (partial)
for (let f of obj.result.models[0].faces) {
for (let v of f.vertices) {
// Calculate face normal and assign to vertices
let faceNormal = calculateFaceNormal(v1, v2, v3);
normals[v.vertexIndex * 3] = faceNormal.x;
normals[v.vertexIndex * 3 + 1] = faceNormal.y;
normals[v.vertexIndex * 3 + 2] = faceNormal.z;
}
}
How Senior Engineers Fix It
- Validate Asset Pipeline: Ensure OBJ files contain valid normals or implement runtime calculation.
- Shader Debugging: Verify normal transformation matrices and lighting equations.
- Systematic Testing: Add visual regression tests for shading artifacts.
- Documentation: Annotate loader code with normal handling requirements.
Why Juniors Miss It
- Assumption of Complete Tutorials: Relying on tutorial code without understanding underlying graphics principles.
- Focus on Shaders: Overlooking asset loading/processing as the root cause.
- Lack of Debugging Tools: Not using render visualizers to inspect normals.
- Misunderstanding Shading Models: Confusing Gouraud’s vertex-based nature with per-pixel requirements.