Free 3D Scene

Three.js Particle Wave

Ten thousand glowing particles arranged in a grid that ripples like the surface of water. A classic WebGL hero background, driven by one buffer of positions updated every frame.

  • dark
  • three.js
  • webgl
  • particles
  • animation
  • hero

The code

Plain HTML, CSS and JavaScript. Uses Three.js r160, loaded from a CDN, so there is nothing to install. Copy a single file, or choose "Full file" for a complete page you can save as index.html and open in a browser.

<canvas id="scene"></canvas>
<div class="overlay">
  <h1>Particle Wave</h1>
  <p>10,000 points, one draw call</p>
</div>

The AI prompt

Paste this into an AI coding tool to generate the same 3d scene, then ask it to adapt the colours, text or framework to your project.

Works with Claude · ChatGPT · Cursor · v0 · Bolt · Gemini
Create an animated particle-wave hero background with Three.js in a single HTML file.

Setup:
- Load Three.js as an ES module inside <script type="module"> with: import * as THREE from "https://cdn.jsdelivr.net/npm/three@0.160.0/build/three.module.js";
- A full-screen fixed <canvas id="scene"> over a dark vertical gradient (#05060f to #0b1238), with a centred overlay heading "Particle Wave" and the subtitle "10,000 points, one draw call".

Scene:
- WebGLRenderer (antialias, alpha, pixel ratio capped at 2) and a PerspectiveCamera (60 degree field of view) at position (0, 9, 26) looking at the origin.
- Build a 100 x 100 grid of points with 0.6 spacing, centred on the origin, by filling a Float32Array of positions (x, y, z per point) and attaching it to a BufferGeometry as the "position" attribute.
- Render it as THREE.Points with a PointsMaterial: colour 0x8fa0ff, size 0.12, transparent, opacity 0.9, sizeAttenuation true.

Animation:
- Use THREE.Clock. Each frame, loop over the grid and set each point's y to sin(ix * 0.3 + time * 1.2) * 0.9 + sin(iz * 0.25 + time * 0.9) * 0.9.
- Set geometry.attributes.position.needsUpdate = true after updating, slowly rotate the whole Points object around Y, then render.
- Include a resize handler that updates the renderer size and the camera aspect.
- If the user prefers reduced motion, keep time at 0 so the wave is static.

Add comments explaining the buffer layout and why needsUpdate is required.

How to build it, step by step

  1. 1

    Store every particle position in one Float32Array: three numbers (x, y, z) per point. Typed arrays are what the GPU reads directly.

  2. 2

    Wrap the array in a BufferAttribute and attach it to a BufferGeometry under the name 'position'.

  3. 3

    Use THREE.Points with a PointsMaterial. All 10,000 particles are drawn in a single draw call, which is why it stays fast.

  4. 4

    Animate by changing only the y values in the array. Adding two sine waves that depend on the grid index and on time produces the rolling surface.

  5. 5

    Set needsUpdate = true on the attribute. Without this flag Three.js does not re-upload the changed data and nothing moves.

  6. 6

    Place the camera above and behind the grid, looking at the centre, so you see the wave in perspective.

Customisation tips

  • Move the wave calculation into a vertex shader (ShaderMaterial) to animate hundreds of thousands of points on the GPU.
  • Add a per-point 'color' attribute and set vertexColors: true to colour particles by height.
  • Lower GRID to 60 on mobile devices for better battery life.
  • Add THREE.FogExp2 to the scene so distant particles fade into the background.

More 3d scenes