From 5301e00826da6ff935bd42649f153d109eaef3b6 Mon Sep 17 00:00:00 2001 From: skal Date: Sun, 8 Feb 2026 17:04:42 +0100 Subject: feat(shaders): Add optimized 4-sample SDF normal estimation Adds get_normal_fast() variant using tetrahedral gradient approximation. Performance improvement: - 4 SDF evaluations (vs 6 in get_normal_basic) - ~33% fewer distance field samples - Tetrahedron pattern: k.xyy, k.yyx, k.yxy, k.xxx where k=(1,-1) Trade-off: - Slightly less accurate than central differences method - Good for real-time rendering where performance matters - Same sphere optimization (analytical normal for obj_type == 1.0) Parameters: - epsilon: 0.0001 (vs 0.001 in basic method) - Same interface: takes position and object params Use case: Fast lighting calculations, performance-critical shaders --- assets/final/shaders/math/sdf_utils.wgsl | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'assets/final/shaders/math') diff --git a/assets/final/shaders/math/sdf_utils.wgsl b/assets/final/shaders/math/sdf_utils.wgsl index c2e49cf..3b06b93 100644 --- a/assets/final/shaders/math/sdf_utils.wgsl +++ b/assets/final/shaders/math/sdf_utils.wgsl @@ -9,6 +9,22 @@ fn get_normal_basic(p: vec3, obj_params: vec4) -> vec3 { )); } +// 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; -- cgit v1.2.3