From c194f59e171a1e58ce1704f37d99ffcd09a42433 Mon Sep 17 00:00:00 2001 From: skal Date: Mon, 2 Feb 2026 15:55:03 +0100 Subject: fix(gpu): Resolve high-DPI squished rendering and 3D shadow bugs - Implemented dynamic resolution support in all shaders and effects. - Added explicit viewport setting for all render passes to ensure correct scaling. - Fixed 3D shadow mapping by adding PLANE support and standardizing soft shadow logic. - Propagated resize events through the Effect hierarchy. - Applied project-wide code formatting. --- src/3d/renderer.cc | 47 +++++++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 18 deletions(-) (limited to 'src/3d/renderer.cc') diff --git a/src/3d/renderer.cc b/src/3d/renderer.cc index 13917b1..505cd31 100644 --- a/src/3d/renderer.cc +++ b/src/3d/renderer.cc @@ -89,10 +89,15 @@ fn sdTorus(p: vec3, t: vec2) -> f32 { return length(q) - t.y; } +fn sdPlane(p: vec3, n: vec3, h: f32) -> f32 { + return dot(p, n) + h; +} + fn get_dist(p: vec3, obj_type: f32) -> f32 { if (obj_type == 1.0) { return sdSphere(p, 0.9); } if (obj_type == 2.0) { return sdBox(p, vec3(0.7)); } if (obj_type == 3.0) { return sdTorus(p, vec2(0.6, 0.25)); } + if (obj_type == 4.0) { return sdPlane(p, vec3(0.0, 1.0, 0.0), 0.0); } return 100.0; } @@ -100,14 +105,11 @@ fn map_scene(p: vec3) -> f32 { var d = 1000.0; let count = u32(globals.params.x); - // Brute force loop over all objects for (var i = 0u; i < count; i = i + 1u) { let obj = object_data.objects[i]; let obj_type = obj.params.x; - if (obj_type <= 0.0) { continue; } // Skip non-sdf objects + if (obj_type <= 0.0) { continue; } - // Transform world p to local q - // Assuming uniform scale let center = vec3(obj.model[3].x, obj.model[3].y, obj.model[3].z); let scale = length(vec3(obj.model[0].x, obj.model[0].y, obj.model[0].z)); let mat3 = mat3x3(obj.model[0].xyz/scale, obj.model[1].xyz/scale, obj.model[2].xyz/scale); @@ -120,18 +122,18 @@ fn map_scene(p: vec3) -> f32 { } fn calc_shadow(ro: vec3, rd: vec3, tmin: f32, tmax: f32) -> f32 { - var t = tmin; var res = 1.0; - for (var i = 0; i < 30; i = i + 1) { + var t = tmin; + if (t < 0.02) { t = 0.02; } + + for (var i = 0; i < 32; i = i + 1) { let h = map_scene(ro + rd * t); - if (h < 0.001) { - return 0.0; // Hard shadow hit - } - res = min(res, 8.0 * h / t); // Soft shadow k=8 - t = t + h; + if (h < 0.001) { return 0.0; } + res = min(res, 32.0 * h / t); // Harder shadows k=32 + t = t + clamp(h, 0.01, 0.5); if (t > tmax) { break; } } - return res; + return clamp(res, 0.0, 1.0); } fn get_normal(p: vec3, obj_type: f32) -> vec3 { @@ -418,9 +420,12 @@ void Renderer3D::update_uniforms(const Scene& scene, const Camera& camera, float time) { GlobalUniforms globals; globals.view_proj = camera.get_projection_matrix() * camera.get_view_matrix(); - globals.camera_pos_time = vec4(camera.position.x, camera.position.y, camera.position.z, time); - globals.params = vec4((float)std::min((size_t)kMaxObjects, scene.objects.size()), 0.0f, 0.0f, 0.0f); - + globals.camera_pos_time = + vec4(camera.position.x, camera.position.y, camera.position.z, time); + globals.params = + vec4((float)std::min((size_t)kMaxObjects, scene.objects.size()), 0.0f, + 0.0f, 0.0f); + wgpuQueueWriteBuffer(queue_, global_uniform_buffer_, 0, &globals, sizeof(GlobalUniforms)); @@ -428,7 +433,7 @@ 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); @@ -441,6 +446,8 @@ void Renderer3D::update_uniforms(const Scene& scene, const Camera& camera, type_id = 2.0f; else if (obj.type == ObjectType::TORUS) type_id = 3.0f; + else if (obj.type == ObjectType::PLANE) + type_id = 4.0f; data.params = vec4(type_id, 0, 0, 0); obj_data.push_back(data); if (obj_data.size() >= kMaxObjects) @@ -510,9 +517,10 @@ void Renderer3D::draw(WGPURenderPassEncoder pass, const Scene& scene, if (s_debug_enabled_) { for (const auto& obj : scene.objects) { // Simple AABB approximation from scale - visual_debug_.add_box(obj.position, obj.scale, vec3(1.0f, 1.0f, 0.0f)); // Yellow boxes + visual_debug_.add_box(obj.position, obj.scale, + vec3(1.0f, 1.0f, 0.0f)); // Yellow boxes } - + // Calculate ViewProj matrix for the debug renderer mat4 view_proj = camera.get_projection_matrix() * camera.get_view_matrix(); visual_debug_.render(pass, view_proj); @@ -558,6 +566,9 @@ void Renderer3D::render(const Scene& scene, const Camera& camera, float time, WGPURenderPassEncoder pass = wgpuCommandEncoderBeginRenderPass(encoder, &pass_desc); + wgpuRenderPassEncoderSetViewport(pass, 0.0f, 0.0f, (float)width_, + (float)height_, 0.0f, 1.0f); + draw(pass, scene, camera, time); wgpuRenderPassEncoderEnd(pass); -- cgit v1.2.3