summaryrefslogtreecommitdiff
path: root/src/3d/renderer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/3d/renderer.cc')
-rw-r--r--src/3d/renderer.cc14
1 files changed, 10 insertions, 4 deletions
diff --git a/src/3d/renderer.cc b/src/3d/renderer.cc
index 267c165..b655588 100644
--- a/src/3d/renderer.cc
+++ b/src/3d/renderer.cc
@@ -20,6 +20,7 @@ struct GlobalUniforms {
struct ObjectData {
model: mat4x4<f32>,
+ model_inv_tr: mat4x4<f32>,
color: vec4<f32>,
params: vec4<f32>,
};
@@ -152,13 +153,13 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
var normal: vec3<f32>;
let light_dir = normalize(vec3<f32>(1.0, 1.0, 1.0));
- if (obj_type == 0.0) { // Rasterized object (like the floor)
+ if (obj_type == 0.0) { // Rasterized object
p = in.world_pos;
let local_normal = normalize(cross(dpdx(in.local_pos), dpdy(in.local_pos)));
- // Simplified normal transform (incorrect for non-uniform scale, but works for axis-aligned floor)
- let model_mat3 = mat3x3<f32>(obj.model[0].xyz, obj.model[1].xyz, obj.model[2].xyz);
- normal = normalize(model_mat3 * local_normal);
+ // Correct normal transformation using inverse transpose
+ let mat3_it = mat3x3<f32>(obj.model_inv_tr[0].xyz, obj.model_inv_tr[1].xyz, obj.model_inv_tr[2].xyz);
+ normal = normalize(mat3_it * local_normal);
} else { // SDF object
let center = vec3<f32>(obj.model[3].x, obj.model[3].y, obj.model[3].z);
let scale = length(vec3<f32>(obj.model[0].x, obj.model[0].y, obj.model[0].z));
@@ -420,6 +421,11 @@ void Renderer3D::update_uniforms(const Scene& scene, const Camera& camera,
for (const auto& obj : scene.objects) {
ObjectData data;
data.model = obj.get_model_matrix();
+
+ // Calculate Inverse Transpose for correct normal transformation
+ mat4 inverse = data.model.inverse();
+ data.model_inverse_transpose = mat4::transpose(inverse);
+
data.color = obj.color;
float type_id = 0.0f;
if (obj.type == ObjectType::SPHERE)