Not a Propaganda Machine

    TypeScript icon, indicating that this package has built-in type declarations

    2.7.0 • Public • Published


    Version Downloads Discord Shield

    react-postprocessing is a postprocessing wrapper for @react-three/fiber. This is not (yet) meant for complex orchestration of effects, but can save you hundreds of LOC for a straight forward effects-chain.

    npm install @react-three/postprocessing

    Bubbles Take Control

    These demos are real, you can click them! They contain the full code, too. 📦

    Why postprocessing and not three/examples/jsm/postprocessing?


    This library provides an EffectPass which automatically organizes and merges any given combination of effects. This minimizes the amount of render operations and makes it possible to combine many effects without the performance penalties of traditional pass chaining. Additionally, every effect can choose its own blend function.

    All fullscreen render operations also use a single triangle that fills the screen. Compared to using a quad, this approach harmonizes with modern GPU rasterization patterns and eliminates unnecessary fragment calculations along the screen diagonal. This is especially beneficial for GPGPU passes and effects that use complex fragment shaders.

    Postprocessing also supports srgb-encoding out of the box, as well as WebGL2 MSAA (multi sample anti aliasing), which is react-postprocessing's default, you get high performance crisp results w/o jagged edges.

    What does it look like?

    Here's an example combining a couple of effects (live demo).

    Bubbles Demo
    import React from 'react'
    import { EffectComposer, DepthOfField, Bloom, Noise, Vignette } from '@react-three/postprocessing'
    import { Canvas } from '@react-three/fiber'
    function App() {
      return (
          {/* Your regular scene contents go here, like always ... */}
            <DepthOfField focusDistance={0} focalLength={0.02} bokehScale={2} height={480} />
            <Bloom luminanceThreshold={0} luminanceSmoothing={0.9} height={300} />
            <Noise opacity={0.02} />
            <Vignette eskil={false} offset={0.1} darkness={1.1} />



    The EffectComposer must wrap all your effects. It will manage them for you.

      enabled?: boolean
      children: JSX.Element | JSX.Element[]
      depthBuffer?: boolean
      disableNormalPass?: boolean
      stencilBuffer?: boolean
      autoClear?: boolean
      multisampling?: number
      frameBufferType?: TextureDataType
      /** For effects that support DepthDownsamplingPass */
      resolutionScale?: number
      renderPriority?: number
      camera?: THREE.Camera
      scene?: THREE.Scene


    Some effects, like Outline or SelectiveBloom can select specific objects. To manage this in a declarative scene with just references can be messy, especially when things have to be grouped. These two components take care of it:

      children: JSX.Element | JSX.Element[]
      enabled?: boolean
      children: JSX.Element | JSX.Element[]
      enabled?: boolean

    You wrap everything into a selection, this one holds all the selections. Now you can individually select objects or groups. Effects that support selections (for instance Outline) will acknowledge it.

      <EffectComposer autoclear={false}>
        <Outline blur edgeStrength={100} />
      <Select enabled>
        <mesh />

    Selection can be nested and group multiple object, higher up selection take precence over lower ones. The following for instance will select everything. Remove the outmost enabled and only the two mesh group is selected. You can flip the selections or bind them to interactions and state.

    <Select enabled>
      <Select enabled>
        <mesh />
        <mesh />
        <mesh />

    Selective bloom

    Bloom is selective by default, you control it not on the effect pass but on the materials by lifting their colors out of 0-1 range. a luminanceThreshold of 1 ensures that ootb nothing will glow, only the materials you pick. For this to work toneMapped has to be false on the materials, because it would otherwise clamp colors between 0 and 1 again.

    <Bloom luminanceThreshold={1} mipmapBlur />
    // ❌ will not glow, same as RGB [1,0,0]
    <meshStandardMaterial color="red"/>
    // ✅ will glow, same as RGB [2,0,0]
    <meshStandardMaterial emissive="red" emissiveIntensity={2} toneMapped={false} />
    // ❌ will not glow, same as RGB [1,0,0]
    <meshBasicMaterial color="red" />
    // ❌ will not glow, same as RGB [1,0,0], tone-mapping will clamp colors between 0 and 1
    <meshBasicMaterial color={[2,0,0]} />
    // ✅ will glow, same as RGB [2,0,0]
    <meshBasicMaterial color={[2,0,0]} toneMapped={false} />


    npm i @react-three/postprocessing

    DownloadsWeekly Downloads






    Unpacked Size

    77.9 kB

    Total Files


    Last publish


    • gsimone
    • giulioz
    • dropthebeatbro
    • drcmda