Three.js Post-Processing
Use this skill for an intentional screen-space pipeline. Route scene/camera setup to
threejs-fundamentals, mesh/material shader work to threejs-shaders, and texture/render
target semantics to threejs-textures.
When to use this skill
- Add bloom, anti-aliasing, ambient occlusion, depth of field, outlines, or color grading
- Configure
EffectComposer and resolve pass ordering or double-rendering bugs
- Write a custom full-screen
ShaderPass or manage offscreen render targets
- Fix blur, incorrect resolution, missing effects, overly expensive passes, or teardown leaks
Instructions
Step 1: Establish the baseline renderer first
- Make the unprocessed
renderer.render(scene, camera) view correct before adding passes.
- Decide whether the effect is a material/scene concern or genuinely screen-space. Do not
use a full-screen pass to compensate for a wrong light, texture color space, or material.
- Keep composer ownership with the canvas/render-loop owner; use either renderer render
or composer render per frame, not both for the same final output.
Step 2: Build a minimal ordered composer
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);
composer.addPass(new RenderPass(scene, camera));
composer.addPass(new UnrealBloomPass(new THREE.Vector2(width, height), 0.6, 0.4, 0.85));
function render() {
composer.render();
requestAnimationFrame(render);
}
render();
Pass order is behavior. Document why each pass precedes/follows the next, especially when
mixing depth-dependent, selection, antialiasing, or color-correction passes.
Step 3: Handle resolution and color deliberately
function resize(width, height) {
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize(width, height, false);
composer.setSize(width, height);
}
Match composer resolution to the renderer's configured drawing-buffer strategy. Effects
that sample pixel offsets or depth must receive current size uniforms. Avoid applying
legacy gamma/color correction passes without checking the renderer's current color-output
configuration.
Step 4: Treat each pass as a budgeted feature
| Need |
First choice |
| Normal scene output |
RenderPass only |
| Bright emissive glow |
Bloom after measuring at target resolution |
| Alias smoothing |
Built-in MSAA where available, then an appropriate AA pass |
| Object outline |
Outline pass or focused custom pass |
| Custom screen-space math |
ShaderPass with explicit uniforms |
| Strong DOF/SSAO/glitch |
Optional quality tier with fallback/off switch |
Use lower-resolution buffers, quality tiers, or selective effects only after validating the
visual contract. Do not stack passes as a substitute for art direction.
Step 5: Verify effects and cleanup
- Test resize, pixel ratio, dynamic camera movement, and route changes/unmounts.
- Test low- and high-quality settings on target hardware and record frame-time impact.
- Check pass order with each effect toggled independently.
- Dispose composer-owned render targets/passes according to the installed API and feature
lifecycle; do not leave offscreen GPU buffers after the scene is gone.
Examples
Selective bloom
Keep selection/layer rendering explicit and verify the normal scene does not become darker
or duplicate objects. Selective bloom is a multi-render pipeline, not a bloom threshold
flag alone.
Custom vignette
Use a ShaderPass only after confirming a CSS/canvas overlay cannot meet the requirement.
Declare time, resolution, and texture uniforms explicitly and update them through one owner.
Best practices
- Start from the plain render path and add one pass at a time.
- Keep composer and renderer dimensions in sync on every resize.
- Treat pass order and color pipeline as part of the feature contract.
- Gate expensive effects behind device-appropriate quality controls.
- Measure GPU frame time before shipping a visual stack.
References
1---2name: threejs-postprocessing3description: Build and optimize Three.js post-processing with EffectComposer, RenderPass, bloom, anti-aliasing, SSAO, depth of field, outlines, color correction, custom ShaderPasses, render targets, resize handling, and frame-budget controls. Use when adding or fixing screen-space effects, composer pass order, render target sizing, or visual-effect cost. Triggers on: Three.js postprocessing, EffectComposer, RenderPass, UnrealBloomPass, FXAA, SMAA, SSAO, depth of field, bloom, ShaderPass, render target, screen-space effect.4license: MIT5---67# Three.js Post-Processing89Use this skill for an intentional screen-space pipeline. Route scene/camera setup to10`threejs-fundamentals`, mesh/material shader work to `threejs-shaders`, and texture/render11target semantics to `threejs-textures`.1213## When to use this skill1415- Add bloom, anti-aliasing, ambient occlusion, depth of field, outlines, or color grading16- Configure `EffectComposer` and resolve pass ordering or double-rendering bugs17- Write a custom full-screen `ShaderPass` or manage offscreen render targets18- Fix blur, incorrect resolution, missing effects, overly expensive passes, or teardown leaks1920## Instructions2122### Step 1: Establish the baseline renderer first23241. Make the unprocessed `renderer.render(scene, camera)` view correct before adding passes.252. Decide whether the effect is a material/scene concern or genuinely screen-space. Do not26 use a full-screen pass to compensate for a wrong light, texture color space, or material.273. Keep composer ownership with the canvas/render-loop owner; use either renderer render28 or composer render per frame, not both for the same final output.2930### Step 2: Build a minimal ordered composer3132```js33import { EffectComposer } from "three/addons/postprocessing/EffectComposer.js";34import { RenderPass } from "three/addons/postprocessing/RenderPass.js";35import { UnrealBloomPass } from "three/addons/postprocessing/UnrealBloomPass.js";3637const composer = new EffectComposer(renderer);38composer.addPass(new RenderPass(scene, camera));39composer.addPass(new UnrealBloomPass(new THREE.Vector2(width, height), 0.6, 0.4, 0.85));4041function render() {42 composer.render();43 requestAnimationFrame(render);44}45render();46```4748Pass order is behavior. Document why each pass precedes/follows the next, especially when49mixing depth-dependent, selection, antialiasing, or color-correction passes.5051### Step 3: Handle resolution and color deliberately5253```js54function resize(width, height) {55 camera.aspect = width / height;56 camera.updateProjectionMatrix();57 renderer.setSize(width, height, false);58 composer.setSize(width, height);59}60```6162Match composer resolution to the renderer's configured drawing-buffer strategy. Effects63that sample pixel offsets or depth must receive current size uniforms. Avoid applying64legacy gamma/color correction passes without checking the renderer's current color-output65configuration.6667### Step 4: Treat each pass as a budgeted feature6869| Need | First choice |70|---|---|71| Normal scene output | `RenderPass` only |72| Bright emissive glow | Bloom after measuring at target resolution |73| Alias smoothing | Built-in MSAA where available, then an appropriate AA pass |74| Object outline | Outline pass or focused custom pass |75| Custom screen-space math | `ShaderPass` with explicit uniforms |76| Strong DOF/SSAO/glitch | Optional quality tier with fallback/off switch |7778Use lower-resolution buffers, quality tiers, or selective effects only after validating the79visual contract. Do not stack passes as a substitute for art direction.8081### Step 5: Verify effects and cleanup8283- Test resize, pixel ratio, dynamic camera movement, and route changes/unmounts.84- Test low- and high-quality settings on target hardware and record frame-time impact.85- Check pass order with each effect toggled independently.86- Dispose composer-owned render targets/passes according to the installed API and feature87 lifecycle; do not leave offscreen GPU buffers after the scene is gone.8889## Examples9091### Selective bloom9293Keep selection/layer rendering explicit and verify the normal scene does not become darker94or duplicate objects. Selective bloom is a multi-render pipeline, not a bloom threshold95flag alone.9697### Custom vignette9899Use a `ShaderPass` only after confirming a CSS/canvas overlay cannot meet the requirement.100Declare time, resolution, and texture uniforms explicitly and update them through one owner.101102## Best practices1031041. Start from the plain render path and add one pass at a time.1052. Keep composer and renderer dimensions in sync on every resize.1063. Treat pass order and color pipeline as part of the feature contract.1074. Gate expensive effects behind device-appropriate quality controls.1085. Measure GPU frame time before shipping a visual stack.109110## References111112- [Three.js Post-Processing source coverage](https://github.com/CloudAI-X/threejs-skills/tree/main/skills/threejs-postprocessing)113- [Three.js manual: post-processing](https://threejs.org/manual/#en/post-processing)114- [EffectComposer documentation](https://threejs.org/docs/#examples/en/postprocessing/EffectComposer)