This is what 3D game particle VFX looks like in the browser. 4 000 particles orbit through WebGL space — move your cursor and a displacement wave ripples outward exactly like a magic spell or shockwave hit in a 3D HTML5 game. Three.js handles the GPU rendering; you write the physics. The same technique powers particle explosions, portal effects, and enemy death bursts in browser-based 3D games.
A BufferGeometry-powered particle cloud where the cursor position is projected onto a 3D plane and a radial force field repels nearby particles. Each particle stores position and velocity in a Float32Array updated entirely on the CPU each frame.
Three.js Particle Cursor Effect
How the Three.js particle cursor effect works
Create a THREE.BufferGeometry and attach a Float32Array of 4 000 × 3 floats as the position attribute. A parallel array stores velocities. Each frame, use a THREE.Raycaster to project the normalized mouse coordinates (NDC) onto a plane at z = 0 to get the 3D intersection point. For each particle within the repulsion radius, compute the distance, scale the impulse inversely, and add it to the velocity. Damp all velocities by 0.92. Update the position attribute and set needsUpdate = true.
The jump from Canvas 2D to Three.js WebGL is not just about particle count. It unlocks additive blending (blending: THREE.AdditiveBlending) which makes dense clusters bloom white—an effect that is physically expensive to fake in 2D Canvas. It also opens the door to vertex shaders that color each particle by speed or distance from center without any per-particle JS color logic.
const geometry = new THREE.BufferGeometry();
geometry.setAttribute(
'position',
new THREE.BufferAttribute(positions, 3)
);
const points = new THREE.Points(
geometry,
new THREE.PointsMaterial({ size: 0.028 })
);
All 4 000 particle positions live in one Float32Array sent to the GPU as a single buffer. The key line after updating it: geometry.attributes.position.needsUpdate = true.
Canvas 2D vs Three.js particles: when to use which
Canvas 2D handles 200–800 particles comfortably on any device. Three.js WebGL handles 10 000–100 000, with the upper limit set by your vertex shader complexity and GPU fill rate rather than CPU cycles. Use Canvas 2D when you need simplicity and maximum browser compatibility. Use Three.js when you need scale, depth, custom shaders, or scene integration with 3D objects.
For this demo, 4 000 particles is the sweet spot: visually dense enough to feel like a cloud, simple enough that a mid-range phone can sustain 60 fps. The repulsion radius and force strength are the two tuning knobs that control how the cloud responds—wider radius for a softer "breath," higher force for a sharp scatter.
Never construct a new Float32Array inside the animation loop—allocate once at init time and overwrite values in-place. Call geometry.attributes.position.needsUpdate = true after each update, not before. Cap renderer.setPixelRatio to 2 on Retina screens; 3× or 4× DPR triples the fragment shader work for minimal visual gain.
Where to take this next
Replace the PointsMaterial with a custom ShaderMaterial that reads each particle's velocity magnitude as a uniform and maps it to color—fast-moving particles glow white, slow ones fade to blue. Add a secondary attractor point that orbits the center to give the cloud a vortex shape at rest. Or scale to 20 000 particles and move the physics to a compute shader using WebGPU.
Frequently asked questions
How is this different from the Canvas 2D particle cursor post?
The Canvas version uses 520 particles on the CPU with 2D drawing. This Three.js version uses 4 000 particles on the CPU with WebGL rendering, additive blending, and perspective projection. The physics formula is nearly identical—comparing both posts side by side is an excellent way to understand when WebGL overhead is justified by the visual payoff.
Can I use a texture for each particle instead of a dot?
Yes. Pass a THREE.TextureLoader-loaded sprite to PointsMaterial.map and set transparent: true, alphaTest: 0.01. Use a white radial gradient PNG for soft circular glows, or a star sprite for a starfield effect. The rest of the physics code stays identical.
Related experiments
- JavaScript Particle Cursor Effect with Canvas
- JavaScript Magnetic Button Effect
- JavaScript Neon Mouse Trail Animation
Part of a weekly series on visual JavaScript, modern CSS, browser graphics, and HTML5 games—one live experiment per post, production-ready code snippets, and the reasoning behind each technique.
No comments:
Post a Comment