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

⚠️ Update

Since the version 0.152 of Three.js outputEncoding has been replaced by outputColorSpace:

renderer.outputColorSpace = THREE.SRGBColorSpace

But the idea stays the same.

Unlock content 🔓

To get access to 93 hours of video, a members-only Discord server, subtitles, lesson resources, future updates and much more join us for only $95!

Want to learn more? 👍


That's the end of the free part 😔

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

Next lesson


Difficulty Hard

Introduction 00:00

Post-processing is about adding effects on the final image (the render). People mostly use this technique in filmmaking, but we can do it in WebGL too.

Post-processing can be subtle to improve the image slightly or to create huge effects.

Here are some examples of what you can use post-processing for:

  • Depth of field
  • Bloom
  • God ray
  • Motion blur
  • Glitch effect
  • Outlines
  • Color variations
  • Antialiasing
  • Reflections and refractions
  • Etc.

Setup 01:24

We will use the same setup as the Realistic Model Render lesson but with the Damaged Helmet model by Leonardo Carrion. It's a popular model with many details and good textures that should go well with our post-processing.

How it works 01:57

Most of the time, post-processing works the same way.

Render target

Instead of rendering in the canvas, we do the render in what we call a render target. That render target will give us a texture very similar to the usual texture. In a simpler way, we render in a texture instead of the canvas on the screen.

The term "render target" is specific to Three.js. Other contexts mostly use the word "buffer".

This texture is then applied to a plane facing the camera and covering the whole view. This plane uses a material with a special fragment shader that will do the post-processing effect. If the post-processing effect consists of redden the image, it would merely multiply the red value of the pixel in that fragment shader.

Most post-process effects are doing more than just tweaking the color values, but you get the idea.

In Three.js those "effects" are called "passes". We will refer to that term from now on.

Ping-pong buffering

We can have multiple passes on our post-process: one doing the motion blur, one doing the color changes, one doing the depth of field, etc. Because we can have multiples passes, the post-processing needs two render targets. The reason is that we can't get the texture of a render target while drawing in it at the same time. The idea is to draw in the first render target while taking the texture from the second one. At the next pass, we switch those render targets, take the texture from the second, and draw on the first. And again at the next pass, we switch them, and again, and again. That is what we call ping pong buffering.

Final pass on the canvas

The last pass won't be in a render target because we can put it directly on the canvas so the user can see the final result.

In the end

All of these can be very complicated for beginners, but, fortunately, we don't have to do it on our own.

Actually, we could have start without even explaining those render target, textures, ping pong buffering, etc. but it's always good to understand what is really going on behind the scene.

All we have to do is use the EffectComposer class that will handle most of the heavy lifting for us.

Want to learn more?

That's the end of the free part 😔

To get access to 93 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 warns you about vulnerabilities, ignore it)
  • Run npm run dev to launch the local server
    (project should open on your default browser 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: