diff options
| -rw-r--r-- | src/3d/renderer.cc | 45 | ||||
| -rw-r--r-- | src/tests/test_3d_render.cc | 16 |
2 files changed, 27 insertions, 34 deletions
diff --git a/src/3d/renderer.cc b/src/3d/renderer.cc index db50a35..9f3f40c 100644 --- a/src/3d/renderer.cc +++ b/src/3d/renderer.cc @@ -109,6 +109,7 @@ fn map_scene(p: vec3<f32>, skip_idx: u32) -> f32 { if (i == skip_idx) { continue; } let obj = object_data.objects[i]; let obj_type = obj.params.x; + // Skip rasterized objects (like the floor) in the SDF map if (obj_type <= 0.0) { continue; } let center = vec3<f32>(obj.model[3].x, obj.model[3].y, obj.model[3].z); @@ -125,16 +126,16 @@ 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.05) { t = 0.05; } // Avoid self-shadowing - - for (var i = 0; i < 32; i = i + 1) { + for (var i = 0; i < 30; 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); // Soft shadow k=16 - t = t + clamp(h, 0.02, 0.5); + if (h < 0.001) { + return 0.0; + } + res = min(res, 8.0 * h / t); // Soft shadow k=8 + t = t + h; if (t > tmax) { break; } } - return clamp(res, 0.0, 1.0); + return res; } fn get_normal(p: vec3<f32>, obj_type: f32) -> vec3<f32> { @@ -155,14 +156,17 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> { var p: vec3<f32>; var normal: vec3<f32>; var base_color = in.color.rgb; - // Tilted light for longer, more visible shadows - let light_dir = normalize(vec3<f32>(1.0, 1.0, 1.0)); + let light_dir = normalize(vec3<f32>(0.2, 1.0, 0.2)); - if (obj_type <= 0.0) { // Rasterized object (legacy path) + if (obj_type <= 0.0) { // Rasterized object 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); + + 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 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)); @@ -174,13 +178,11 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> { let mat3 = mat3x3<f32>(obj.model[0].xyz/scale, obj.model[1].xyz/scale, obj.model[2].xyz/scale); var hit = false; - // Raymarch into the proxy box to find the SDF surface - for (var i = 0; i < 64; i = i + 1) { + for (var i = 0; i < 40; i = i + 1) { let q = transpose(mat3) * (p - center) / scale; - let d_local = get_dist(q, obj_type); - let d_world = d_local * scale; + let d_world = get_dist(q, obj_type) * scale; if (d_world < 0.001) { hit = true; break; } - if (d_world > 3.0 * scale) { break; } // Out of proxy box bounds + if (d_world > 3.0 * scale) { break; } p = p + rd * d_world; } @@ -188,19 +190,10 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> { let q_hit = transpose(mat3) * (p - center) / scale; normal = normalize(mat3 * get_normal(q_hit, obj_type)); - - // Optional: procedural grid for all objects, but mainly for the floor - if (obj_type == 4.0) { // Plane - let uv = p.xz * 0.2; - let grid = 0.5 + 0.5 * sin(uv.x * 3.14 * 2.0) * sin(uv.y * 3.14 * 2.0); - base_color = base_color * (0.6 + 0.4 * smoothstep(0.45, 0.55, grid)); - } } - // Shadow ray start from hit point p - let shadow = calc_shadow(p, light_dir, 0.1, 20.0, in.instance_index); - // Darken shadowed areas significantly - let lighting = (max(dot(normal, light_dir), 0.0) * (0.2 + 0.8 * shadow)) + 0.1; + let shadow = calc_shadow(p + normal * 0.01, light_dir, 0.01, 20.0, in.instance_index); + let lighting = (max(dot(normal, light_dir), 0.0) * shadow) + 0.1; return vec4<f32>(base_color * lighting, 1.0); } diff --git a/src/tests/test_3d_render.cc b/src/tests/test_3d_render.cc index 141b1b7..f98ee7c 100644 --- a/src/tests/test_3d_render.cc +++ b/src/tests/test_3d_render.cc @@ -137,18 +137,18 @@ void setup_scene() { g_scene.clear(); srand(12345); // Fixed seed - // Large floor, use PLANE type - Object3D floor(ObjectType::PLANE); + // Large floor, use CUBE type + Object3D floor(ObjectType::CUBE); floor.position = vec3(0, -2.0f, 0); - floor.scale = vec3(100.0f, 1.0f, 100.0f); + floor.scale = vec3(50.0f, 0.5f, 50.0f); floor.color = vec4(0.9f, 0.9f, 0.9f, 1.0f); // Brighter white for better shadow contrast g_scene.add_object(floor); // Center object Object3D center(ObjectType::TORUS); - center.position = vec3(0, 1.0f, 0); // Higher - center.scale = vec3(2.5f, 2.5f, 2.5f); // Larger + center.position = vec3(0, 0, 0); + center.scale = vec3(1.5f, 1.5f, 1.5f); center.color = vec4(1, 0, 0, 1); g_scene.add_object(center); @@ -163,12 +163,12 @@ void setup_scene() { Object3D obj(type); float angle = (rand() % 360) * 0.01745f; - float dist = 4.0f + (rand() % 100) * 0.06f; - float height = 0.5f + (rand() % 100) * 0.04f; // Higher + float dist = 4.0f + (rand() % 100) * 0.05f; + float height = -1.0f + (rand() % 100) * 0.04f; obj.position = vec3(std::cos(angle) * dist, height, std::sin(angle) * dist); - float s = 0.5f + (rand() % 100) * 0.005f; + float s = 0.3f + (rand() % 100) * 0.005f; obj.scale = vec3(s, s, s); obj.color = vec4((rand() % 100) / 100.0f, (rand() % 100) / 100.0f, |
