Skip to content
Skills Library
Programming · Building & coding

threejs-impl-post-processing

/threejs-impl-post-processing

Use when adding post-processing effects like bloom, SSAO, depth of field, or anti-aliasing to a Three.js scene. Prevents the common mistake of mixing Three.js EffectComposer with pmndrs/postprocessing, wrong pass order, or missing RenderPass. Covers EffectComposer, 27+ passes, pmndrs/postprocessing, custom ShaderPass. Keywords: post-processing, EffectComposer, bloom, UnrealBloomPass, SSAO, outline, SMAA, FXAA, postprocessing, effects, render pass, glow effect, blur, cinematic, visual effects.

Licence
MIT
Last repository change
09.11.2026

Assessment and security

100/ 100Class: good
Format25 / 25
Frontmatter with name and description, valid name, description up to 1,024 characters, name matching the folder.
Discoverability25 / 25
Description explains when to use the skill, has a reasonable length and uses third person.
Content35 / 35
At least 150 words and at most 500 lines, headings, step lists, examples or code.
Hygiene15 / 15
No placeholders such as TODO, no Windows paths, with a licence.
Riskno signals detected in the scan
Files in this package
5
Scripts
0
HTML comments
0
URLs in SKILL.md
4
Deprecation

No signals detected. Repository changed on 09.11.2026, without references to retired models or APIs.

Licence

MIT, open: use and modify while retaining author attribution.

What it does and when to use it

Use when adding post-processing effects like bloom, SSAO, depth of field, or anti-aliasing to a Three.js scene. Prevents the common mistake of mixing Three.js EffectComposer with pmndrs/postprocessing, wrong pass order, or missing RenderPass. Covers EffectComposer, 27+ passes, pmndrs/postprocessing, custom ShaderPass. Keywords: post-processing, EffectComposer, bloom, UnrealBloomPass, SSAO, outline, SMAA, FXAA, postprocessing, effects, render pass, glow effect, blur, cinematic, visual effects.

Original author description

Use when adding post-processing effects like bloom, SSAO, depth of field, or anti-aliasing to a Three.js scene. Prevents the common mistake of mixing Three.js EffectComposer with pmndrs/postprocessing, wrong pass order, or missing RenderPass. Covers EffectComposer, 27+ passes, pmndrs/postprocessing, custom ShaderPass. Keywords: post-processing, EffectComposer, bloom, UnrealBloomPass, SSAO, outline, SMAA, FXAA, postprocessing, effects, render pass, glow effect, blur, cinematic, visual effects.

How it works

  1. Quick Reference
  2. EffectComposer API
  3. Available Pass Types
  4. Key Effect Configuration
  5. Custom ShaderPass
  6. pmndrs/postprocessing
  7. Resize Handling
  8. WebGPU PostProcessing
  9. Reference Links
Original SKILL.md headings · 310 lines, 1,482 words
SKILL.md preview
---
name: threejs-impl-post-processing
description: >
  Use when adding post-processing effects like bloom, SSAO, depth of
  field, or anti-aliasing to a Three.js scene. Prevents the common
  mistake of mixing Three.js EffectComposer with pmndrs/postprocessing,
  wrong pass order, or missing RenderPass. Covers EffectComposer,
  27+ passes, pmndrs/postprocessing, custom ShaderPass.
  Keywords: post-processing, EffectComposer, bloom, UnrealBloomPass, SSAO, outline, SMAA, FXAA, postprocessing, effects, render pass, glow effect, blur, cinematic, visual effects.
license: MIT
compatibility: "Designed for Claude Code. Requires Three.js r160+."
metadata:
  author: OpenAEC-Foundation
  version: "1.0"
---

# threejs-impl-post-processing

## Quick Reference

### Architecture Overview

Three.js offers TWO incompatible post-processing systems. NEVER mix them.

| System | Package | Approach | Best For |
|--------|---------|----------|----------|
| Built-in EffectComposer | `three/addons/postprocessing/` | One shader pass per effect | Simple setups, custom ShaderPass |
| pmndrs/postprocessing | `postprocessing` (npm) | Merges effects into single pass | Performance-critical, R3F apps |
| WebGPU PostProcessing | `three/addons/tsl/display/` | Node-based TSL graphs | WebGPU renderer only |

### Standard Pipeline (Built-in EffectComposer)

```js
import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
import { OutputPass } from 'three/addons/postprocessing/OutputPass.js';

const composer = new EffectComposer( renderer );
composer.addPass( new RenderPass( scene, camera ) ); // ALWAYS first
// ... effect passes here ...
composer.addPass( new OutputPass() );                 // ALWAYS last

function animate() {
  composer.render(); // replaces renderer.render( scene, camera )
}
```

### Pass Ordering Rules

1. `RenderPass` MUST be the FIRST pass -- it renders the scene to the internal buffer
2. Effect passes go in the MIDDLE in any order (bloom, SSAO, outline, etc.)
3. Anti-aliasing passes (SMAA, FXAA) go AFTER effect passes
4. `OutputPass` MUST be the LAST pass -- it applies tone mapping and color space conversion
5. NEVER omit `OutputPass` -- without it, colors appear washed out or incorrect

### Critical Warnings

**NEVER** mix `three/addons/postprocessing/EffectComposer` with `pmndrs/postprocessing` `EffectComposer`. They use incompatible buffer formats and will produce rendering artifacts or crashes.

**NEVER** forget to call `composer.setSize()` on window resize. Failing to resize the composer causes blurry or misaligned effects.

**NEVER** call `renderer.render( scene, camera )` when using EffectComposer. ALWAYS call `composer.render()` instead -- calling both renders the scene twice.

**NEVER** use WebGL post-processing passes with the WebGPU renderer. WebGPU uses an entirely separate node-based `PostProcessing` class.

**ALWAYS** include `RenderPass` as the first pass. Without it, subsequent passes receive an empty buffer.

---

## EffectComposer API

### Constructor

```js
new EffectComposer( renderer: WebGLRenderer, renderTarget?: WebGLRenderTarget )
```

- `renderer` -- the WebGLRenderer instance
- `renderTarget` -- optional custom render target; auto-created if omitted

### Properties

| Property | Type | Description |
|----------|------|-------------|
| `.passes` | `Pass[]` | Ordered array of post-processing passes |
| `.readBuffer` | `WebGLRenderTarget` | Internal read buffer |
| `.writeBuffer` | `WebGLRenderTarget` | Internal write buffer |
| `.renderToScreen` | `boolean` | Whether the final pass renders to screen (default `true`) |
| `.renderer` | `WebGLRenderer` | The renderer instance |

### Methods

| Method | Description |
|--------|-------------|
| `.addPass( pass )` | Appends a pass to the end of the chain |
| `.insertPass( pass, index )` | Inserts a pass at a specific position |
| `.removePass( pass )` | Removes a pass from the chain |
| `.render( deltaTime? )` | Executes all enabled passes in order |
| `.setSize( width, height )` | Resizes all internal buffers and passes |
| `.setPixelRatio( ratio )` | Configures device pixel ratio |
| `.swapBuffers()` | Exchanges read/write buffers |
| `.reset( renderTarget? )` | Restores internal state |
| `.dispose()` | Frees all GPU resources |

---

## Available Pass Types

### Core Passes (ALWAYS needed)

| Pass | Import | Purpose |
|------|--------|---------|
| `RenderPass` | `postprocessing/RenderPass.js` | Renders scene to buffer; ALWAYS first |
| `OutputPass` | `postprocessing/OutputPass.js` | Tone mapping + color space; ALWAYS last |

### Effect Passes

| Pass | Constructor | Purpose |
|------|-------------|---------|
| `UnrealBloomPass` | `( resolution, strength?, radius?, threshold? )` | HDR bloom glow |
| `SSAOPass` | `( scene, camera, width?, height? )` | Screen-space ambient occlusion |
| `GTAOPass` | `( scene, camera, width?, height? )` | Ground truth AO (higher quality) |
| `SAOPass` | `( scene, camera )` | Scalable ambient obscurance |
| `OutlinePass` | `( resolution, scene, camera, selectedObjects? )` | Object selection outlines |
| `BokehPass` | `( scene, camera, params )` | Depth of field |
| `SSRPass` | `( params )` | Screen-space reflections |
| `FilmPass` | `( intensity?, grayscale? )` | Film grain / scanlines |
| `GlitchPass` | `( dtSize? )` | Digital glitch effect |
| `HalftonePass` | `( width, height, params )` | Halftone dot pattern |
| `DotScreenPass` | `( center?, angle?, scale? )` | Dot screen overlay |
| `AfterimagePass` | `( damp? )` | Motion trails / ghosting |
| `LUTPass` | `( params )` | Color LUT grading |
| `RenderPixelatedPass` | `( pixelSize, scene, camera )` | Pixelation effect |

### Anti-Aliasing Passes

| Pass | Constructor | Quality | Cost |
|------|-------------|---------|------|
| `FXAAPass` | `()` | Low -- fast approximation | Cheapest |
| `SMAAPass` | `( width, height )` | Medium -- subpixel morphological | Moderate |
| `SSAARenderPass` | `( scene, camera )` | High -- super-sampling | Expensive |
| `TAARenderPass` | `( scene, camera )` | High -- temporal accumulation | Expensive |

### Utility Passes

| Pass | Purpose |
|------|---------|
| `ShaderPass` | Custom GLSL shader effect |
| `MaskPass` | Stencil masking |
| `ClearMaskPass` | Clears stencil mask |
| `ClearPass` | Clears buffer |
| `TexturePass` | Renders a texture |
| `CubeTexturePass` | Renders cubemap background |
| `SavePass` | Saves current buffer to render target |
| `RenderTransitionPass` | Animated transition between two scenes |

ALL passes import from `three/addons/postprocessing/{PassName}.js`.

---

## Key Effect Configuration

### UnrealBloomPass

```js
import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js';

const bloom = new UnrealBloomPass(
  new THREE.Vector2( window.innerWidth, window.innerHeight ),
  1.5,  // strength -- bloom intensity [0, 3+]
  0.4,  // radius -- bloom spread [0, 1]
  0.85  // threshold -- luminance cutoff [0, 1]
);
```

Tone mapping MUST be enabled on the renderer for bloom to work correctly. Selective bloom (per-object) is NOT natively supported -- use the `layers` system with multiple render passes as a workaround.

### SSAOPass / GTAOPass

ALWAYS prefer `GTAOPass` over `SSAOPass` for production quality. Use `SSAOPass` only for prototyping.

```js
// SSAOPass (faster, lower quality)
const ssao = new SSAOPass( scene, camera, width, height );
ssao.kernelRadius = 8;
ssao.minDistance = 0.005;
ssao.maxDistance = 0.1;

// GTAOPass (slower, production quality)
const gtao = new GTAOPass( scene, camera, width, height );
```

### OutlinePass

```js
const outline = new OutlinePass(
  new THREE.Vector2( window.innerWidth, window.innerHeight ),
  scene, camera
);
outline.selectedObjects = [ mesh1, mesh2 ];
outline.edgeStrength = 3;
outline.edgeGlow = 0;
outline.edgeThickness = 1;
outline.visibleEdgeColor.set( 0xffffff );
outline.hiddenEdgeColor.set( 0x190a05 );
```

---

## Custom ShaderPass

```js
import { ShaderPass } from 'three/addons/postprocessing/ShaderPass.js';

const myShader = {
  uniforms: {
    tDiffuse: { value: null }, // ALWAYS include -- receives read buffer
    amount: { value: 0.5 }
  },
  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() {
      vec4 color = texture2D( tDiffuse, vUv );
      gl_FragColor = mix( color, vec4( 1.0 - color.rgb, color.a ), amount );
    }
  `
};

const customPass = new ShaderPass( myShader );
composer.insertPass( customPass, 1 ); // after RenderPass
```

The `textureID` parameter defaults to `'tDiffuse'`. If your shader uses a different uniform name for the input texture, pass it as the second argument: `new ShaderPass( myShader, 'myInputTexture' )`.

---

## pmndrs/postprocessing

### Architecture

The `pmndrs/postprocessing` library merges multiple effects into a SINGLE shader pass, reducing draw calls significantly compared to the built-in system.

```js
import { EffectComposer, EffectPass, RenderPass, BloomEffect,
         SMAAEffect } from 'postprocessing';

const composer = new EffectComposer( renderer );
composer.addPass( new RenderPass( scene, camera ) );
composer.addPass( new EffectPass( camera, new BloomEffect(), new SMAAEffect() ) );

function animate() {
  composer.render();
}
```

### Key Effects

| Effect | Purpose |
|--------|---------|
| `BloomEffect` | Configurable bloom with mipmaps |
| `SMAAEffect` | Subpixel morphological AA |
| `SSAOEffect` | Screen-space ambient occlusion |
| `DepthOfFieldEffect` | Bokeh depth-of-field |
| `ToneMappingEffect` | Tone mapping operators |
| `VignetteEffect` | Screen edge darkening |
| `ChromaticAberrationEffect` | Color fringing |
| `NoiseEffect` | Film grain |
| `GodRaysEffect` | Volumetric light scattering |

For React Three Fiber, use `@react-three/postprocessing` which wraps these effects as JSX components.

---

## Resize Handling

ALWAYS resize both the renderer AND the composer on window resize:

```js
window.addEventListener( 'resize', () => {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize( window.innerWidth, window.innerHeight );
  composer.setSize( window.innerWidth, window.innerHeight ); // MUST resize
});
```

---

## WebGPU PostProcessing

The WebGPU renderer uses a SEPARATE node-based system:

```js
import { PostProcessing } from 'three/addons/tsl/display/PostProcessing.js';

const postProcessing = new PostProcessing( renderer );
// Uses TSL (Three Shading Language) node graphs for effects
```

This is entirely incompatible with both the built-in WebGL `EffectComposer` and `pmndrs/postprocessing`.

---

## Reference Links

- [references/methods.md](references/methods.md) -- Complete API signatures for EffectComposer, all passes, and pmndrs effects
- [references/examples.md](references/examples.md) -- Working code examples for common post-processing setups
- [references/anti-patterns.md](references/anti-patterns.md) -- What NOT to do with post-processing

### Official Sources

- https://threejs.org/docs/#examples/en/postprocessing/EffectComposer
- https://threejs.org/examples/?q=postprocessing
- https://github.com/pmndrs/postprocessing
- https://docs.pmnd.rs/react-three-fiber/tutorials/post-processing
Files in this package (5)
  • .gitkeep 1 KB
  • SKILL.md 11 KB
  • references/anti-patterns.md 8 KB
  • references/examples.md 9 KB
  • references/methods.md 9 KB

Versions

The database has no other skills named threejs-impl-post-processing.

Database snapshot: 13.11.2026 · package version ff84853f364a (SHA-256 digest of the entire package)

Downloads in the last 30 days: 0 · ranking

Report a problem with this skill: harmful content, incorrect descriptions or an author’s removal request.

Similar skills

  • 100threejs-postprocessing
    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,…
  • 100r3f-postprocessing
    Post-processing in React Three Fiber via @react-three/postprocessing (pmndrs) — EffectComposer, Bloom, DepthOfField, ChromaticAberration, Vignette, Noise, SSAO, ToneMapping, custom effects. Use when adding cinematic visuals (bloom, DOF, color grading) to an R3F scene, debugging…
  • 95threejs-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.
  • 95threejs-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.
  • 100threejs-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.
  • 100threejs-postprocessing
    Three.js post-processing: composer pass chains, built-in renderer effects, and the WebGPU/TSL node pipeline — bloom, depth of field, ambient occlusion, custom screen effects. Use when adding visual effects, color grading, blur, glow, or screen-space shaders, on WebGL or with WebGPU and TSL.

Feedback and reports

Your message goes to Bartosz Sokoliński. An email address is needed only for a reply. See the privacy policy.