r3f-postprocessing
enzed/r3f-skills
Configure React Three Fiber postprocessing: bloom, selection effects, ambient occlusion, and depth of field.
What is r3f-postprocessing?
Set up screen-space postprocessing effects in React Three Fiber using EffectComposer and the postprocessing library. Use this for bloom, selective object highlighting, SSAO, depth of field, and tone mapping—not for mesh material shaders.
- Configure EffectComposer pipelines with SelectiveBloom, Bloom, SSAO, DepthOfField, and ToneMapping effects
- Isolate bloom to selected objects using Selection/Select wrappers and SelectiveBloom
- Apply screen-space ambient occlusion (SSAO) with enableNormalPass for extra buffers
- Control depth of field with world-space target positions and focus distance
- Manage tone mapping and HDR effects before final output to avoid duplicate conversions
How to install r3f-postprocessing
npx skills add https://github.com/enzed/r3f-skills --skill r3f-postprocessing- React Three Fiber 9.7+
- @react-three/postprocessing 3.1+
- postprocessing 6.39+
- WebGL renderer (WebGPURenderer requires separate RenderPipeline setup)
How to use r3f-postprocessing
- 1.Install the skill: npx skills add https://github.com/enzed/r3f-skills --skill r3f-postprocessing
- 2.Wrap your scene content in Selection and Select components to enable object selection
- 3.Mount EffectComposer beneath Canvas with desired effects (SelectiveBloom, SSAO, DepthOfField, ToneMapping)
- 4.For SelectiveBloom, pass relevant lights and set luminanceThreshold and intensity; test with unselected bright objects
- 5.For SSAO, enable enableNormalPass on EffectComposer; for DepthOfField, provide world-space target position, not mesh refs
- 6.Disable renderer tone mapping and use ToneMapping effect for final appearance; place bloom/HDR effects before tone mapping
- 7.Test the full pipeline under Strict Mode, toggle effects, and verify selection-only behavior and color output
Use cases
- Highlight selected 3D objects with bloom while keeping unselected objects unaffected
- Add atmospheric depth of field to focus viewer attention on specific scene areas
- Apply SSAO to add contact shadows and depth cues without expensive mesh-level shaders
- Combine multiple postprocessing effects in a single EffectComposer pipeline
- Implement HDR bloom with proper tone mapping for realistic lighting appearance
- React Three Fiber developers building interactive 3D web experiences
- Graphics engineers optimizing scene rendering with screen-space effects
- Teams implementing selection feedback and visual emphasis in 3D UIs
r3f-postprocessing FAQ
Use ordinary Bloom to isolate bright surfaces via HDR threshold. Use SelectiveBloom only when you need actual object selection to control which objects contribute to bloom; it adds computational work.
DepthOfField target is a world position (vector/tuple), not a mesh ref. focusDistance={0} is not a universal autofocus switch; use a supported target or the Autofocus helper component.
No. Only enable enableNormalPass on EffectComposer when using SSAO or other effects that require it. Extra buffers are expensive; enable them only for effects that need them.
Yes. Mount multiple effects inside a single EffectComposer. Compatible effects can be merged into fewer passes. Measure GPU cost and avoid blindly stacking MSAA, SMAA, and FXAA.
EffectComposer disables renderer tone mapping. Use a ToneMapping effect for final appearance. Keep bloom/HDR effects before tone mapping to avoid duplicate output conversion.
Full instructions (SKILL.md)
Source of truth, from enzed/r3f-skills.
name: r3f-postprocessing description: Configure React Three Fiber postprocessing, bloom, selection effects, ambient occlusion, and depth of field. Use for composer pipelines and screen-space effects, rather than mesh material shaders.
React Three Fiber postprocessing
Check the actual renderer and package peer dependencies first. This example targets Fiber 9.7 / React 19 with @react-three/postprocessing 3.1 and postprocessing 6.39 on WebGL. Do not combine arbitrary newest package versions or silently upgrade a project.
Choose the pipeline
- The React postprocessing composer here is for WebGL. Three.js WebGPURenderer uses node effects and
RenderPipelineon r183+; verify that backend separately. - Let one owner render the final scene. EffectComposer uses a positive frame priority; an additional manual
gl.rendercan overwrite or duplicate its output. - Ordinary Bloom can isolate bright surfaces via an HDR threshold. Use SelectiveBloom only when actual object selection is required; it adds work.
Actual selected-object bloom
Mount beneath Canvas. Click the left box to toggle selection. Both boxes are bright, but only the selected object contributes to this bloom pass.
import { useMemo, useRef, useState } from 'react'
import { EffectComposer, Select, Selection, SelectiveBloom, ToneMapping } from '@react-three/postprocessing'
import { ToneMappingMode } from 'postprocessing'
import type { DirectionalLight } from 'three'
export default function Example() {
const light = useRef<DirectionalLight>(null)
const lights = useMemo(() => [light], [])
const [selected, setSelected] = useState(true)
return (
<Selection>
<directionalLight ref={light} position={[0, 3, 5]} intensity={2} />
<Select enabled={selected}>
<mesh name="bloom-selected" position={[-1.2, 0, 0]} onClick={() => setSelected((value) => !value)}>
<boxGeometry args={[0.7, 0.7, 0.7]} />
<meshStandardMaterial color="black" emissive="white" emissiveIntensity={3} />
</mesh>
</Select>
<mesh name="bloom-control" position={[1.2, 0, 0]}>
<boxGeometry args={[0.7, 0.7, 0.7]} />
<meshStandardMaterial color="black" emissive="white" emissiveIntensity={3} />
</mesh>
<EffectComposer multisampling={0}>
<SelectiveBloom lights={lights} luminanceThreshold={0} intensity={2} mipmapBlur />
<ToneMapping mode={ToneMappingMode.ACES_FILMIC} />
</EffectComposer>
</Selection>
)
}
Color, selection, and refs
- Selection/Select provide selection to effects that support it, such as Outline and SelectiveBloom. Wrapping ordinary Bloom in Selection does not make Bloom respect selected objects.
- Supply SelectiveBloom's relevant lights and keep selection layers coordinated with other layer uses. Test an equally bright unselected object, not only a dark background.
- Bloom operates on brightness before final tone mapping. Use emissive/HDR values and a meaningful threshold; do not flatten the whole scene to force a glow.
- This composer disables renderer tone mapping; use a ToneMapping effect for the intended final appearance. Keep bloom/HDR effects before tone mapping, and avoid duplicate output conversion.
ref.currentbecoming non-null does not trigger a React render. Do not gate the initial mounting of an effect on a ref assignment alone; use supported refs or callback-ref state where an object is needed reactively.
Depth and effect-specific requirements
- SSAO in this wrapper needs
<EffectComposer enableNormalPass>; enable extra buffers only for effects that require them. Check the installed effect's source/types if docs and behavior disagree. - DepthOfField
targetis a world position (vector/tuple), not a mesh ref.focusDistance={0}is not a universal autofocus switch; use a supported target or Autofocus helper. - Some effect props accept Three.js Vector2/Vector3 instances rather than tuples. Type-check against the installed wrapper; don't transfer JSX coercion assumptions to arbitrary React components.
- Alpha-blended surfaces, depth, selection, and multisampling interact. Test the actual transparent/transmissive scene rather than relying on opaque-box screenshots.
Performance and custom effects
- Begin with few effects and modest DPR/resolution. Choose an anti-aliasing strategy deliberately; avoid blindly stacking MSAA, SMAA, and FXAA.
- Effect count is not identical to pass count: compatible effects can be merged. Convolution/depth effects and auxiliary buffers can still be expensive; measure GPU cost.
- Prefer supported wrapper components. For a custom postprocessing Effect, follow
mainImage/mainUv, uniforms, input-buffer, and effect-attribute contracts; a UV-changing effect needs the appropriate convolution declaration. - Give custom Effect instances explicit cleanup ownership. Do not use
dispose={null}without an owner, or dispose a shared effect from one consumer. - Check dynamic prop support after updates: construction-only settings may recreate an effect. Do not rebuild the composer each frame to animate a uniform.
Verify
Render the full pipeline, toggle effects/selection, resize, and unmount/remount under Strict Mode. Confirm selected-only behavior and final color output; TypeScript cannot prove either.
Sources
- Selection, SelectiveBloom, Bloom.
- Released wrapper source — composer, SSAO, refs, and target types.
- Postprocessing, Three.js migration guide.
Related skills
More from enzed/r3f-skills and the wider catalog.

r3f-shaders
Implement custom GLSL or TSL materials in React Three Fiber with uniforms and vertex deformation.

r3f-textures
Configure textures in React Three Fiber: color spaces, UV channels, sampling, video, and render targets.

r3f-animation
Animate React Three Fiber objects with useFrame, damping, and GLTF clips.

r3f-fundamentals
Set up React Three Fiber scenes, Canvas, typed JSX, hooks, and resource ownership.

bb-browser
Browser automation with login state for accessing public and private information across 36+ platforms.

fusion-code-conventions
Enforce TypeScript, React, C#, and Markdown code conventions, ADR compliance, and intent documentation.