summaryrefslogtreecommitdiff
path: root/src/3d/renderer.cc
diff options
context:
space:
mode:
authorskal <pascal.massimino@gmail.com>2026-02-02 15:55:03 +0100
committerskal <pascal.massimino@gmail.com>2026-02-02 15:55:03 +0100
commitc194f59e171a1e58ce1704f37d99ffcd09a42433 (patch)
treef77a32f2c4c23b335209b8df11cc82920388b51a /src/3d/renderer.cc
parent316825883c705ed0fe927c32e072f98141d3eaa3 (diff)
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.
Diffstat (limited to 'src/3d/renderer.cc')
-rw-r--r--src/3d/renderer.cc47
1 files changed, 29 insertions, 18 deletions
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<f32>, t: vec2<f32>) -> f32 {
return length(q) - t.y;
}
+fn sdPlane(p: vec3<f32>, n: vec3<f32>, h: f32) -> f32 {
+ return dot(p, n) + h;
+}
+
fn get_dist(p: vec3<f32>, obj_type: f32) -> f32 {
if (obj_type == 1.0) { return sdSphere(p, 0.9); }
if (obj_type == 2.0) { return sdBox(p, vec3<f32>(0.7)); }
if (obj_type == 3.0) { return sdTorus(p, vec2<f32>(0.6, 0.25)); }
+ if (obj_type == 4.0) { return sdPlane(p, vec3<f32>(0.0, 1.0, 0.0), 0.0); }
return 100.0;
}
@@ -100,14 +105,11 @@ fn map_scene(p: vec3<f32>) -> 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<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));
let mat3 = mat3x3<f32>(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>) -> f32 {
}
fn calc_shadow(ro: vec3<f32>, rd: vec3<f32>, 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<f32>, obj_type: f32) -> vec3<f32> {
@@ -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);