| name | add-crt-effect |
| description | Stack fullscreen post-process effects (CRT curvature, scanlines, bloom, glitch) on top of the finished frame, which runs on WebGPU only. Use for a retro CRT look, screen glitches, bloom or glow, or any whole-screen filter. |
Add a CRT or post-process effect
Stack fullscreen effects (CRT curvature, scanlines, bloom, glitch) on top of the finished frame. These run on WebGPU
only.
When to use
Use for a retro CRT look, screen glitches, bloom or glow, or any whole-screen filter.
Step 1: a bigger output buffer
Display-tier effects (curvature, scanlines, mask, bloom) need an output buffer larger than the logical screen, set in
configure():
configure() {
return {
displaySize: new Vector2i(320, 240),
drawingBufferSize: new Vector2i(1280, 960),
};
}
Step 2: guard the software fallback, then add effects
Post-process throws on the Canvas 2D fallback, so check the active backend first:
async init() {
if (BT.activeBackend === 'webgpu') {
this.crt = BT.preset.crtPipBoy();
for (const fx of this.crt) BT.effectAdd(fx);
}
return true;
}
Turn it off again (guard the same way – this.crt is never set on the software fallback):
if (this.crt) {
for (const fx of this.crt) BT.effectRemove(fx);
}
BT.effectClear();
Key calls
BT.effectAdd(effect) / BT.effectRemove(effect) / BT.effectClear() – methods.
- Presets (functions on
BT.preset): BT.preset.crtPipBoy(), BT.preset.amber(), BT.preset.green() – each returns a
fresh array of effects.
- Effect classes you can construct, tweak, then
effectAdd: display-tier Scanlines, BarrelDistortion, Bloom,
Vignette, RGBMask, ChromaticAberration, Noise, Flicker, Interference, RollLine; pixel-tier
PixelGlitch, PixelMosaic.
import { Scanlines } from 'blit386';
const lines = new Scanlines();
lines.strength = 0.4;
BT.effectAdd(lines);
Notes
- Always gate effects behind
BT.activeBackend === 'webgpu' so the game still runs on the software fallback. Keep
starter games effect-free.
- Gate on
BT.activeBackend, never on BT.requestedBackend. requestedBackend is the backend you asked for, and
it still says 'webgpu' even after the engine has quietly fallen back to Canvas 2D – so a guard built on it passes on
exactly the machines it was meant to protect, and BT.effectAdd throws there.
- Some effects animate from a
time field – set fx.time = BT.timeSeconds each frame.
- Hold onto effect instances and reuse them; rebuilding every toggle re-allocates GPU pipelines.
- Full effect reference lives in the engine repo (linked from
AGENTS.md); the local docs do not cover every effect.