Skip to main content Home Creators calesthio openmontage threejs-postprocessing
threejs-postprocessing Three.js post-processing - EffectComposer, bloom, DOF, screen effects. Use when adding visual effects, color grading, blur, glow, or creating custom screen-space shaders.
Jump to install Skills Marketplace Discover and explore AI skills built by the community.
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Copy promptShow prompt details A direct command skips the review prompt. Inspect the source before running it.
npx skills add https://github.com/calesthio/OpenMontage --skill threejs-postprocessingThe command stays on one line. Scroll horizontally to inspect it before copying.
Prefer a local copy? Download the files currently available to SkillsMP.
Download Zip Downloading... More from this repository
Related occupations SOC
Based on SOC occupation classification
name threejs-postprocessing description Three.js post-processing - EffectComposer, bloom, DOF, screen effects. Use when adding visual effects, color grading, blur, glow, or creating custom screen-space shaders.
Three.js Post-Processing
Quick Start
import * as THREE from "three" ;
import { EffectComposer } from "three/addons/postprocessing/EffectComposer.js" ;
import { RenderPass } from "three/addons/postprocessing/RenderPass.js" ;
import { UnrealBloomPass } from "three/addons/postprocessing/UnrealBloomPass.js" ;
const composer = new EffectComposer (renderer);
const renderPass = new RenderPass (scene, camera);
composer.addPass (renderPass);
const bloomPass = new UnrealBloomPass (
new . ( . , . ),
,
,
,
);
composer. (bloomPass);
( ) {
(animate);
composer. ();
}
THREE
Vector2
window
innerWidth
window
innerHeight
1.5
0.4
0.85
addPass
function
animate
requestAnimationFrame
render
EffectComposer Setup import { EffectComposer } from "three/addons/postprocessing/EffectComposer.js" ;
import { RenderPass } from "three/addons/postprocessing/RenderPass.js" ;
const composer = new EffectComposer (renderer);
const renderPass = new RenderPass (scene, camera);
composer.addPass (renderPass);
composer.addPass (effectPass);
effectPass.renderToScreen = true ;
function onResize ( ) {
const width = window .innerWidth ;
const height = window .innerHeight ;
camera.aspect = width / height;
camera.updateProjectionMatrix ();
renderer.setSize (width, height);
composer.setSize (width, height);
}
Common Effects
Bloom (Glow) import { UnrealBloomPass } from "three/addons/postprocessing/UnrealBloomPass.js" ;
const bloomPass = new UnrealBloomPass (
new THREE .Vector2 (window .innerWidth , window .innerHeight ),
1.5 ,
0.4 ,
0.85 ,
);
composer.addPass (bloomPass);
bloomPass.strength = 2.0 ;
bloomPass.threshold = 0.5 ;
bloomPass.radius = 0.8 ;
Selective Bloom Apply bloom only to specific objects.
import { UnrealBloomPass } from "three/addons/postprocessing/UnrealBloomPass.js" ;
import { ShaderPass } from "three/addons/postprocessing/ShaderPass.js" ;
const BLOOM_LAYER = 1 ;
const bloomLayer = new THREE .Layers ();
bloomLayer.set (BLOOM_LAYER );
glowingMesh.layers .enable (BLOOM_LAYER );
const darkMaterial = new THREE .MeshBasicMaterial ({ color : 0x000000 });
const materials = {};
function darkenNonBloomed (obj ) {
if (obj.isMesh && !bloomLayer.test (obj.layers )) {
materials[obj.uuid ] = obj.material ;
obj.material = darkMaterial;
}
}
function restoreMaterial (obj ) {
if (materials[obj.uuid ]) {
obj.material = materials[obj.uuid ];
delete materials[obj.uuid ];
}
}
function render ( ) {
scene.traverse (darkenNonBloomed);
composer.render ();
scene.traverse (restoreMaterial);
renderer.render (scene, camera);
}
FXAA (Anti-Aliasing) import { ShaderPass } from "three/addons/postprocessing/ShaderPass.js" ;
import { FXAAShader } from "three/addons/shaders/FXAAShader.js" ;
const fxaaPass = new ShaderPass (FXAAShader );
fxaaPass.material .uniforms ["resolution" ].value .set (
1 / window .innerWidth ,
1 / window .innerHeight ,
);
composer.addPass (fxaaPass);
function onResize ( ) {
fxaaPass.material .uniforms ["resolution" ].value .set (
1 / window .innerWidth ,
1 / window .innerHeight ,
);
}
SMAA (Better Anti-Aliasing) import { SMAAPass } from "three/addons/postprocessing/SMAAPass.js" ;
const smaaPass = new SMAAPass (
window .innerWidth * renderer.getPixelRatio (),
window .innerHeight * renderer.getPixelRatio (),
);
composer.addPass (smaaPass);
SSAO (Ambient Occlusion) import { SSAOPass } from "three/addons/postprocessing/SSAOPass.js" ;
const ssaoPass = new SSAOPass (
scene,
camera,
window .innerWidth ,
window .innerHeight ,
);
ssaoPass.kernelRadius = 16 ;
ssaoPass.minDistance = 0.005 ;
ssaoPass.maxDistance = 0.1 ;
composer.addPass (ssaoPass);
ssaoPass.output = SSAOPass .OUTPUT .Default ;
Depth of Field (DOF) import { BokehPass } from "three/addons/postprocessing/BokehPass.js" ;
const bokehPass = new BokehPass (scene, camera, {
focus : 10.0 ,
aperture : 0.025 ,
maxblur : 0.01 ,
});
composer.addPass (bokehPass);
bokehPass.uniforms ["focus" ].value = distanceToTarget;
Film Grain import { FilmPass } from "three/addons/postprocessing/FilmPass.js" ;
const filmPass = new FilmPass (
0.35 ,
0.5 ,
648 ,
false ,
);
composer.addPass (filmPass);
Vignette import { ShaderPass } from "three/addons/postprocessing/ShaderPass.js" ;
import { VignetteShader } from "three/addons/shaders/VignetteShader.js" ;
const vignettePass = new ShaderPass (VignetteShader );
vignettePass.uniforms ["offset" ].value = 1.0 ;
vignettePass.uniforms ["darkness" ].value = 1.0 ;
composer.addPass (vignettePass);
Color Correction import { ShaderPass } from "three/addons/postprocessing/ShaderPass.js" ;
import { ColorCorrectionShader } from "three/addons/shaders/ColorCorrectionShader.js" ;
const colorPass = new ShaderPass (ColorCorrectionShader );
colorPass.uniforms ["powRGB" ].value = new THREE .Vector3 (1.2 , 1.2 , 1.2 );
colorPass.uniforms ["mulRGB" ].value = new THREE .Vector3 (1.0 , 1.0 , 1.0 );
composer.addPass (colorPass);
Gamma Correction import { GammaCorrectionShader } from "three/addons/shaders/GammaCorrectionShader.js" ;
const gammaPass = new ShaderPass (GammaCorrectionShader );
composer.addPass (gammaPass);
Pixelation import { RenderPixelatedPass } from "three/addons/postprocessing/RenderPixelatedPass.js" ;
const pixelPass = new RenderPixelatedPass (6 , scene, camera);
composer.addPass (pixelPass);
Glitch Effect import { GlitchPass } from "three/addons/postprocessing/GlitchPass.js" ;
const glitchPass = new GlitchPass ();
glitchPass.goWild = false ;
composer.addPass (glitchPass);
Halftone import { HalftonePass } from "three/addons/postprocessing/HalftonePass.js" ;
const halftonePass = new HalftonePass (window .innerWidth , window .innerHeight , {
shape : 1 ,
radius : 4 ,
rotateR : Math .PI / 12 ,
rotateB : (Math .PI / 12 ) * 2 ,
rotateG : (Math .PI / 12 ) * 3 ,
scatter : 0 ,
blending : 1 ,
blendingMode : 1 ,
greyscale : false ,
});
composer.addPass (halftonePass);
Outline import { OutlinePass } from "three/addons/postprocessing/OutlinePass.js" ;
const outlinePass = new OutlinePass (
new THREE .Vector2 (window .innerWidth , window .innerHeight ),
scene,
camera,
);
outlinePass.edgeStrength = 3 ;
outlinePass.edgeGlow = 0 ;
outlinePass.edgeThickness = 1 ;
outlinePass.pulsePeriod = 0 ;
outlinePass.visibleEdgeColor .set (0xffffff );
outlinePass.hiddenEdgeColor .set (0x190a05 );
outlinePass.selectedObjects = [mesh1, mesh2];
composer.addPass (outlinePass);
Custom ShaderPass Create your own post-processing effects.
import { ShaderPass } from "three/addons/postprocessing/ShaderPass.js" ;
const CustomShader = {
uniforms : {
tDiffuse : { value : null },
time : { value : 0 },
intensity : { value : 1.0 },
},
vertexShader : `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
` ,
fragmentShader : `
uniform sampler2D tDiffuse;
uniform float time;
uniform float intensity;
varying vec2 vUv;
void main() {
vec2 uv = vUv;
// Wave distortion
uv.x += sin(uv.y * 10.0 + time) * 0.01 * intensity;
vec4 color = texture2D(tDiffuse, uv);
gl_FragColor = color;
}
` ,
};
const customPass = new ShaderPass (CustomShader );
composer.addPass (customPass);
customPass.uniforms .time .value = clock.getElapsedTime ();
Invert Colors Shader const InvertShader = {
uniforms : {
tDiffuse : { value : null },
},
vertexShader : `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
` ,
fragmentShader : `
uniform sampler2D tDiffuse;
varying vec2 vUv;
void main() {
vec4 color = texture2D(tDiffuse, vUv);
gl_FragColor = vec4(1.0 - color.rgb, color.a);
}
` ,
};
Chromatic Aberration const ChromaticAberrationShader = {
uniforms : {
tDiffuse : { value : null },
amount : { value : 0.005 },
},
vertexShader : `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
` ,
fragmentShader : `
uniform sampler2D tDiffuse;
uniform float amount;
varying vec2 vUv;
void main() {
vec2 dir = vUv - 0.5;
float dist = length(dir);
float r = texture2D(tDiffuse, vUv - dir * amount * dist).r;
float g = texture2D(tDiffuse, vUv).g;
float b = texture2D(tDiffuse, vUv + dir * amount * dist).b;
gl_FragColor = vec4(r, g, b, 1.0);
}
` ,
};
Combining Multiple Effects import { EffectComposer } from "three/addons/postprocessing/EffectComposer.js" ;
import { RenderPass } from "three/addons/postprocessing/RenderPass.js" ;
import { UnrealBloomPass } from "three/addons/postprocessing/UnrealBloomPass.js" ;
import { ShaderPass } from "three/addons/postprocessing/ShaderPass.js" ;
import { FXAAShader } from "three/addons/shaders/FXAAShader.js" ;
import { VignetteShader } from "three/addons/shaders/VignetteShader.js" ;
import { GammaCorrectionShader } from "three/addons/shaders/GammaCorrectionShader.js" ;
const composer = new EffectComposer (renderer);
composer.addPass (new RenderPass (scene, camera));
const bloomPass = new UnrealBloomPass (
new THREE .Vector2 (window .innerWidth , window .innerHeight ),
0.5 ,
0.4 ,
0.85 ,
);
composer.addPass (bloomPass);
const vignettePass = new ShaderPass (VignetteShader );
vignettePass.uniforms ["offset" ].value = 0.95 ;
vignettePass.uniforms ["darkness" ].value = 1.0 ;
composer.addPass (vignettePass);
composer.addPass (new ShaderPass (GammaCorrectionShader ));
const fxaaPass = new ShaderPass (FXAAShader );
fxaaPass.uniforms ["resolution" ].value .set (
1 / window .innerWidth ,
1 / window .innerHeight ,
);
composer.addPass (fxaaPass);
Render to Texture
const renderTarget = new THREE .WebGLRenderTarget (512 , 512 );
renderer.setRenderTarget (renderTarget);
renderer.render (scene, camera);
renderer.setRenderTarget (null );
const texture = renderTarget.texture ;
otherMaterial.map = texture;
Multi-Pass Rendering
const bgComposer = new EffectComposer (renderer);
bgComposer.addPass (new RenderPass (bgScene, camera));
const fgComposer = new EffectComposer (renderer);
fgComposer.addPass (new RenderPass (fgScene, camera));
fgComposer.addPass (bloomPass);
function animate ( ) {
renderer.autoClear = false ;
renderer.clear ();
bgComposer.render ();
renderer.clearDepth ();
fgComposer.render ();
}
WebGPU Post-Processing (Three.js r150+) import { postProcessing } from "three/addons/nodes/Nodes.js" ;
import { pass, bloom, dof } from "three/addons/nodes/Nodes.js" ;
const scenePass = pass (scene, camera);
const bloomNode = bloom (scenePass, 0.5 , 0.4 , 0.85 );
const postProcessing = new THREE .PostProcessing (renderer);
postProcessing.outputNode = bloomNode;
function animate ( ) {
postProcessing.render ();
}
Performance Tips
Limit passes : Each pass adds a full-screen render
Lower resolution : Use smaller render targets for blur passes
Disable unused effects : Toggle passes on/off
Use FXAA over MSAA : Less expensive anti-aliasing
Profile with DevTools : Check GPU usage
bloomPass.enabled = false ;
const bloomPass = new UnrealBloomPass (
new THREE .Vector2 (window .innerWidth / 2 , window .innerHeight / 2 ),
strength,
radius,
threshold,
);
const isMobile = /iPhone|iPad|Android/i .test (navigator.userAgent );
if (!isMobile) {
composer.addPass (expensivePass);
}
Handle Resize function onWindowResize ( ) {
const width = window .innerWidth ;
const height = window .innerHeight ;
const pixelRatio = renderer.getPixelRatio ();
camera.aspect = width / height;
camera.updateProjectionMatrix ();
renderer.setSize (width, height);
composer.setSize (width, height);
if (fxaaPass) {
fxaaPass.material .uniforms ["resolution" ].value .set (
1 / (width * pixelRatio),
1 / (height * pixelRatio),
);
}
if (bloomPass) {
bloomPass.resolution .set (width, height);
}
}
window .addEventListener ("resize" , onWindowResize);
See Also
threejs-shaders - Custom shader development
threejs-textures - Render targets
threejs-fundamentals - Renderer setup