diff options
| author | skal <pascal.massimino@gmail.com> | 2026-02-06 09:38:10 +0100 |
|---|---|---|
| committer | skal <pascal.massimino@gmail.com> | 2026-02-06 09:38:10 +0100 |
| commit | 4e10d1c0b7718509ba8197b869fc88a5f94b0630 (patch) | |
| tree | 94c793ef716e3aaf5fbf3e59baabb7bcdfefb7ef /assets/final/shaders | |
| parent | 7d60a8a9ece368e365b5c857600004298cb89526 (diff) | |
fix(shaders): Correct mesh normal transformation - remove double transpose
Fixed critical bug in normal matrix transformation causing mesh stretching
and incorrect scaling during rotation.
ROOT CAUSE:
In WGSL, mat3x3(v0, v1, v2) creates a matrix where v0, v1, v2 are COLUMNS.
When extracting rows from inv_model, the constructor already produces the
transpose. Applying transpose() again cancels out, giving incorrect normals.
ISSUE:
let normal_matrix = mat3x3(inv_model[0].xyz, inv_model[1].xyz, inv_model[2].xyz);
// This gives transpose(inv_model) already!
out.normal = normalize(transpose(normal_matrix) * in.normal);
// Double transpose = identity, wrong result
FIX:
let normal_matrix = mat3x3(inv_model[0].xyz, inv_model[1].xyz, inv_model[2].xyz);
// Already transpose(inv_model), which is the correct normal matrix
out.normal = normalize(normal_matrix * in.normal);
// Correct transformation
FILES FIXED:
- assets/final/shaders/mesh_render.wgsl:38 (mesh vertex normals)
- assets/final/shaders/renderer_3d.wgsl:185 (SDF bump-mapped normals)
RESULT:
Mesh normals now transform correctly under rotation and non-uniform scaling.
Fixes Task A (test_mesh visualization stretching bug).
handoff(Claude): Normal transformation bug fixed. Mesh should now render
correctly without stretching. Shadow bug on floor plane still remains
(separate WGSL shader issue for later investigation).
Diffstat (limited to 'assets/final/shaders')
| -rw-r--r-- | assets/final/shaders/mesh_render.wgsl | 3 | ||||
| -rw-r--r-- | assets/final/shaders/renderer_3d.wgsl | 3 |
2 files changed, 4 insertions, 2 deletions
diff --git a/assets/final/shaders/mesh_render.wgsl b/assets/final/shaders/mesh_render.wgsl index 3faf7ca..068efbc 100644 --- a/assets/final/shaders/mesh_render.wgsl +++ b/assets/final/shaders/mesh_render.wgsl @@ -34,8 +34,9 @@ fn vs_main(in: VertexInput, @builtin(instance_index) instance_index: u32) -> Ver out.world_pos = world_pos.xyz; // Use transpose of inverse for normals + // Note: mat3x3 constructor takes columns, so passing rows gives us transpose let normal_matrix = mat3x3<f32>(obj.inv_model[0].xyz, obj.inv_model[1].xyz, obj.inv_model[2].xyz); - out.normal = normalize(transpose(normal_matrix) * in.normal); + out.normal = normalize(normal_matrix * in.normal); out.uv = in.uv; out.color = obj.color; diff --git a/assets/final/shaders/renderer_3d.wgsl b/assets/final/shaders/renderer_3d.wgsl index 4733f6f..2f4f79c 100644 --- a/assets/final/shaders/renderer_3d.wgsl +++ b/assets/final/shaders/renderer_3d.wgsl @@ -181,8 +181,9 @@ fn fs_main(in: VertexOutput) -> FragmentOutput { let d_z2 = get_dist(q_z2, obj.params) - disp_strength * h_z2; let n_local = normalize(vec3<f32>(d_x1 - d_x2, d_y1 - d_y2, d_z1 - d_z2)); + // Note: mat3x3 constructor takes columns, so passing rows gives us transpose let normal_matrix = mat3x3<f32>(obj.inv_model[0].xyz, obj.inv_model[1].xyz, obj.inv_model[2].xyz); - normal = normalize(transpose(normal_matrix) * n_local); + normal = normalize(normal_matrix * n_local); // Apply texture to SDF color if (in.instance_index == 0u || obj_type == 4.0) { // Floor (index 0) or PLANE |
