diff options
| -rw-r--r-- | src/3d/renderer.cc | 56 | ||||
| -rw-r--r-- | src/tests/test_3d_render.cc | 45 |
2 files changed, 45 insertions, 56 deletions
diff --git a/src/3d/renderer.cc b/src/3d/renderer.cc index 215cd97..9f43382 100644 --- a/src/3d/renderer.cc +++ b/src/3d/renderer.cc @@ -104,21 +104,16 @@ 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; - // 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); 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; - - let dist = get_dist(q, obj_type) * scale; - d = min(d, dist); + d = min(d, get_dist(q, obj_type) * scale); } return d; } @@ -128,11 +123,9 @@ fn calc_shadow(ro: vec3<f32>, rd: vec3<f32>, tmin: f32, tmax: f32, skip_idx: u32 var t = tmin; 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, 32.0 * h / t); // Sharper shadow k=32 - t = t + h; + 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); if (t > tmax) { break; } } return clamp(res, 0.0, 1.0); @@ -156,45 +149,42 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> { var p: vec3<f32>; var normal: vec3<f32>; var base_color = in.color.rgb; - // Slanted light for better shadow visibility - let light_dir = normalize(vec3<f32>(0.5, 1.0, 0.5)); + let light_dir = normalize(vec3<f32>(1.0, 1.0, 1.0)); - if (obj_type <= 0.0) { // Rasterized object + if (obj_type <= 0.0) { // Legacy 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); - - let uv = p.xz * 0.1; - let grid_val = textureSample(noise_tex, noise_sampler, uv).r; - base_color = base_color * (0.4 + 0.6 * grid_val); - } else { // SDF object + } 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); - var t_hit = length(in.world_pos - ro); - p = ro + rd * t_hit; - let mat3 = mat3x3<f32>(obj.model[0].xyz/scale, obj.model[1].xyz/scale, obj.model[2].xyz/scale); - - var hit = false; - for (var i = 0; i < 40; i = i + 1) { + // Raymarch from camera to find exact SDF hit + var t = length(in.world_pos - ro) * 0.9; // Start slightly before the proxy hull + 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_world = get_dist(q, obj_type) * scale; - if (d_world < 0.001) { hit = true; break; } - if (d_world > 3.0 * scale) { break; } - p = p + rd * d_world; + let d = get_dist(q, obj_type) * scale; + if (d < 0.001) { break; } + t = t + d; + if (t > length(in.world_pos - ro) * 1.5) { discard; } } - if (!hit) { 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 shadow = calc_shadow(p + normal * 0.02, light_dir, 0.02, 20.0, in.instance_index); - let lighting = (max(dot(normal, light_dir), 0.0) * shadow) + 0.1; + // 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 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 11cca46..5b4593d 100644 --- a/src/tests/test_3d_render.cc +++ b/src/tests/test_3d_render.cc @@ -137,43 +137,42 @@ void setup_scene() { g_scene.clear(); srand(12345); // Fixed seed - // Large floor, use CUBE type - Object3D floor(ObjectType::CUBE); + // Large floor, use BOX type (SDF) for receiving shadows + Object3D floor(ObjectType::BOX); floor.position = vec3(0, -2.0f, 0); - 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 + floor.scale = vec3(25.0f, 0.2f, 25.0f); + floor.color = vec4(0.8f, 0.8f, 0.8f, 1.0f); g_scene.add_object(floor); - // Center object + // Large center Torus (SDF) Object3D center(ObjectType::TORUS); - center.position = vec3(0, 1.5f, 0); // Elevated - center.scale = vec3(1.5f, 1.5f, 1.5f); - center.color = vec4(1, 0, 0, 1); + center.position = vec3(0, 1.0f, 0); + center.scale = vec3(2.0f, 2.0f, 2.0f); + center.color = vec4(1, 0.2, 0.2, 1); g_scene.add_object(center); + // Moving Sphere (SDF) + Object3D sphere(ObjectType::SPHERE); + sphere.position = vec3(4.0f, 2.0f, 0); + sphere.scale = vec3(1.2f, 1.2f, 1.2f); + sphere.color = vec4(0.2, 1, 0.2, 1); + g_scene.add_object(sphere); + // Random objects - for (int i = 0; i < 30; ++i) { + for (int i = 0; i < 20; ++i) { ObjectType type = ObjectType::SPHERE; int r = rand() % 3; - if (r == 1) - type = ObjectType::TORUS; - if (r == 2) - type = ObjectType::BOX; + if (r == 1) type = ObjectType::TORUS; + if (r == 2) type = ObjectType::BOX; Object3D obj(type); float angle = (rand() % 360) * 0.01745f; - float dist = 4.0f + (rand() % 100) * 0.05f; - float height = 0.5f + (rand() % 100) * 0.04f; // Elevated - + float dist = 5.0f + (rand() % 100) * 0.08f; + float height = 0.5f + (rand() % 100) * 0.04f; obj.position = vec3(std::cos(angle) * dist, height, std::sin(angle) * dist); - - float s = 0.3f + (rand() % 100) * 0.005f; + float s = 0.4f + (rand() % 100) * 0.005f; obj.scale = vec3(s, s, s); - - obj.color = vec4((rand() % 100) / 100.0f, (rand() % 100) / 100.0f, - (rand() % 100) / 100.0f, 1.0f); - + obj.color = vec4((rand()%100)/100.0f, (rand()%100)/100.0f, (rand()%100)/100.0f, 1.0f); g_scene.add_object(obj); } } |
