Pixel Shader (Three.js)
A small scene of boxes around a glowing, turning crystal, pushed through Three.js’s EffectComposer with the RenderPixelatedPass addon: chunky retro pixels with clean edges.
The teapot showcase draws in a single forward pass. This one renders into off-screen targets, runs custom GLSL for the pixel-art edge detection, and blits the result to the screen. It is the demo to look at if your app needs multi-pass rendering, render targets or shaders of its own.
Ported from the upstream webgl_postprocessing_pixel example.
Live demo
Section titled “Live demo”Run it
Section titled “Run it”It declares all four runtimes, so pick the one you have:
gjsify showcase three-postprocessing-pixel --runtime gjsgjsify showcase three-postprocessing-pixel --runtime nodegjsify showcase three-postprocessing-pixel --runtime bungjsify showcase three-postprocessing-pixel --runtime denoA GTK 4 window opens as an Adw.OverlaySplitView with the controls in the sidebar. Pixel Size crushes the resolution into bigger cells. Normal Edge and Depth Edge set how strongly the shader outlines geometry. Pixel-Aligned Panning snaps camera movement to the pixel grid so the image stops shimmering as it moves. Same window and same pipeline on all four.
--runtime gjs runs the --app gjs bundle against GJS’s native gi://. The other three share one --app node bundle, where gi:// goes through the node-gi bridge. Leave the flag off and Choose the runtime says what the CLI picks.
Run it in the browser
Section titled “Run it in the browser”import { mount } from '@gjsify/example-dom-three-postprocessing-pixel/browser';
const handle = mount(document.getElementById('app')!, { assetBase: '/demos/pixel/', // where checker.png is served from});
handle.pause();handle.resume();The browser build rebuilds the same sidebar from @gjsify/adwaita-web custom elements.
What the pipeline does
Section titled “What the pipeline does”The composer chain is the standard Three.js one, and nothing in it changes for the GTK window:
EffectComposerwraps the renderer and owns the off-screen targets.RenderPixelatedPassrenders the scene at a reduced resolution and applies the edge detection, with its own GLSL compiled at runtime.OutputPassblits the result to the screen framebuffer.
Each stage carries its own buffer and texture state, which is the part @gjsify/webgl has to track for you.
What it uses
Section titled “What it uses”| Package | What it needs |
|---|---|
@gjsify/webgl | Off-screen framebuffers, shaders compiled at runtime, OrbitControls |
@gjsify/dom-elements | HTMLCanvasElement and requestAnimationFrame |
@gjsify/adwaita-web | The sidebar in the browser build |
| Libadwaita | Adw.SpinRow and Adw.SwitchRow in the GTK build |
Copy the structure
Section titled “Copy the structure”showcases/dom/three-postprocessing-pixel/
src/three-demo.ts holds the scene and the whole post-processing chain behind one start(canvas) function. Both targets reuse it; only the shell around the canvas differs, in src/gjs/ and src/browser/.
Related
Section titled “Related”three-geometry-teapotis the single-pass companion.three-loader-ldrawloads its geometry from disk overfetch.- Bridge widgets covers the
WebGLBridgelifecycle.