How It Works

Every Three.js application has the same core structure: a Scene (the 3D world), a Camera (what you see), and a Renderer (draws it to the screen). You add objects to the scene, position the camera, and call renderer.render(scene, camera) every frame.

Objects in Three.js are called Meshes — a combination of Geometry (the shape) and Material (the surface appearance). In this tutorial, we use a BoxGeometry (cube shape) with a MeshStandardMaterial (physically-based surface that responds to light).

COMPLETE SOURCE CODE

Copy this code into an HTML file and open it in your browser to see it in action:

HTML / Three.js
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>My First Three.js Scene - Spinning Cube</title>
    <style>
        /* Remove default margins and fill the entire window */
        body { margin: 0; overflow: hidden; }
        canvas { display: block; }
    </style>
</head>
<body>
    <!-- Load Three.js from CDN -->
    <script src="https://cdn.jsdelivr.net/npm/three@latest/build/three.min.js"></script>

    <script>
    // ============================================================
    // STEP 1: CREATE THE SCENE
    // The scene is the 3D world that holds all your objects
    // ============================================================
    const scene = new THREE.Scene();
    scene.background = new THREE.Color(0x1a1a2e);  // Dark blue background

    // ============================================================
    // STEP 2: CREATE THE CAMERA
    // The camera defines what the viewer sees
    // PerspectiveCamera(fieldOfView, aspectRatio, near, far)
    // ============================================================
    const camera = new THREE.PerspectiveCamera(
        75,                             // Field of view (degrees)
        window.innerWidth / window.innerHeight,  // Aspect ratio
        0.1,                            // Near clipping plane
        1000                            // Far clipping plane
    );
    camera.position.z = 4;  // Move camera back so we can see the cube

    // ============================================================
    // STEP 3: CREATE THE RENDERER
    // The renderer draws the scene to a canvas element
    // ============================================================
    const renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.setPixelRatio(window.devicePixelRatio);
    document.body.appendChild(renderer.domElement);  // Add canvas to page

    // ============================================================
    // STEP 4: CREATE A CUBE
    // A Mesh = Geometry (shape) + Material (surface)
    // ============================================================
    const geometry = new THREE.BoxGeometry(1.5, 1.5, 1.5);  // Width, Height, Depth

    const material = new THREE.MeshStandardMaterial({
        color: 0x00d4ff,      // Cyan color
        metalness: 0.3,       // Slightly metallic
        roughness: 0.4,       // Slightly smooth
    });

    const cube = new THREE.Mesh(geometry, material);
    scene.add(cube);  // Add the cube to the scene

    // ============================================================
    // STEP 5: ADD LIGHTING
    // Without light, MeshStandardMaterial appears black!
    // ============================================================

    // Point light - like a light bulb in 3D space
    const pointLight = new THREE.PointLight(0xffffff, 1.5, 50);
    pointLight.position.set(3, 3, 5);  // Position the light
    scene.add(pointLight);

    // Ambient light - soft fill light everywhere (no shadows)
    const ambientLight = new THREE.AmbientLight(0xffffff, 0.3);
    scene.add(ambientLight);

    // ============================================================
    // STEP 6: ANIMATION LOOP
    // This function runs ~60 times per second
    // ============================================================
    function animate() {
        requestAnimationFrame(animate);  // Schedule next frame

        // Rotate the cube a little each frame
        cube.rotation.x += 0.01;   // Rotate around X axis
        cube.rotation.y += 0.015;  // Rotate around Y axis

        // Draw the scene from the camera's perspective
        renderer.render(scene, camera);
    }

    // ============================================================
    // STEP 7: HANDLE WINDOW RESIZE
    // Keep the scene looking correct if the window size changes
    // ============================================================
    window.addEventListener('resize', () => {
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize(window.innerWidth, window.innerHeight);
    });

    // Start the animation!
    animate();
    </script>
</body>
</html>

Code Breakdown

Let's walk through each section of the code to understand exactly what's happening.

Step 1: The Scene

The THREE.Scene() is the container for everything in your 3D world. Think of it as an empty room — you'll add objects, lights, and cameras to it. The scene.background sets the color you see behind all objects (like painting the walls of the room).

Step 2: The Camera

PerspectiveCamera simulates how human eyes see — objects farther away appear smaller. The four parameters are:

We position the camera at z = 4 so it's looking at the origin (0,0,0) where our cube will be, from 4 units away.

Step 3: The Renderer

WebGLRenderer creates a <canvas> element and uses WebGL to draw 3D graphics on it. antialias: true smooths jagged edges. We set it to fill the full window and append it to the page body.

Step 4: The Cube (Mesh)

A Mesh is the fundamental visible object in Three.js. It combines:

Step 5: Lighting

Without light, MeshStandardMaterial renders as pure black. We add two lights:

Step 6: The Animation Loop

requestAnimationFrame(animate) tells the browser to call our animate function before the next screen repaint (~60 times per second). Each frame, we rotate the cube slightly and re-render. This creates smooth, continuous animation. Without this loop, you'd see a single static frame.

Step 7: Resize Handling

If the user resizes their browser window, we need to update the camera's aspect ratio and the renderer's size. Without this, the scene would look stretched or cropped after a resize.

Next Steps

Now that you have a working 3D scene, try these experiments: