GPGPU physics for Three.js
Launch demo or watch the video. NOTE: Works only on desktops with good GPUs.
Include gp.js into your Three.js project HTML:
<script src="gp.js"></script>
Sample code below. See the examples/ directory for full examples.
// Create a simulation world
var world = new gp.World({
renderer: threejsRenderer, // Must be a THREE.WebGLRenderer
maxBodies: 128 * 128, // Max number of bodies
maxParticles: 128 * 128, // Max number of particles (each body consists of a number of particles)
radius: 0.05, // Size of a particle in the simulation
stiffness: 100, // Contact stiffness
damping: 0.4, // Contact damping
fixedTimeStep: 1/60, // Simulation timestep
boxSize: new THREE.Vector3(10,10,10), // World collision bounds
// The "grid" is a box where collisions can occur. Specify its position and resolution.
// The size of the grid box is gridResolution * radius * 2
gridPosition: new THREE.Vector3(0,0,0),
gridResolution: new THREE.Vector3(128,16,128),
gravity: new THREE.Vector3(0,-1,0),
friction: 0.4,
drag: 0.3,
});
// Create a body
// position rotation mass inertia
var bodyId = world.addBody(0, 0, 0, 0,0,0,1, 1, 0.1,0.1,0.1);
world.addParticle(bodyId, 0,0,0); // Add a particle in the center of the body
// Get the UV coordinate for the body
var uv = world.getBodyUV(bodyId);
myCustomShaderMaterial.uniforms.bodyUV.value = uv;
// A simple render loop can look like this:
var prevTime;
function render(time) {
requestAnimationFrame(render);
// Calculate time since last frame
var deltaTime = prevTime ? (time - prevTime) / 1000 : 0;
prevTime = time;
// Update physics
world.step( deltaTime );
// Use textures from the world, they contain positions and rotations of all bodies.
// Note: you need to fetch these textures every frame from the World, since they are swapped by the World every step.
myCustomShaderMaterial.uniforms.bodyPositionTex.value = world.bodyPositionTexture;
myCustomShaderMaterial.uniforms.bodyQuaternionTex.value = world.bodyQuaternionTexture;
// Render scene
renderer.render( scene, camera );
}
requestAnimationFrame(render);
The demo is largely based on GPU Gems 3 ch. 29, Real-Time Rigid Body Simulation on GPUs. It heavily relies on the THREE.WebGLRenderTarget
class and custom shaders.
The simulation loop is in short: