diff options
Diffstat (limited to 'src/shaders/render/raymarching.wgsl')
| -rw-r--r-- | src/shaders/render/raymarching.wgsl | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/src/shaders/render/raymarching.wgsl b/src/shaders/render/raymarching.wgsl new file mode 100644 index 0000000..2d6616d --- /dev/null +++ b/src/shaders/render/raymarching.wgsl @@ -0,0 +1,66 @@ +// Common functions for Signed Distance Field (SDF) raymarching. +// +// Required user-defined functions: +// - df(vec3f) -> f32 +// Distance field for single-pass rendering (rayMarch, normal, shadow) +// +// For two-pass rendering with object IDs, see raymarching_id.wgsl +// +// Provided constants: +// TOLERANCE, MAX_RAY_LENGTH, MAX_RAY_MARCHES, NORM_OFF + +const TOLERANCE: f32 = 0.0005; +const MAX_RAY_LENGTH: f32 = 20.0; +const MAX_RAY_MARCHES: i32 = 80; +const NORM_OFF: f32 = 0.005; + +// Computes the surface normal of the distance field at a point `pos`. +fn normal(pos: vec3f) -> vec3f { + let eps = vec2f(NORM_OFF, 0.0); + var nor: vec3f; + nor.x = df(pos + eps.xyy) - df(pos - eps.xyy); + nor.y = df(pos + eps.yxy) - df(pos - eps.yxy); + nor.z = df(pos + eps.yyx) - df(pos - eps.yyx); + return normalize(nor); +} + +// Performs the raymarching operation. +// Returns the distance along the ray to the surface, or MAX_RAY_LENGTH if no surface is hit. +fn rayMarch(ro: vec3f, rd: vec3f, tmin: f32) -> f32 { + var t = tmin; + for (var i = 0; i < MAX_RAY_MARCHES; i++) { + if (t > MAX_RAY_LENGTH) { + t = MAX_RAY_LENGTH; + break; + } + let d = df(ro + rd * t); + if (d < TOLERANCE) { + break; + } + t += d; + } + return t; +} + +// Computes a soft shadow for a given point. +fn shadow(lp: vec3f, ld: vec3f, mint: f32, maxt: f32) -> f32 { + let ds = 1.0 - 0.4; + var t = mint; + var nd = 1e6; + let soff = 0.05; + let smul = 1.5; + let MAX_SHD_MARCHES = 20; + + for (var i = 0; i < MAX_SHD_MARCHES; i++) { + let p = lp + ld * t; + let d = df(p); + if (d < TOLERANCE || t >= maxt) { + let sd = 1.0 - exp(-smul * max(t / maxt - soff, 0.0)); + return select(mix(sd, 1.0, smoothstep(0.0, 0.025, nd)), sd, t >= maxt); + } + nd = min(nd, d); + t += ds * d; + } + let sd = 1.0 - exp(-smul * max(t / maxt - soff, 0.0)); + return sd; +} |
