Navigate

Search topics across all sections

GitHub
Post-Processing

Built-in Effects

Your 3D scene looks good, but it feels flat. No glow around bright lights, no blurry background behind the hero object, no cinematic mood. The built-in effects library gives you camera-lens-quality polish with just a few props.

You add a Bloom effect to your scene. The glow slider goes up, but nothing glows. Every object looks exactly the same. You try intensity={10} and still nothing. What is going on?

terminal
Bloom has no visible effect. Objects use meshStandardMaterial with toneMapped={true} (default) — brightness is clamped to 1.0 before Bloom can detect it.

Real-world

Each built-in effect mimics something that happens with a real camera lens.

Bloom is the glow you see when a bright streetlight bleeds into the surrounding darkness -- lens flare in a movie.

Depth of Field is the blurry background behind a portrait -- photographers call it bokeh.

Vignette is the natural darkening at the edges of old photographs, drawing your eye to the center.

Chromatic Aberration is the subtle rainbow fringing you see in cheap lenses when colors don't converge at the same point.

These effects trick the brain into thinking your WebGL scene was captured through a real lens. Subtlety is everything -- dial them down, not up.

Bright Pixel

Emissive > threshold

Extract

Bloom finds it

Blur

Soft glow spreads

Composite

Layered back

The Effects Toolkit

Each effect is a React component you drop inside EffectComposer. Let's walk through the ones you will reach for most often.

Bloom -- make things glow

BloomEffect.tsxTSX
<Bloom intensity={1.5} luminanceThreshold={0.6} mipmapBlur />

{/* The material that actually glows */}
<meshStandardMaterial
  emissive="cyan"
  emissiveIntensity={2}
  toneMapped={false}
/>

Bloom finds pixels brighter than the luminanceThreshold and blurs them outward. The trick: your material must push brightness past that threshold. Use emissiveIntensity above 1 and toneMapped=false so the values are not clamped.

Depth of Field -- blurry backgrounds

DepthOfField.tsxTSX
<DepthOfField
  target={[0, 0, 5]}
  focalLength={0.5}
  bokehScale={8}
/>

Point the target at the object you want in focus. Everything closer or farther gets progressively blurry, just like a portrait photo. Increase bokehScale for a stronger blur.

Vignette + Noise + Chromatic Aberration -- cinematic mood

CinematicEffects.tsxTSX
<Vignette offset={0.3} darkness={0.9} />
<Noise opacity={0.15} />
<ChromaticAberration offset={[0.002, 0.002]} />

These lightweight effects merge into a single shader pass. Keep Chromatic Aberration offset tiny (0.001 to 0.005) and Noise opacity below 0.2 for a film-like look. Going higher looks amateurish.

N8AO -- ambient occlusion (darkened crevices)

SSAOEffect.tsxTSX
<N8AO aoRadius={0.5} intensity={2} quality="medium" />
<SMAA />

N8AO darkens corners and crevices where light would naturally be blocked. Always pair it with SMAA anti-aliasing to clean up the noise that AO produces at contact edges.

What you just learned

Bloom needs emissive materials with emissiveIntensity > 1 and toneMapped={false} to actually glow.

Depth of Field is easiest to configure with the target prop using world-space coordinates.

Lightweight effects (Vignette, Noise, Chromatic Aberration) merge into one pass and are nearly free.

N8AO for ambient occlusion should always be paired with SMAA anti-aliasing for clean results.

Subtlety is key: small values look professional, big values look amateur.

Question

You set Bloom intensity to 5 and everything looks washed out. You set it to 0.5 and nothing seems to glow. What is the real knob you should be turning to control how much glow an individual object gets?

Think about it...

You want a neon sign to glow brightly in your scene. Which combination of props makes it work?

Hint: Think about what Bloom is actually looking for -- which pixels exceed the luminance threshold?

Try These Challenges

Put what you learned into practice. Try each challenge in the demo above using the Leva controls, then check the solution.

Try This!

Beginner

Max emissiveIntensity — blinding!

Try This!

Beginner

Set floorReflectivity to 0 — matte floor

Try This!

Beginner

Set pulseSpeed to 0 — frozen orbs

These are the patterns that trip up developers most often. Switch between Wrong and Fixed to compare the code side by side.

1
Bloom has no visible effect on objects
Objects need emissive materials with values above the threshold
Don't do this
BloomGlow.tsxTSX
// This mesh won't glow — color is clamped to [0,1]
<mesh>
  <sphereGeometry />
  <meshStandardMaterial color="white" />
</mesh>
Bloom extracts pixels brighter than the luminanceThreshold and blurs them. Standard colors are clamped to [0, 1], which may not exceed that threshold. Use emissive materials with emissiveIntensity > 1 and toneMapped={false} to push brightness high enough for Bloom to detect.
2
Depth of Field blurs the entire scene
Focus distance is misconfigured
Don't do this
DepthOfFieldFocus.tsxTSX
// Everything is blurred — focus is wrong
<DepthOfField
  focusDistance={0}  // Normalized 0-1, not world units!
  focalLength={0.02}
  bokehScale={6}
/>
focusDistance uses a normalized 0-1 range, not world units. This is unintuitive to set correctly. Use the target prop instead, which accepts world-space coordinates. Pass the position of the object you want in focus and the math is handled for you.
3
SSAO creates visible banding or noise
AO settings don't match the scene scale
Don't do this
SSAOQuality.tsxTSX
// Too aggressive — visible artifacts
<N8AO
  aoRadius={5}
  intensity={10}
/>
SSAO artifacts usually come from aoRadius being too large for your scene or intensity being cranked too high. Keep radius as a fraction of your scene scale, start with low intensity, and always pair N8AO with SMAA anti-aliasing to smooth the contact edges.

Best Practices

toneMapped=false for Glow

Any material that should glow with Bloom must have toneMapped=false and emissiveIntensity greater than 1. Without this, tone mapping clamps brightness before Bloom can detect it.

Use target for Depth of Field

The target prop accepts world-space coordinates and is much easier to use than focusDistance (which requires a normalized 0-1 value). Point it at the object you want sharp.

Keep Effects Subtle

Chromatic Aberration offset of 0.002, Vignette darkness of 0.7, and Noise opacity of 0.15 are good starting points. Professional effects are barely noticeable -- if someone spots the effect immediately, it is probably too strong.

Pair AO with Anti-Aliasing

N8AO produces noise at contact edges. Always add SMAA anti-aliasing alongside it to smooth out the artifacts and get clean contact shadows.