This project applies a classic ordered (Bayer) dithering effect to a rendered Three.js scene as a full-screen post-processing pass. The scene renders a 3D model with custom environment-map lighting, and a GLSL shader pixelates the frame and quantizes brightness through a 4x4 dither matrix to produce the retro halftone look. Key parameters are exposed through an on-screen Leva control panel so you can tweak the effect in real time.
Requires Node.js and Yarn (a yarn.lock is committed).
git clone https://github.com/niccolofanton/dithering-shader.git
cd dithering-shader
yarn install
yarn startThen open the local dev server printed in your terminal. To create a production build:
yarn buildThe dithering pass (src/dithering-shader/) runs after the scene is rendered:
- The frame is pixelated according to the grid size and pixel-size ratio.
- Luminance is computed per pixel.
- The pixel position is mapped into a 4x4 Bayer threshold matrix; the brightness is compared against the matrix value to decide whether the pixel is drawn or knocked out.
- The result can be rendered in grayscale or color.
Bloom can be added before (pre-dithering) and/or after (post-dithering) the dither pass,
chaining postprocessing effect passes through an EffectComposer.
- Custom ordered-dithering effect using a 4x4 Bayer matrix
- Adjustable dithering grid resolution and pixelation strength
- Grayscale-only or color mode toggle
- Independent pre- and post-dithering bloom passes
- Live tweaking of grid resolution, pixelation strength, grayscale mode, and the bloom passes via Leva controls
- 3D model lit with a custom environment map
- Responsive, full-window canvas
- React + TypeScript
- Three.js via React Three Fiber and drei
- postprocessing for the effect composer
- Leva for the controls panel
- Create React App (configured with craco)
- 3D Model: Jousting Helmet by The Royal Armoury, CC-BY-4.0
- Original dithering pattern by Klems on Shadertoy
- Environment lighting inspired by @0xca0a
Released under the MIT License.