ANIMATED WHITE
CLOUD PARTICLES

Create soft, drifting clouds in the browser with Three.js — built from layered smoke sprites that face the camera and slowly rotate.

Three.js Animated White Cloud Particle System

LIVE DEMO

The soft clouds drifting behind this page are the live demo. Use the buttons to pause and resume the animation.

Introduction

Realistic clouds are surprisingly easy in Three.js. Instead of a complex GPU particle simulation, this free tutorial layers about 25 flat planes, each mapped with a soft, semi-transparent smoke texture. Scatter them through space, make each one face the camera, and rotate them slowly — the overlapping transparency blends into soft, volumetric-looking clouds.

It runs fast, looks great, and the whole effect is only a few dozen lines of code. Copy it below and drop it into any page.

Frequently Asked Questions

How do you make clouds in Three.js?

The simplest realistic cloud effect uses many flat planes, each mapped with a soft semi-transparent smoke texture. Scatter the planes through space, make each face the camera, and slowly rotate them. Overlapping transparent sprites blend into soft, volumetric-looking clouds.

Why use textured planes instead of real particles for clouds?

A soft smoke texture on a plane already looks like a puff of cloud. Layering 25 to 50 of these transparent, camera-facing planes and rotating them gives a convincing volumetric look for a tiny performance cost, without a complex GPU particle system.

How do you make a plane always face the camera in Three.js?

Call mesh.lookAt(camera.position) so the plane's normal points at the camera. This billboarding keeps each flat smoke sprite facing the viewer no matter where the camera moves, which is what sells the cloud illusion.

Is this Three.js cloud tutorial free?

Yes. This is a completely free tutorial. The full source code is shown on the page, you can copy it, and there is a live cloud demo running in the background. No sign-in or membership is required.

How To Add The Code

Follow these steps to get the cloud effect running on your own page. You need a plain HTML file, a soft smoke PNG texture, and Three.js from a CDN.

  1. 1Create an HTML file. Make a new file called index.html with the standard <!DOCTYPE html>, <head>, and <body> tags.
  2. 2Get a smoke texture. Save a soft, semi-transparent smoke PNG next to your HTML (e.g. smoke.png). A white puff on a transparent background works best.
  3. 3Load Three.js from a CDN. Just before your closing </body> tag, add the Three.js script so THREE is available.
  4. 4Add the cloud script. Below the Three.js tag, paste the full script shown below. It builds the scene, camera, renderer, and lighting.
  5. 5Load the texture. Use TextureLoader to load your smoke PNG so it can be applied to each plane.
  6. 6Create the cloud planes. In a loop, make ~25 transparent PlaneGeometry meshes at random positions, call lookAt(camera.position) so each faces the camera, and give each a random rotation speed.
  7. 7Animate and handle resize. Rotate every plane a little each frame inside requestAnimationFrame, and update the camera when the window resizes.
  8. 8Open it in your browser. Serve the folder locally (so the PNG loads) and you will see soft clouds drifting and turning.

Tip: browsers block local file textures over file://. Run a quick local server, e.g. python -m http.server, then open http://localhost:8000.

The Full Code

Paste this into index.html, put a smoke.png beside it, and serve the folder.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Three.js Animated Cloud Particle System</title>
  <style> body { margin: 0; background: #0a0b0f; } </style>
</head>
<body>

  <!-- 1. Load Three.js from a CDN -->
  <script src="https://cdn.jsdelivr.net/npm/three@latest/build/three.min.js"></script>

  <!-- 2. The cloud system -->
  <script>
    // Scene, camera, renderer
    const scene = new THREE.Scene();
    const camera = new THREE.PerspectiveCamera(
      100, window.innerWidth / window.innerHeight, 1, 4000
    );

    const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.setClearColor(0x0a0b0f, 1);
    document.body.appendChild(renderer.domElement);

    // Light so the smoke material is visible
    const ambient = new THREE.AmbientLight(0xffffff, 5);
    scene.add(ambient);

    // Load a soft smoke texture (put smoke.png next to this file)
    const smokeTexture = new THREE.TextureLoader().load('smoke.png');

    // Build ~25 camera-facing smoke planes
    const planes = [];
    for (let i = 0; i < 25; i++) {
      const geometry = new THREE.PlaneGeometry(15, 15);
      const material = new THREE.MeshPhongMaterial({
        map: smokeTexture,
        transparent: true,
        opacity: 1,
        depthTest: false
      });
      const plane = new THREE.Mesh(geometry, material);

      // Random position in space
      plane.position.set(
        Math.random() * 30 - 15,
        Math.random() * 30 - 15,
        -2
      );

      // Face the camera (billboard)
      plane.lookAt(camera.position);

      // Give each plane its own slow spin
      plane.userData.speed = Math.random() * 0.3;
      scene.add(plane);
      planes.push(plane);
    }

    // Animation loop
    const clock = new THREE.Clock();
    function animate() {
      requestAnimationFrame(animate);
      const delta = clock.getDelta();
      for (const plane of planes) {
        plane.rotateOnAxis(new THREE.Vector3(0, 0, 1), plane.userData.speed * delta);
      }
      renderer.render(scene, camera);
    }
    animate();

    // Keep it sharp on resize
    window.addEventListener('resize', () => {
      camera.aspect = window.innerWidth / window.innerHeight;
      camera.updateProjectionMatrix();
      renderer.setSize(window.innerWidth, window.innerHeight);
    });
  </script>
</body>
</html>

What To Try Next

  • Increase the loop count to 50+ planes for denser, fuller clouds.
  • Tint the MeshPhongMaterial with a color for stormy grey or sunset orange clouds.
  • Lower each plane's opacity (e.g. 0.4) so overlaps blend more softly.
  • Slowly drift the whole cloud group along X for a windswept sky.
  • Add colored lights that move to make the clouds shift hue over time.