00:00/00:00
3:22
00:03:22

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

Unlock content 🔓

To get access to 91 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? 🤘

57%

That's the end of the free part 😔

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

Next lesson
41.

GPGPU Flow Field Particles

Difficulty Very hard

Introduction 00:00

A rather difficult technique I get questions about, is the field of particles you can see on Chartogne Taillet website:

Particles seem to move as if they are influenced by various streams pushing them around. There are actually two techniques implemented:

  • GPGPU
  • Flow field

We are going to explain both techniques and apply them in order to animate the following model https://sketchfab.com/3d-models/mv-spartan-e2c3ced464f14e3b864f15871bf6d87d

Setup 02:10

The starter is quite similar to the previous lesson with particles ready to be enhanced:

  • A tweakable clearColor
  • A model file named model.glb that you can find in the static/ folder (you can download the original Blender file using the Resources button)
  • A GLTFLoader instance with a DracoLoader instance associated with it
  • A sphere made out of particles using a ShaderMaterial
  • The vite-plugin-glsl dependency to handle GLSL files
  • OrbitControls to rotate around

Regarding the particles shader:

  • The size is already handled with perspective and we can control it using the uSize tweak
  • Particles are shaped as discs
  • The color is sent from the vertex to the fragment as the vColor varying

Theory 03:44

GPGPU and flow field, what’s the difference?

GPGPU stands for General-Purpose computing on Graphics Processing Units. It’s a way of using the GPU to process data rather than rendering pixels for the end-user. It’s great for when you need to do the same complex calculation thousands of times.

Flow field corresponds to spatialized streams. For any point in space, we calculate a direction:

Now imagine throwing a particle on a flow field. For each frame, we would calculate the stream direction for the particle and make it move accordingly, resulting in the particle moving around:

Unfortunately, a flow field takes up a considerable amount of computing power. As a result, doing the calculation for each frame for thousands and thousands of particles using just the CPU wouldn’t be possible, which is why we are going to use the aforementioned GPGPU.

Persistence

An important aspect of the problem is that the data needs to persist. Until now, when doing animation on particles, we have been calculating a sort of snapshot of where all particles should be.

In the case of a flow field, the trajectory of the particle is unpredictable and keeps on evolving with time. We need to save the current position of all particles to use it on the next frame.

We can’t save the result in the attribute because updating would result in a catastrophic frame rate if used on too many particles.

And this is where the GPGPU solves our problem perfectly. As mentioned earlier, GPGPU helps us process data using the GPU. To do that, it utilizes what we call FBO (Frame Buffer Object).

FBOs are textures in which we save the renders instead of doing it on the <canvas> and they can be created in Three.js using WebGLRenderTarget.

In the case of particles, we use each pixel of the texture for one particle where the RGB channels correspond to the XYZ coordinates. And the A channel can be used for something else if we need (which we are going to need):

Instead of using the classic position attribute on the particles vertex shader, we use the FBO generated and updated by the GPGPU:

On each frame, we update the FBO according to the previous FBO. This way, the position of the particles persists and we keep on updating them.

Creating our own GPGPU

Although it may seem very interesting, creating our own GPGPU is quite daunting. We are going to use a solution that will save us a lot of time and headaches. Yet, it’s important to understand the technique in order to use it properly, allowing us to achieve the best result possible.

Here’s how it would go if we were to do it ourselves.

First, we need to create a brand new offscreen scene. This scene is independent from the actual scene that the user sees.

In it, we put a camera facing a plane which fills the camera view perfectly.

To that plane, we apply a custom shader. To that custom shader, we send the FBO texture containing the position of the particles. But instead of just displaying the texture, the custom shader updates the pixels, thus updating the particles.

And this is where we calculate and apply the flow field to the pixels as if the RGB channels were XYZ coordinates.

Then, before rendering the real scene, we render that offscreen scene using the offscreen camera and save the result in an FBO.

For the next frame, we send the result of the previously rendered FBO to the plane shader and complete a new render while applying the flow field again to the pixels.

And again for the next frame. And again, and again.

We end up with an FBO (a texture) containing the particle coordinates, while the pixels are being updated for each frame. These updates are done in the blink of an eye thanks to the GPU.

Want to learn more?

That's the end of the free part 😔

To get access to 91 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:

Discord