postprocessing

A post-processing library for three.js that merges bloom, depth of field, SSAO, and dozens of other effects into a single optimized shader pass.

Library
npm
v6.39.4
2,847stars
Zlib

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
82/100Excellent
Development Activity84
Maintenance84
Community60
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
87/100Excellent
Architecture88
Code Quality75
Innovation85
Learning Curve100

postprocessing extends the standard three.js rendering workflow with a pass-and-effect pipeline for full-screen image manipulation. Instead of rendering a scene once, an EffectComposer runs a chain of passes — typically a RenderPass followed by an EffectPass — to apply cinematic effects like bloom, depth of field, god rays, SSAO, outlines, and color grading on top of the rendered frame.

What sets it apart from naive pass-chaining is its effect-merging design: the EffectPass automatically combines any number of Effect instances into one shader program at runtime, each with its own configurable blend function, instead of running a separate full-screen draw call per effect. Combined with single-triangle full-screen rendering (rather than a quad), this keeps many simultaneous effects cheap even on modest GPUs.

The library ships over 35 built-in effects and passes covering antialiasing (SMAA, FXAA), color grading (LUT, hue/saturation, brightness/contrast, sepia), blur variants (Gaussian, Kawase, box, tilt-shift), and stylized effects (glitch, pixelation, dot-screen, scanline, shock wave). It also supports HDR workflows via HalfFloatType frame buffers and proper linear color space handling, and exposes a documented API for writing custom effects and passes.

What You Get

  • An EffectComposer that manages render targets and runs a configurable chain of passes in place of a raw WebGLRenderer.render() call
  • 35+ production-ready effects (Bloom, DepthOfField, SSAO, GodRays, Outline, Glitch, ToneMapping, LUT color grading, and more) that can be combined and blended
  • Automatic shader merging via EffectPass, which fuses multiple effects into a single fragment shader instead of chaining separate full-screen draws
  • HDR-aware rendering with HalfFloatType frame buffers and correct linear color space handling for high-fidelity pipelines
  • A documented API and Wiki guide for authoring custom effects and passes on top of the same composition model
  • Hand-written TypeScript declarations validated by a dedicated tsc project, giving full editor autocomplete without a TS source rewrite

Common Use Cases

  • Adding cinematic bloom, vignette, and depth of field to a three.js game or interactive visualization
  • Building stylized WebGL experiences with glitch, pixelation, or color-grading effects for art direction
  • Layering SSAO and outline passes onto a scene for improved depth perception and object highlighting
  • Implementing HDR tone-mapping pipelines that need linear-workflow color management
  • Prototyping custom full-screen shader effects using the library’s Effect/Pass composition primitives as a base

Under The Hood

Architecture postprocessing is organized into clearly separated layers under src/: core (the EffectComposer, Selection, Timer, and shared lifecycle interfaces like Resizable/Disposable/Initializable), passes (discrete rendering steps such as RenderPass, ClearPass, DepthPass, and the pivotal EffectPass), effects (37 concrete Effect subclasses plus the abstract Effect base and a blending module for BlendFunction/BlendMode), and supporting materials, textures, loaders, enums, and utils directories. The composition model is the core idea: an EffectComposer owns ping-ponged input/output render targets and a linear list of Pass instances; EffectPass is itself a pass that accepts any number of Effect instances and merges their fragment shader code, uniforms, and defines into one compiled shader at construction time, avoiding the cost of one full-screen draw call per effect. Changing the core Effect/Pass contract would ripple through all 37 effect implementations, but the abstraction is stable and has clearly absorbed years of iteration.

Tech Stack The library is authored in plain ES2025 JavaScript (ESM) with GLSL shader files bundled directly via esbuild-plugin-glsl, targeting both ESM and CJS consumers through a custom esbuild.js build script; type information is provided via a hand-written types/index.d.ts validated by a dedicated tsconfig.types.json project rather than a TypeScript source rewrite. Its only runtime dependency is a peer dependency on three (constrained to a specific compatible version range), keeping the published package dependency-free. The demo/docs site under manual/ is built with Hugo, Sass, and PostCSS, and API docs are generated with ESDoc. The project is managed as a pnpm workspace and tested with the ava test runner.

Code Quality Testing lives under test/ (92 files mirroring the src/ structure) using ava, though most tests are shallow instantiation smoke checks (t.truthy(new SomeEffect())) rather than deep behavioral assertions — adequate for catching constructor regressions but not exercising rendering output. Linting is enforced through a shared eslint-config-aether config for JS and stylelint for the demo’s SCSS, both wired into a single pnpm install-test command that GitHub Actions CI runs on every push and pull request (lint, clean, build, test, doc in sequence). Code is consistently documented with JSDoc across public classes, which doubles as the source of truth for the hand-maintained type declarations.

API Design Getting started requires only a handful of lines: construct an EffectComposer around an existing WebGLRenderer, add a RenderPass, add an EffectPass wrapping the desired effects, and call composer.render() in the animation loop in place of the renderer’s own render call. Effect and pass class names follow a consistent XEffect/XPass convention, every effect accepts a uniform blendFunction option for compositing, and the automatic shader-merging in EffectPass means adding a new effect to an existing pipeline is a one-line change rather than a new render pass to wire up by hand.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search