Multi-pass CRT rendering for WebGL 2, with image, React, Three.js and pmndrs adapters. The pipeline applies signal filtering, brightness-dependent scanlines and display optics.
Documentation · Gallery · npm
Add the skill to your coding agent:
npx skills add OutThisLife/crt-shaderThen ask for what you want, like "put a CRT effect on the hero image". The agent installs the package and wires it in.
Or install it yourself:
pnpm add crt-shaderThe package ships ES modules and TypeScript declarations. Get started has working examples and the dependencies for each adapter.
Paste this into a browser module, such as src/main.js in a Vite app. It draws its own source image.
import { createRuntime, prepareInput } from 'crt-shader';
const source = document.createElement('canvas');
source.width = 64;
source.height = 48;
const context = source.getContext('2d');
context.fillStyle = '#fff';
context.font = 'bold 24px monospace';
context.fillText('CRT', 4, 32);
const output = document.body.appendChild(document.createElement('canvas'));
output.setAttribute('aria-label', 'CRT text');
output.style.maxWidth = '100%';
const runtime = createRuntime();
try {
await runtime.render({
source: prepareInput(source), output,
width: 512, height: 384, preset: 'reference',
});
} finally {
runtime.dispose();
}| Import | Use | Guide |
|---|---|---|
crt-shader |
Image preparation, runtime, CRTRenderer, presets |
Vanilla JavaScript |
crt-shader/react |
<CRTImage> for still images |
React |
crt-shader/three |
CRTPass for Three's native EffectComposer |
Three.js |
crt-shader/postprocessing |
CRTPass for the pmndrs composer |
pmndrs |
crt-shader/r3f |
<CRT> inside @react-three/postprocessing |
React Three Fiber |
crt-shader/presets |
Immutable PRESETS |
Options |
Images preserve native pixels by default; photo downsampling is opt-in. Scene adapters default to inputResolution="auto", which downsamples the rendered scene. For native-resolution CRT, set a numeric resolution at least as large as the input buffer's longest edge. See scene input sizing.
The effect processes full frames with opaque RGB output on a black matte.
For custom integrations, see the GLSL reference and porting guide.
Use the pnpm version pinned in package.json.
pnpm install
pnpm docs:devThe docs run at http://127.0.0.1:3000/. Use pnpm dev for the standalone examples. Build, package and release commands are in Contributing.
Code by Brooklyn (OutThisLife), with visual inspiration from Datagubbe's CRT article and follow-up.
Original code is MIT-licensed; retain LICENSE and NOTICE.md when copying or porting it. Third-party images and articles have separate rights. See Credits.