Choosing the a bcd
00:00/00:00TIME LEFT

Shortcuts ⌨️

  • SPACE to play / pause
  • ARROW RIGHT or L to go forward
  • ARROW LEFT or J to go backward
  • ARROW UP to increase volume
  • ARROW DOWN to decrease volume
  • F to toggle fullscreen
  • M to toggle mute
  • 0 to 9 to go to the corresponding part of the video
  • SHIFT + , to decrease playback speed
  • SHIFT + . or ; to increase playback speed

Subtitles 💬

Subtitles are only available for members

To get access to 72 hours of video, a members-only Discord server and future updates, join us for only $95!

⚠️ Update

Use version 2.14 of @react-three/postprocessing:

npm install @react-three/postprocessing@2.14

⚠️ Update

You might notice that all materials are changing when adding <EffectComposer>.

It’s a bug in the latest versions of @react-three/postprocessing due to EffectComposer rendering the scene with MeshNormalMaterial for later use in the effects.

It’ll automatically disappear once you add effects and you can ignore it.

⚠️ Update

Use version 6.31 of postprocessing:

npm install postprocessing@6.31

Want to learn more? 👍


That's the end of the free part 😔

To get access to 72 hours of video, a members-only Discord server and future updates, join us for only $95!

Next lesson


Difficulty Very hard

Starter packFinal project

Introduction 00:00

Post-processing also benefits from the React and R3F system, as it got easier to implement but is also optimised in some ways.

In this lesson, we are going to learn how it differs from the post-processing techniques we’ve covered before, implement a bunch of effects and even create our own effect.

Before starting 01:20

The issue with post-processing 02:41

In the previous lessons, we used post-processing by adding passes.

Those passes had their own code and were completing one or multiple renders in order to get the wanted result.

Then the next pass would do the same, and again, and again.

Those passes all occurred independently and some of them were doing the same renders (depth renders, normal renders, etc.) which resulted in performance issues and limited the number of passes we could add before getting a frame rate drop.

The solution 04:31

And this is exactly what Post Processing is trying to resolve.

The various passes will be merged into the least number of passes possible. Actually we don’t talk about passes anymore, but we talk about “effects”.

Those effects will be merged together into one or multiple passes (if needed) automatically while keeping the order in which we added them.

We can even choose the blending of each effect (more about that later).

And, as you might’ve guessed, we can use Post Processing in R3F with @react-three/postprocessing.

Setup 06:51

In the starter, we have the classic orange sphere, purple cube and green floor.

We also have a directional light source and an ambient light source.

The @react-three/drei dependency is already installed within the project and we are using the OrbitControls helper to be able to move the camera around.

We also have <Perf /> from r3f-perf in order to keep an eye on performance.

Implement 07:50

We need two dependencies, @react-three/postprocessing, and postprocessing.

But for now, the only one we need to install is @react-three/postprocessing since this dependency will also install postprocessing.

In the terminal, use npm install @react-three/postprocessing@2.14 (we force the versions to prevent surprises, you can ignore potential vulnerability warnings).

In Experience.jsx, import EffectComposer from @react-three/postprocessing:

import { EffectComposer } from '@react-three/postprocessing'

Although it’s the same name as the EffectComposer we used in native Three.js, it’s not the same class.

Now, add it to the JSX:

export default function Experience()
    return <>


        {/* ... */}


Adding effects is as simple as importing the effect and adding it to the <EffectComposer>.

We don’t even need to add the first render, since Post Processing will take care of that.

Be careful, in the following parts, you might have to reload the page after tweaking or adding an effect.


We can set various attributes to the <EffectComposer>, but the most interesting one is multisample.

As discussed in the previous lessons, multi-sampling is used to prevent the aliasing effect (the little stairs on the edges of geometries).

By default, its value is at 8 and we can lower it down to 0 in order to disable it completely.

<EffectComposer multisampling={ 0 }>

(Note that you will probably not see a big difference in the screenshot above because of the image compression)

Performance should be better when disabling multi-sampling, but we don’t really care about that in this lesson, so let’s remove it and keep the default value:


Finding effects and how to implement them 13:08

In the following part of the lesson, we are going to test a bunch of effects for the sake of learning.

We are going to set very specific values without going too much into detail because it would take ages and be boring.

But you should roam the documentations in order to discover the various effects, test them and see how they work.

Unfortunately, those documentations (though useful) are a bit messy and spread across react-postprocessing and Post Processing, which means you’ll have to dig a little in order to find what you are looking for.

Here are the links that you might need.

Post Processing:


Vignette effect 18:01

Let’s start with a very common effect, the Vignette effect.

Vignette will make the corners of the render a little darker.

Want to learn more?

That's the end of the free part 😔

To get access to 72 hours of video, a members-only Discord server and future updates, join us for only $95!

How to use it 🤔

  • Download the Starter pack or Final project
  • Unzip it
  • Open your terminal and go to the unzip folder
  • Run npm install to install dependencies
    (if your terminal warn you about vulnerabilities, ignore it)
  • Run npm run dev to launch the local server
    (your browser should start automatically)
  • Start coding
  • The JS is located in src/script.js
  • The HTML is located in src/index.html
  • The CSS is located in src/style.css

If you get stuck and need help, join the members-only Discord server: