fn get_normal_basic(p: vec3, obj_params: vec4) -> vec3 { let obj_type = obj_params.x; if (obj_type == 1.0) { return normalize(p); } let e = vec2(0.001, 0.0); return normalize(vec3( get_dist(p + e.xyy, obj_params) - get_dist(p - e.xyy, obj_params), get_dist(p + e.yxy, obj_params) - get_dist(p - e.yxy, obj_params), get_dist(p + e.yyx, obj_params) - get_dist(p - e.yyx, obj_params) )); } // Optimized normal estimation using tetrahedron pattern (4 SDF evals instead of 6). // Slightly less accurate than central differences but faster. // Uses tetrahedral gradient approximation with corners at (±1, ±1, ±1). fn get_normal_fast(p: vec3, obj_params: vec4) -> vec3 { let obj_type = obj_params.x; if (obj_type == 1.0) { return normalize(p); } let eps = 0.0001; let k = vec2(1.0, -1.0); return normalize( k.xyy * get_dist(p + k.xyy * eps, obj_params) + k.yyx * get_dist(p + k.yyx * eps, obj_params) + k.yxy * get_dist(p + k.yxy * eps, obj_params) + k.xxx * get_dist(p + k.xxx * eps, obj_params) ); } // Distance to an Axis-Aligned Bounding Box fn aabb_sdf(p: vec3, min_p: vec3, max_p: vec3) -> f32 { let center = (min_p + max_p) * 0.5; let extent = (max_p - min_p) * 0.5; let q = abs(p - center) - extent; return length(max(q, vec3(0.0))) + min(max(q.x, max(q.y, q.z)), 0.0); }