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.cc73
1 files changed, 41 insertions, 32 deletions
diff --git a/src/3d/renderer.cc b/src/3d/renderer.cc
index 9f43382..80d0160 100644
--- a/src/3d/renderer.cc
+++ b/src/3d/renderer.cc
@@ -20,7 +20,7 @@ struct GlobalUniforms {
struct ObjectData {
model: mat4x4<f32>,
- model_inv_tr: mat4x4<f32>,
+ inv_model: mat4x4<f32>,
color: vec4<f32>,
params: vec4<f32>,
};
@@ -94,9 +94,9 @@ fn sdPlane(p: vec3<f32>, n: vec3<f32>, h: f32) -> f32 {
}
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 == 1.0) { return length(p) - 1.0; } // Unit Sphere
+ if (obj_type == 2.0) { return sdBox(p, vec3<f32>(1.0)); } // Unit Box
+ if (obj_type == 3.0) { return sdTorus(p, vec2<f32>(1.0, 0.4)); } // Unit Torus
if (obj_type == 4.0) { return sdPlane(p, vec3<f32>(0.0, 1.0, 0.0), 0.0); }
return 100.0;
}
@@ -104,16 +104,22 @@ fn get_dist(p: vec3<f32>, obj_type: f32) -> f32 {
fn map_scene(p: vec3<f32>, skip_idx: u32) -> f32 {
var d = 1000.0;
let count = u32(globals.params.x);
+
for (var i = 0u; i < count; i = i + 1u) {
if (i == skip_idx) { continue; }
let obj = object_data.objects[i];
let obj_type = obj.params.x;
if (obj_type <= 0.0) { continue; }
- 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);
- let q = transpose(mat3) * (p - center) / scale;
- d = min(d, get_dist(q, obj_type) * scale);
+
+ let q = (obj.inv_model * vec4<f32>(p, 1.0)).xyz;
+
+ // Extraction of approx min scale for distance normalization
+ let scale_x = length(obj.model[0].xyz);
+ let scale_y = length(obj.model[1].xyz);
+ let scale_z = length(obj.model[2].xyz);
+ let s = min(scale_x, min(scale_y, scale_z));
+
+ d = min(d, get_dist(q, obj_type) * s);
}
return d;
}
@@ -121,11 +127,13 @@ fn map_scene(p: vec3<f32>, skip_idx: u32) -> f32 {
fn calc_shadow(ro: vec3<f32>, rd: vec3<f32>, tmin: f32, tmax: f32, skip_idx: u32) -> f32 {
var res = 1.0;
var t = tmin;
+ if (t < 0.1) { t = 0.1; } // Robust bias to avoid self-shadowing
+
for (var i = 0; i < 32; i = i + 1) {
let h = map_scene(ro + rd * t, skip_idx);
if (h < 0.001) { return 0.0; }
res = min(res, 16.0 * h / t); // Standard k=16
- t = t + clamp(h, 0.01, 0.5);
+ t = t + clamp(h, 0.02, 0.5);
if (t > tmax) { break; }
}
return clamp(res, 0.0, 1.0);
@@ -151,40 +159,42 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
var base_color = in.color.rgb;
let light_dir = normalize(vec3<f32>(1.0, 1.0, 1.0));
- if (obj_type <= 0.0) { // Legacy raster path
+ if (obj_type <= 0.0) { // Raster path
p = in.world_pos;
let local_normal = normalize(cross(dpdx(in.local_pos), dpdy(in.local_pos)));
- 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);
+ // Normal transformation: multiply by transpose of inverse
+ 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) * local_normal);
} else { // SDF path
- 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 ro = globals.camera_pos_time.xyz;
let rd = normalize(in.world_pos - ro);
- // Raymarch from camera to find exact SDF hit
- var t = length(in.world_pos - ro) * 0.9; // Start slightly before the proxy hull
+ var t = length(in.world_pos - ro) * 0.9;
for (var i = 0; i < 64; i = i + 1) {
p = ro + rd * t;
- let mat3 = mat3x3<f32>(obj.model[0].xyz/scale, obj.model[1].xyz/scale, obj.model[2].xyz/scale);
- let q = transpose(mat3) * (p - center) / scale;
- let d = get_dist(q, obj_type) * scale;
- if (d < 0.001) { break; }
- t = t + d;
+ let q = (obj.inv_model * vec4<f32>(p, 1.0)).xyz;
+ let d_local = get_dist(q, obj_type);
+
+ let scale_x = length(obj.model[0].xyz);
+ let scale_y = length(obj.model[1].xyz);
+ let scale_z = length(obj.model[2].xyz);
+ let s = min(scale_x, min(scale_y, scale_z));
+ let d_world = d_local * s;
+
+ if (d_world < 0.001) { break; }
+ t = t + d_world;
if (t > length(in.world_pos - ro) * 1.5) { discard; }
}
- let mat3 = mat3x3<f32>(obj.model[0].xyz/scale, obj.model[1].xyz/scale, obj.model[2].xyz/scale);
- let q_hit = transpose(mat3) * (p - center) / scale;
- normal = normalize(mat3 * get_normal(q_hit, obj_type));
+ let q_hit = (obj.inv_model * vec4<f32>(p, 1.0)).xyz;
+ let n_local = get_normal(q_hit, obj_type);
+ 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);
}
- // Shadow ray: start from surface, march towards light
- // Use instance skipping to avoid self-shadowing artifacts
let shadow = calc_shadow(p, light_dir, 0.05, 20.0, in.instance_index);
-
let diffuse = max(dot(normal, light_dir), 0.0);
- let lighting = diffuse * (0.1 + 0.9 * shadow) + 0.1; // Ambient + Shadowed Diffuse
+ let lighting = diffuse * (0.2 + 0.8 * shadow) + 0.15;
return vec4<f32>(base_color * lighting, 1.0);
}
@@ -387,9 +397,8 @@ void Renderer3D::update_uniforms(const Scene& scene, const Camera& camera,
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);
+ // Calculate Inverse for point transformation
+ data.inv_model = data.model.inverse();
data.color = obj.color;
float type_id = 0.0f;