pub const QUANTIZE_WGSL: &str = "\
fn rlx_srgb_encode(c: vec3<f32>) -> vec3<f32> {
let x = max(c, vec3<f32>(0.0));
let lo = x * 12.92;
let hi = 1.055 * pow(x, vec3<f32>(1.0 / 2.4)) - 0.055;
return select(hi, lo, x <= vec3<f32>(0.0031308));
}
fn rlx_srgb_decode(c: vec3<f32>) -> vec3<f32> {
let x = max(c, vec3<f32>(0.0));
let lo = x / 12.92;
let hi = pow((x + 0.055) / 1.055, vec3<f32>(2.4));
return select(hi, lo, x <= vec3<f32>(0.04045));
}
fn rlx_quantize(c: vec3<f32>, steps: f32) -> vec3<f32> {
let n = abs(steps);
if (n < 1.0) { return c; }
let e = rlx_srgb_encode(clamp(c, vec3<f32>(0.0), vec3<f32>(1.0)));
if (steps < 0.0) {
return select(c, vec3<f32>(0.0), e < vec3<f32>(1.0 / n));
}
return rlx_srgb_decode(floor(e * n) / n);
}
";Expand description
The feedback-field quantizer (ADR-0118), as WGSL — the one text,
emitted into every converted module by fragment_prelude and concatenated
onto the engine’s own built-in warp fragment by render/scenes/warp_mesh. A
transfer function written out twice is a transfer function that drifts.
§Why the round trip
The reference’s feedback target is 8-bit, so decay times a dim pixel
truncates to zero and a classic preset’s background stays black. This
engine’s field is Rgba16Float, nothing truncates, and every dim residual
integrates — the wash, glow, runaway and inversion Plan 0100 Phase 7 judged.
The field is linear light (ADR-0046) and the reference quantizes in its
gamma-encoded target, so the step has to be taken in the encoded domain.
One number carries the whole decision: one 8-bit sRGB step is 1/255 = 0.00392 encoded, which is 3.03e-4 in linear light. A literal 1/255 floor
applied in linear would truncate everything below encoded 0.0498 — sRGB
level ~13, thirteen times too aggressive — and would crush the dim trails
the reference keeps rather than the dimmer ones it discards.
§Why sRGB and not the reference’s own ~2.2 gamma
DX9-era MilkDrop wrote to an 8-bit target with no explicit encoding, which in
practice is a plain 2.2 power curve — and it differs from sRGB’s piecewise
one only in the near-black region this whole decision is about, so the
choice was rendered rather than assumed (ADR-0118’s Outcome, 2026-08-17).
The two agree to within one 8-bit level at every frame where the picture
reads. They part in the tail, and there sRGB’s floor lands on linear
3.03e-4 — exactly 8-bit display level 1, so what it discards is
precisely what a viewer could not have seen. The 2.2 curve floors at
(1/255)^2.2 = 5.1e-6, 59x lower, keeping six more e-foldings of invisible
light alive to accumulate. sRGB is also already here (ADR-0046).
§The lane
steps is a count, not a flag, so the look gate can A/B a tuning without
a rebuild:
|steps| < 1— off, and off is an exact identity: the early return hands back the argument, so a nativewarp_meshpreset renders the bytes it rendered before this existed.steps > 0— the decision: encode, floor tostepslevels, decode.steps < 0— ADR-0118’s Alternative D, the named fallback: floor to zero at one encoded step and leave the levels between alone. It is the half of the mechanism that does the visible work (dim residuals die instead of accumulating) without re-introducing the banding ADR-0096 dithers away. Reachable from the same lane on purpose — the fallback is a parameter change, not a rebuild.