From 2184a1043d1a071cdc78303b2247145bf3f18c0b Mon Sep 17 00:00:00 2001 From: skal Date: Mon, 2 Feb 2026 16:46:59 +0100 Subject: fix(3d): Correct debug box transforms and restore object textures - Updated VisualDebug to accept mat4 transforms, enabling wireframes to follow rotating objects. - Restored SDF bump mapping and floor grid texture in the fragment shader. - Added vec4::xyz() helper to mini_math.h. - Fixed Renderer3D to pass the full model matrix for debug visualization. --- src/3d/renderer.cc | 46 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 4 deletions(-) (limited to 'src/3d/renderer.cc') diff --git a/src/3d/renderer.cc b/src/3d/renderer.cc index 80d0160..021374a 100644 --- a/src/3d/renderer.cc +++ b/src/3d/renderer.cc @@ -162,9 +162,13 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4 { if (obj_type <= 0.0) { // Raster path p = in.world_pos; let local_normal = normalize(cross(dpdx(in.local_pos), dpdy(in.local_pos))); - // Normal transformation: multiply by transpose of inverse let normal_matrix = mat3x3(obj.inv_model[0].xyz, obj.inv_model[1].xyz, obj.inv_model[2].xyz); normal = normalize(transpose(normal_matrix) * local_normal); + + // Apply grid texture to floor (type 0 is floor in test_3d_render) + let uv = p.xz * 0.1; + let grid_val = textureSample(noise_tex, noise_sampler, uv).r; + base_color = base_color * (0.3 + 0.7 * grid_val); } else { // SDF path let ro = globals.camera_pos_time.xyz; let rd = normalize(in.world_pos - ro); @@ -187,7 +191,42 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4 { } let q_hit = (obj.inv_model * vec4(p, 1.0)).xyz; - let n_local = get_normal(q_hit, obj_type); + + // Calculate normal with bump mapping + let e = vec2(0.005, 0.0); + let disp_strength = 0.05; + + let q_x1 = q_hit + e.xyy; + let uv_x1 = vec2(atan2(q_x1.x, q_x1.z) / 6.28 + 0.5, acos(clamp(q_x1.y / length(q_x1), -1.0, 1.0)) / 3.14); + let h_x1 = textureSample(noise_tex, noise_sampler, uv_x1).r; + let d_x1 = get_dist(q_x1, obj_type) - disp_strength * h_x1; + + let q_x2 = q_hit - e.xyy; + let uv_x2 = vec2(atan2(q_x2.x, q_x2.z) / 6.28 + 0.5, acos(clamp(q_x2.y / length(q_x2), -1.0, 1.0)) / 3.14); + let h_x2 = textureSample(noise_tex, noise_sampler, uv_x2).r; + let d_x2 = get_dist(q_x2, obj_type) - disp_strength * h_x2; + + let q_y1 = q_hit + e.yxy; + let uv_y1 = vec2(atan2(q_y1.x, q_y1.z) / 6.28 + 0.5, acos(clamp(q_y1.y / length(q_y1), -1.0, 1.0)) / 3.14); + let h_y1 = textureSample(noise_tex, noise_sampler, uv_y1).r; + let d_y1 = get_dist(q_y1, obj_type) - disp_strength * h_y1; + + let q_y2 = q_hit - e.yxy; + let uv_y2 = vec2(atan2(q_y2.x, q_y2.z) / 6.28 + 0.5, acos(clamp(q_y2.y / length(q_y2), -1.0, 1.0)) / 3.14); + let h_y2 = textureSample(noise_tex, noise_sampler, uv_y2).r; + let d_y2 = get_dist(q_y2, obj_type) - disp_strength * h_y2; + + let q_z1 = q_hit + e.yyx; + let uv_z1 = vec2(atan2(q_z1.x, q_z1.z) / 6.28 + 0.5, acos(clamp(q_z1.y / length(q_z1), -1.0, 1.0)) / 3.14); + let h_z1 = textureSample(noise_tex, noise_sampler, uv_z1).r; + let d_z1 = get_dist(q_z1, obj_type) - disp_strength * h_z1; + + let q_z2 = q_hit - e.yyx; + let uv_z2 = vec2(atan2(q_z2.x, q_z2.z) / 6.28 + 0.5, acos(clamp(q_z2.y / length(q_z2), -1.0, 1.0)) / 3.14); + let h_z2 = textureSample(noise_tex, noise_sampler, uv_z2).r; + let d_z2 = get_dist(q_z2, obj_type) - disp_strength * h_z2; + + let n_local = normalize(vec3(d_x1 - d_x2, d_y1 - d_y2, d_z1 - d_z2)); let normal_matrix = mat3x3(obj.inv_model[0].xyz, obj.inv_model[1].xyz, obj.inv_model[2].xyz); normal = normalize(transpose(normal_matrix) * n_local); } @@ -478,8 +517,7 @@ void Renderer3D::draw(WGPURenderPassEncoder pass, const Scene& scene, #if !defined(STRIP_ALL) if (s_debug_enabled_) { for (const auto& obj : scene.objects) { - // Simple AABB approximation from scale - visual_debug_.add_box(obj.position, obj.scale, + visual_debug_.add_box(obj.get_model_matrix(), vec3(1.0f, 1.0f, 0.0f)); // Yellow boxes } -- cgit v1.2.3