Using GPUComputationRenderer for Real-Time Fluid and Particle Simulations in Three.js

Overview

The GPUComputationRenderer utility in Three.js allows you to offload heavy calculations—like physics, fluid dynamics, or particle systems—onto the GPU using fragment shaders. This enables real-time, high-performance simulations that would otherwise be too expensive on the CPU.

What is GPUComputationRenderer?

It’s a helper class in Three.js that turns fragment shaders into GPU-based computation kernels. Instead of rendering pixels to the screen, you’re rendering to offscreen DataTextures used as input/output buffers.

Use Case: Fluid Simulation or Particle Swarming

Think of:

  • Water surface ripples
  • Smoke-like particle systems
  • Flocking boids
  • Fireworks / sand effects

Core Setup

1. Initialize the computation renderer:

const gpuCompute = new GPUComputationRenderer(width, height, renderer);

2. Create data textures to store simulation state:

const dtPosition = gpuCompute.createTexture();
const dtVelocity = gpuCompute.createTexture();

3. Fill these textures with initial values:

function fillPositionTexture(texture) {
  const data = texture.image.data;
  for (let i = 0; i < data.length; i += 4) {
    data[i] = Math.random() * 100 - 50;  // x
    data[i + 1] = Math.random() * 100 - 50; // y
    data[i + 2] = Math.random() * 100 - 50; // z
    data[i + 3] = 1.0; // padding
  }
}

4. Create shader variables for compute steps:

const velocityVariable = gpuCompute.addVariable("textureVelocity", velocityShader, dtVelocity);
const positionVariable = gpuCompute.addVariable("texturePosition", positionShader, dtPosition);

5. Set dependencies:

gpuCompute.setVariableDependencies(velocityVariable, [velocityVariable, positionVariable]);
gpuCompute.setVariableDependencies(positionVariable, [positionVariable, velocityVariable]);

6. Initialize the renderer:

gpuCompute.init();

7. In your animation loop:

gpuCompute.compute();

material.uniforms.texturePosition.value = gpuCompute.getCurrentRenderTarget(positionVariable).texture;

Common Effects You Can Simulate

  • Gravity: Apply force to particles downward.
  • Wind: Offset velocities directionally.
  • Repulsion/Attraction: Use inverse-square laws.
  • Obstacles: Detect collision boundaries via shader logic.

Optimization Tips

  • Use Float textures: Ensure you have OES_texture_float support.
  • Minimize uniform writes: Pass in bulk data via textures when possible.
  • Offload physics completely: Avoid syncing back to CPU every frame.

Real Examples

  • Yves Lesaout’s fire/smoke simulations
  • Boids simulations using flocking rules
  • Interactive sandboxes and ripple tanks

Leave a comment

Your email address will not be published. Required fields are marked *