fp64 checker plane
A 1-unit checkerboard on a world plane.
// ═══ typeshade example — fp64 world-plane checkerboard ═══//// The map-engine failure mode in its purest form: a 1×1-unit checkerboard on// a world plane, viewed 100 million units from the origin (ulp_f32(1e8) = 8 —// EIGHT whole cells wide). The tile grid is recovered with floor/fract ON THE// f64 TYPE (both are in the df64 whitelist): parity = fract((⌊x⌋+⌊y⌋)/2)// stays exact because ⌊x⌋ at 1e8 does not FIT in an f32 — narrowing first is// precisely the bug. The plain-f32 left half only ever sees the coordinate in// 8-cell steps — parity never flips and the checker collapses FLAT; the f64// right half stays a crisp checkerboard with anti-aliased cell borders.//// The `_fp64` guard uniform is auto-injected by the lowering; the render// harnesses bind it to 1.0f by probing the program for the Fp64Guard block.
import { fn, module, vec3, vec4, f32, pow, floor, fract, min, mix, step, smoothstep, toF32, toF64, f32T, vec2fT, vec2f64T, Let, uniformStruct,} from '../src/index.js';import { VsOut, vs } from './_fullscreen.js';import type { ShaderExample } from './_shared.js';
const U = uniformStruct( 'Uniforms', { group: 0, binding: 0, as: 'u' }, { center: vec2f64T, // one DF64Vec2 slot — host packs [hi.x, hi.y, lo.x, lo.y] resolution: vec2fT, zoom_exp: f32T, // view span = 10^-zoom_exp world units (negative = zoom out) fp64: f32T, // toggle: 1 = split-screen f32 | f64 (canonical), 0 = all-f32 },);
const fsChecker = fn( 'fs_checker', { vo: VsOut }, (p) => { const span = Let(pow(f32(10.0), U.field.zoom_exp.neg())); const half = Let(p.vo.uv.x.mul(2.0)); const sx = Let(half.sub(p.vo.uv.x.lt(0.5).select(0.0, 1.0))); const dx = Let(sx.sub(0.5).mul(span)); const dy = Let( p.vo.uv.y.sub(0.5).mul(span).mul(U.field.resolution.y.div(U.field.resolution.x).mul(2.0)), );
const isF32 = Let(p.vo.uv.x.lt(0.5).or(U.field.fp64.lt(0.5))); // f64 path — floor/fract in extended precision; only RESULTS narrow // (cell parity is 0/0.5 exactly; the in-cell fraction is sub-unit). const px = Let(U.field.center.x.add(toF64(dx))); const py = Let(U.field.center.y.add(toF64(dy))); const par64 = Let(toF32(fract(floor(px).add(floor(py)).mul(0.5)))); const fx64 = Let(toF32(fract(px))); const fy64 = Let(toF32(fract(py))); // f32 twin — SAME formulas, world coordinate narrowed first: at 1e8 the // coordinate moves in 8-cell steps, so parity NEVER flips (always even) // and the fraction is identically 0 — the half renders flat. const px32 = Let(toF32(U.field.center.x).add(dx)); const py32 = Let(toF32(U.field.center.y).add(dy)); const par32 = Let(fract(floor(px32).add(floor(py32)).mul(0.5))); const fx32 = Let(fract(px32)); const fy32 = Let(fract(py32));
const par = Let(isF32.select(par32, par64)); const fx = Let(isF32.select(fx32, fx64)); const fy = Let(isF32.select(fy32, fy64));
// Two-tone slate/ivory checker + anti-aliased cell borders. The AA width // comes from the analytic pixel size in WORLD units (span / half-width in // px) — fwidth(fract(x)) would spike across the cell seam itself. const chk = Let(step(0.25, par)); const edge = Let(min(min(fx, f32(1).sub(fx)), min(fy, f32(1).sub(fy)))); const pixw = Let(span.div(U.field.resolution.x.mul(0.5))); const line = Let(smoothstep(f32(0), pixw.mul(1.5).add(1e-9), edge)); const ivory = vec3(0.93, 0.9, 0.82); const slate = vec3(0.23, 0.29, 0.36); const rgb = mix(ivory, slate, chk).mul(mix(f32(0.35), f32(1.0), line)); return vec4(rgb, f32(1)); }, { stage: 'fragment', retAttr: '@location(0)' },);
// `_fp64` guard lands at (group 0, binding 1) automatically.const fp64CheckerPlaneModule = module({ funcs: [vs, fsChecker], uses: [U, VsOut],});
export const fp64CheckerPlane: ShaderExample = { id: 'fp64-checker-plane', title: 'fp64 checker plane', blurb: 'A 1-unit checkerboard on a world plane. Drag the DISTANCE slider (or wheel) to carry the plane out from the origin: near 10⁶ both halves are a crisp checker, but past ~10⁷·² one f32 ulp grows wider than a cell and the plain-f32 left half collapses flat (parity can no longer flip) — while the f64 right half, doing floor/fract on the emulated-double type, keeps cell parity and anti-aliased borders all the way to 10⁹. Watch the exact distance where f32 gives out; flip the fp64 toggle to collapse the right half too.', category: 'cartographic', file: 'fp64-checker-plane.ts', module: fp64CheckerPlaneModule, renderable: true, splitLabels: ['f32', 'f64 (emulated)'], controls: { // Sweep the plane's distance from the origin: base·10^mag + offset (the // fractional offset is the sub-cell detail f32 loses first). At mag = 8 this // is the classic 10⁸ view; drop to 6 and f32 is fine — the point is the // THRESHOLD in between, which the viewer drives. center: { kind: 'logmag2d', magField: 'mag', base: [1, 0.5], offset: [0.3, 0.7] }, resolution: { kind: 'resolution' }, mag: { kind: 'slider', label: 'Distance from origin 10^x', min: 4, max: 9, step: 0.02, value: 6, wheel: true, }, // View span across each half (10^-zoom_exp world units ≈ number of cells). zoom_exp: { kind: 'slider', label: 'Zoom 10^-x', min: -2, max: 5, step: 0.05, value: -0.9, }, fp64: { kind: 'toggle', label: 'fp64 emulation', value: true }, },};struct Uniforms { @align(16) center: DF64Vec2, resolution: vec2<f32>, zoom_exp: f32, fp64: f32,}
struct VsOut { @builtin(position) pos: vec4<f32>, @location(0) uv: vec2<f32>,}
struct DF64Vec2 { hi: vec2<f32>, lo: vec2<f32>,}
@group(0) @binding(0) var<uniform> u: Uniforms;@group(0) @binding(1) var _fp64: texture_2d<f32>;
@vertexfn vs(@builtin(vertex_index) vi: u32) -> VsOut { let _cse0 = ((f32((vi & 1u)) * 4.0) - 1.0); let _cse1 = ((f32((vi >> 1u)) * 4.0) - 1.0); return VsOut(vec4<f32>(_cse0, _cse1, 0.0, 1.0), vec2<f32>(((_cse0 * 0.5) + 0.5), ((_cse1 * 0.5) + 0.5)));}
@fragmentfn fs_checker(vo: VsOut) -> @location(0) vec4<f32> { let _fp64_g = textureLoad(_fp64, vec2<i32>(0, 0), 0).x; let _v0 = pow(10.0, (-u.zoom_exp)); let _v1 = (vo.uv.x * 2.0); let _cse0 = (vo.uv.x < 0.5); let _v2 = (_v1 - select(1.0, 0.0, _cse0)); let _v3 = ((_v2 - 0.5) * _v0); let _v4 = (((vo.uv.y - 0.5) * _v0) * ((u.resolution.y / u.resolution.x) * 2.0)); let _v5 = (_cse0 || (u.fp64 < 0.5)); let _cse1 = vec2<f32>(u.center.hi.x, u.center.lo.x); let _v6 = df64_add(_cse1, vec2<f32>(_v3, 0.0), _fp64_g); let _cse2 = vec2<f32>(u.center.hi.y, u.center.lo.y); let _v7 = df64_add(_cse2, vec2<f32>(_v4, 0.0), _fp64_g); let _v8 = df64_narrow(df64_fract((df64_add(df64_floor(_v6, _fp64_g), df64_floor(_v7, _fp64_g), _fp64_g) * 0.5), _fp64_g)); let _cse4 = bitcast<f32>(bitcast<u32>(0.0)); let _cse3 = vec2<f32>(_cse4, _cse4); let _v9 = df64_narrow(df64_fract(df64_add(_v6, _cse3, _fp64_g), _fp64_g)); let _v10 = df64_narrow(df64_fract(df64_add(_v7, _cse3, _fp64_g), _fp64_g)); let _v11 = (df64_narrow(_cse1) + _v3); let _v12 = (df64_narrow(_cse2) + _v4); let _v13 = fract(((floor(_v11) + floor(_v12)) * 0.5)); let _v14 = fract(_v11); let _v15 = fract(_v12); let _v16 = select(_v8, _v13, _v5); let _v17 = select(_v9, _v14, _v5); let _v18 = select(_v10, _v15, _v5); let _v19 = step(0.25, _v16); let _v20 = min(min(_v17, (1.0 - _v17)), min(_v18, (1.0 - _v18))); let _v21 = (_v0 / (u.resolution.x * 0.5)); let _v22 = smoothstep(0.0, ((_v21 * 1.5) + 1e-9), _v20); return vec4<f32>((mix(vec3<f32>(0.93, 0.9, 0.82), vec3<f32>(0.23, 0.29, 0.36), _v19) * mix(0.35, 1.0, _v22)), 1.0);}
fn df64_twoSum(a: f32, b: f32, _fp64_g: f32) -> vec2<f32> { let _v0 = (a + b); let _v1 = (((_v0 * _fp64_g) - a) * _fp64_g); let _v2 = (((a - ((_v0 - _v1) * _fp64_g)) * _fp64_g) + (b - _v1)); return vec2<f32>(_v0, _v2);}
fn df64_quickTwoSum(a: f32, b: f32, _fp64_g: f32) -> vec2<f32> { let _v0 = ((a + b) * _fp64_g); let _v1 = (b - ((_v0 - a) * _fp64_g)); return vec2<f32>(_v0, _v1);}
fn df64_add(a: vec2<f32>, b: vec2<f32>, _fp64_g: f32) -> vec2<f32> { var _v0: vec2<f32> = df64_twoSum(a.x, b.x, _fp64_g); let _v1 = df64_twoSum(a.y, b.y, _fp64_g); _v0.y = (_v0.y + _v1.x); _v0 = df64_quickTwoSum(_v0.x, _v0.y, _fp64_g); _v0.y = (_v0.y + _v1.y); _v0 = df64_quickTwoSum(_v0.x, _v0.y, _fp64_g); return _v0;}
fn df64_sub(a: vec2<f32>, b: vec2<f32>, _fp64_g: f32) -> vec2<f32> { return df64_add(a, (-b), _fp64_g);}
fn df64_floor(a: vec2<f32>, _fp64_g: f32) -> vec2<f32> { let _v0 = floor(a.x); return select(vec2<f32>(_v0, 0.0), df64_quickTwoSum(_v0, floor(a.y), _fp64_g), (_v0 == a.x));}
fn df64_fract(a: vec2<f32>, _fp64_g: f32) -> vec2<f32> { return df64_sub(a, df64_floor(a, _fp64_g), _fp64_g);}
fn df64_narrow(a: vec2<f32>) -> f32 { return (a.x + a.y);}#version 300 esprecision highp float;precision highp int;
out vec2 uv;
void main() { uint vi = uint(gl_VertexID); float _cse0 = ((float((vi & 1u)) * 4.0) - 1.0); float _cse1 = ((float((vi >> 1u)) * 4.0) - 1.0); gl_Position = vec4(_cse0, _cse1, 0.0, 1.0); uv = vec2(((_cse0 * 0.5) + 0.5), ((_cse1 * 0.5) + 0.5));}#version 300 esprecision highp float;precision highp int;
struct DF64Vec2 { vec2 hi; vec2 lo;};layout(std140) uniform Uniforms { DF64Vec2 center; vec2 resolution; float zoom_exp; float fp64;} u;
uniform highp sampler2D _fp64;vec2 df64_twoSum(float a, float b, float _fp64_g) { float _v0 = (a + b); float _v1 = (((_v0 * _fp64_g) - a) * _fp64_g); float _v2 = (((a - ((_v0 - _v1) * _fp64_g)) * _fp64_g) + (b - _v1)); return vec2(_v0, _v2);}
vec2 df64_quickTwoSum(float a, float b, float _fp64_g) { float _v0 = ((a + b) * _fp64_g); float _v1 = (b - ((_v0 - a) * _fp64_g)); return vec2(_v0, _v1);}
vec2 df64_add(vec2 a, vec2 b, float _fp64_g) { vec2 _v0 = df64_twoSum(a.x, b.x, _fp64_g); vec2 _v1 = df64_twoSum(a.y, b.y, _fp64_g); _v0.y = (_v0.y + _v1.x); _v0 = df64_quickTwoSum(_v0.x, _v0.y, _fp64_g); _v0.y = (_v0.y + _v1.y); _v0 = df64_quickTwoSum(_v0.x, _v0.y, _fp64_g); return _v0;}
vec2 df64_sub(vec2 a, vec2 b, float _fp64_g) { return df64_add(a, (-b), _fp64_g);}
vec2 df64_floor(vec2 a, float _fp64_g) { float _v0 = floor(a.x); return ((_v0 == a.x) ? df64_quickTwoSum(_v0, floor(a.y), _fp64_g) : vec2(_v0, 0.0));}
vec2 df64_fract(vec2 a, float _fp64_g) { return df64_sub(a, df64_floor(a, _fp64_g), _fp64_g);}
float df64_narrow(vec2 a) { return (a.x + a.y);}in vec2 uv;layout(location = 0) out vec4 _ret;
void main() { float _fp64_g = texelFetch(_fp64, ivec2(0, 0), 0).x; float _v0 = pow(10.0, (-u.zoom_exp)); float _v1 = (uv.x * 2.0); bool _cse0 = (uv.x < 0.5); float _v2 = (_v1 - (_cse0 ? 0.0 : 1.0)); float _v3 = ((_v2 - 0.5) * _v0); float _v4 = (((uv.y - 0.5) * _v0) * ((u.resolution.y / u.resolution.x) * 2.0)); bool _v5 = (_cse0 || (u.fp64 < 0.5)); vec2 _cse1 = vec2(u.center.hi.x, u.center.lo.x); vec2 _v6 = df64_add(_cse1, vec2(_v3, 0.0), _fp64_g); vec2 _cse2 = vec2(u.center.hi.y, u.center.lo.y); vec2 _v7 = df64_add(_cse2, vec2(_v4, 0.0), _fp64_g); float _v8 = df64_narrow(df64_fract((df64_add(df64_floor(_v6, _fp64_g), df64_floor(_v7, _fp64_g), _fp64_g) * 0.5), _fp64_g)); float _cse4 = uintBitsToFloat(floatBitsToUint(0.0)); vec2 _cse3 = vec2(_cse4, _cse4); float _v9 = df64_narrow(df64_fract(df64_add(_v6, _cse3, _fp64_g), _fp64_g)); float _v10 = df64_narrow(df64_fract(df64_add(_v7, _cse3, _fp64_g), _fp64_g)); float _v11 = (df64_narrow(_cse1) + _v3); float _v12 = (df64_narrow(_cse2) + _v4); float _v13 = fract(((floor(_v11) + floor(_v12)) * 0.5)); float _v14 = fract(_v11); float _v15 = fract(_v12); float _v16 = (_v5 ? _v13 : _v8); float _v17 = (_v5 ? _v14 : _v9); float _v18 = (_v5 ? _v15 : _v10); float _v19 = step(0.25, _v16); float _v20 = min(min(_v17, (1.0 - _v17)), min(_v18, (1.0 - _v18))); float _v21 = (_v0 / (u.resolution.x * 0.5)); float _v22 = smoothstep(0.0, ((_v21 * 1.5) + 1e-9), _v20); _ret = vec4((mix(vec3(0.93, 0.9, 0.82), vec3(0.23, 0.29, 0.36), _v19) * mix(0.35, 1.0, _v22)), 1.0);}This example is steered by a control the page has no value for, so the page shows no picture.
The WGSL and GLSL tabs are the compiler's own output at commit 26de7be8, read from the goldens its emit suite bakes (emit-goldens.test.ts).
This example is written against the fn() builder API, which the editor in the Playground does not take.