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_floatsupport. - 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