Three.js CRT Effect with DotScreen and RGB Shift
This article explains how to recreate a retro CRT monitor aesthetic
in a 3D scene using Three.js post-processing. By combining the
EffectComposer, DotScreenPass to simulate
phosphor screen pixels, and a custom ShaderPass with
RGBShiftShader to create chromatic aberration, you can
easily achieve a nostalgic, analog television screen distortion.
1. Import the Required Modules
To implement post-processing, you need to import the core Three.js
library along with the specific post-processing passes and shaders.
Ensure you import the EffectComposer,
RenderPass, DotScreenPass,
ShaderPass, and RGBShiftShader.
import * as THREE from 'three';
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js';
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js';
import { DotScreenPass } from 'three/examples/jsm/postprocessing/DotScreenPass.js';
import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js';
import { RGBShiftShader } from 'three/examples/jsm/shaders/RGBShiftShader.js';2. Initialize the Effect Composer
First, set up your standard Three.js scene, camera, and WebGL
renderer. Once those are established, initialize the
EffectComposer by passing your renderer to it. Add a
standard RenderPass so the composer renders your original
3D scene before applying any effects.
// Set up the composer
const composer = new EffectComposer(renderer);
// Add the base render pass
const renderPass = new RenderPass(scene, camera);
composer.addPass(renderPass);3. Add the DotScreenPass for the Pixel Grid
The DotScreenPass simulates the shadow mask or aperture
grille of a classic CRT monitor by overlaying a dot pattern. You can
control the angle and scale of the pattern. A high scale value creates a
fine, subtle pixel grid.
// Parameters: (center, angle, scale)
const dotScreenPass = new DotScreenPass(new THREE.Vector2(0.5, 0.5), 0.5, 0.8);
composer.addPass(dotScreenPass);- Center: The focus point of the dot pattern.
- Angle: The rotation of the dot pattern grid.
- Scale: The density of the dots. Lower numbers make the dots larger and more obvious; higher numbers simulate a higher-resolution screen grid.
4. Add the RGBShiftShader for Color Bleeding
CRT monitors often suffer from convergence issues, causing color
channels (Red, Green, and Blue) to misalign at the edges of the screen.
You can replicate this using the RGBShiftShader wrapped in
a ShaderPass.
const rgbShiftPass = new ShaderPass(RGBShiftShader);
// Adjust the amount of color separation
rgbShiftPass.uniforms['amount'].value = 0.0035;
composer.addPass(rgbShiftPass);- amount: Controls the distance of the color channel
separation. Keep this value small (between
0.001and0.005) for a subtle, realistic analog glitch, or increase it for a heavily distorted look.
5. Update the Render Loop
To apply the effects, you must replace your standard renderer call in
the animation loop. Instead of calling
renderer.render(scene, camera), call
composer.render().
function animate() {
requestAnimationFrame(animate);
// Update animations or controls here
// Render the scene through the post-processing pipeline
composer.render();
}
animate();6. Handle Window Resizing
Because post-processing relies on render targets that match the
screen dimensions, you must update the EffectComposer size
whenever the browser window is resized.
```window.addEventListener(‘resize’, onWindowResize);
function onWindowResize() { const width = window.innerWidth; const height = window.innerHeight;
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize(width, height);
composer.setSize(width, height);
} ```