3-D SDF — sphere trace, WebGL2

A signed distance field — a sphere orbiting on a unit circle, smooth-unioned with a static box — sphere-traced in a WebGL2 fragment shader (64 iterations max, ε = 1e-3). Normals via central differences, simple diffuse + rim shading. The receipt prices the shader at iterations × pixels × ~20 f32 ops × 32 bit-ops; μ is the gap between TDP envelope and Landauer floor at GPU throughput.

view the kernel that wrote this receipt crates/mathground-view/src/sdf3d.rs
//! 3-D SDF — sphere-trace fragment shader shipped as a static GLSL ES 3.0
//! string. The Rust side counts iterations × pixels to derive a bit-op
//! estimate; the GPU does the actual work.
//!
//! Scene: smooth-union of a moving sphere and a static box. V-class L0-closed
//! given the same uniforms.

pub const VERTEX_SRC: &str = r#"#version 300 es
in vec2 a_pos;
out vec2 v_uv;
void main() {
    gl_Position = vec4(a_pos, 0.0, 1.0);
    v_uv = a_pos;
}
"#;

pub const FRAGMENT_SRC: &str = r#"#version 300 es
precision highp float;
in vec2 v_uv;
uniform float u_time;
uniform vec2  u_resolution;
out vec4 frag;

float sdSphere(vec3 p, float r) { return length(p) - r; }
float sdBox(vec3 p, vec3 b) {
    vec3 q = abs(p) - b;
    return length(max(q, 0.0)) + min(max(q.x, max(q.y, q.z)), 0.0);
}
float smin(float a, float b, float k) {
    float h = clamp(0.5 + 0.5 * (b - a) / k, 0.0, 1.0);
    return mix(b, a, h) - k * h * (1.0 - h);
}
float scene(vec3 p) {
    vec3 sp = vec3(0.7 * sin(u_time), 0.0, 0.7 * cos(u_time));
    float s = sdSphere(p - sp, 0.45);
    float b = sdBox(p, vec3(0.40));
    return smin(s, b, 0.30);
}
vec3 normal(vec3 p) {
    float e = 0.0008;
    return normalize(vec3(
        scene(p + vec3(e, 0.0, 0.0)) - scene(p - vec3(e, 0.0, 0.0)),
        scene(p + vec3(0.0, e, 0.0)) - scene(p - vec3(0.0, e, 0.0)),
        scene(p + vec3(0.0, 0.0, e)) - scene(p - vec3(0.0, 0.0, e))
    ));
}
void main() {
    vec2 uv = v_uv;
    uv.x *= u_resolution.x / u_resolution.y;
    vec3 ro = vec3(0.0, 0.0, -2.5);
    vec3 rd = normalize(vec3(uv, 1.2));
    float t = 0.0;
    bool hit = false;
    for (int i = 0; i < 64; i++) {
        vec3 p = ro + rd * t;
        float d = scene(p);
        if (d < 0.001) { hit = true; break; }
        t += d;
        if (t > 10.0) break;
    }
    if (!hit) { frag = vec4(0.03, 0.05, 0.08, 1.0); return; }
    vec3 p = ro + rd * t;
    vec3 n = normal(p);
    vec3 l = normalize(vec3(0.7, 0.7, -0.5));
    float diff = max(dot(n, l), 0.0);
    float rim = pow(1.0 - max(dot(n, -rd), 0.0), 2.0);
    vec3 col = mix(vec3(0.18, 0.55, 0.85), vec3(0.95, 0.55, 0.18), 0.5 + 0.5 * sin(u_time * 0.5));
    col = col * (0.18 + 0.82 * diff) + vec3(0.4, 0.8, 1.0) * rim * 0.35;
    frag = vec4(col, 1.0);
}
"#;

/// Estimate the bit-ops cost for one frame at `width × height` pixels.
/// Conservative: 64 march iterations × ~20 f32 ops × 32 bit-ops per pixel.
pub fn estimate_bit_ops_per_pixel() -> u64 {
    64 * 20 * 32
}

pub fn estimate_bit_ops_per_frame(w: u32, h: u32) -> u64 {
    (w as u64) * (h as u64) * estimate_bit_ops_per_pixel()
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn shaders_are_non_empty() {
        assert!(VERTEX_SRC.contains("a_pos"));
        assert!(FRAGMENT_SRC.contains("scene"));
        assert!(FRAGMENT_SRC.contains("smin"));
    }

    #[test]
    fn cost_scales_with_area() {
        let a = estimate_bit_ops_per_frame(100, 100);
        let b = estimate_bit_ops_per_frame(200, 100);
        assert_eq!(b, 2 * a);
    }
}

This is the exact Rust file compiled into the WASM module the page just loaded. Every line that runs on your device is here. The receipt is a function of this code, not a bespoke benchmark.