MONO CHROME
A 1-bit interface layer for products that refuse to blend in. Ordered dithering on the GPU, inertial scroll, aggressive motion — two colours, infinite signal.
We deleted 16,777,214 colours. What remained was the interface.
Noise is a design failure.
Every gradient, every shadow, every 8-bit gradient band is a decision you delegated to a renderer. We took the decision back. One threshold, evaluated per pixel, per frame.
FILE: /core/bayer.tsl · 42 BYTESFn( [a] => {
const f = a => fract(a.x/2.0 + a.y*a.y*0.75);
return bayer4(a*0.5)*0.25 + f(a);
})
GPU dithering, zero textures.
Bayer 8×8 вычисляется аналитически — три sin/fract-операции. Никаких texture fetch, никаких lookup-таблиц, ноль полос памяти.
3 ALU · 0 TEX · 0 KB VRAM4096 voxels, один draw call.
InstancedBufferGeometry. Позиция и высота считаются в вершинном шейдере из per-instance атрибута и uniform времени. CPU — 0 байт на кадр.
1 DRAW CALL · GPU-DRIVEN WAVESРазрешение подстраивается само.
Скользящее среднее frame time за 30 кадров. Медленно — DPR падает до 0.75. Стабильно 60 fps — растёт до 1.5. Гистерезис защищает от осцилляции.
0.75× — 1.5× DPR · ADAPTIVEПауза когда не смотришь.
Tab скрыт → рендер стоп. Canvas ушёл из вьюпорта → 10 fps. Нет ввода 2 сек → 20 fps. Батарея не тратится на невидимое.
VISIBILITY · IO · IDLEПартитура камеры и вокселей.
Keyframe-таймлайн в JSON. ScrollProgress — единственный вход. Один источник правды для камеры, амплитуды и скорости вращения.
SCROLL → SEQUENCE → UNIFORMSNative WebGPU. Auto fallback.
WGSL на нативе, GLSL на WebGL2. Один и тот же TSL-граф компилируется в оба бэкенда. Детект и переключение — автоматически.
Get the layer- Full TSL shader source
- Single commercial project
- Community support
- MIT-ish, honestly
- Everything in PIXEL
- Unlimited commercial projects
- Theatre state files
- Priority render support
- Everything in BAYER
- White-label & redistribution
- Bespoke compute shaders
- Named engineer on Slack