Three.js Getting Started: Your First Scene

Updated June 2026
Getting started with Three.js means setting up a project, creating the three core objects that every 3D application needs (a scene, a camera, and a renderer), adding geometry and lighting, and running an animation loop. This guide walks you through each step to produce a working 3D scene in the browser that you can build into a game.

Three.js abstracts the complexity of WebGL into a scene graph API that feels natural to JavaScript developers. Rather than managing shader programs, vertex buffers, and GPU state manually, you work with objects, materials, and lights. The learning curve is real, but the first working scene takes only a few dozen lines of code, and every concept you learn here carries directly into game development.

Step 1: Set Up Your Project

The fastest way to start a Three.js project in 2026 is with Vite, a modern build tool that provides hot module reloading and ES module support out of the box. Create a new directory for your project, initialize it with npm, and install Three.js as a dependency.

Run npm create vite@latest my-threejs-game -- --template vanilla in your terminal, then cd my-threejs-game and npm install three. This gives you a project with a development server, module bundling, and production builds. Open main.js and clear its contents, because you will write the Three.js code from scratch.

Alternatively, you can use Three.js without a build tool by importing it from a CDN. Add <script type="importmap"> to your HTML with an entry mapping "three" to a CDN URL like unpkg or jsDelivr. This approach works for prototyping but lacks the optimization benefits of a bundler for production games.

Create a minimal HTML file with a <canvas> element or let Three.js create one automatically. Remove any default margins and padding from the body with CSS, and set the canvas to fill the viewport. This fullscreen setup is standard for games.

Step 2: Create the Scene, Camera, and Renderer

Every Three.js application needs three objects. The Scene is the container that holds all your 3D objects, lights, and effects. The PerspectiveCamera defines the viewpoint with a field of view, aspect ratio, and near/far clipping planes. The WebGLRenderer (or WebGPURenderer) takes the scene and camera and produces the image on screen.

In your JavaScript file, import Three.js with import * as THREE from 'three'. Create a scene with const scene = new THREE.Scene(). Set its background color with scene.background = new THREE.Color(0x1a1a2e) to give it a dark blue tone rather than the default black.

Create a perspective camera with new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000). The first argument is the field of view in degrees, 75 is a good default for games. The aspect ratio should match the canvas dimensions to prevent stretching. Move the camera back with camera.position.z = 5 so it can see objects placed at the origin.

Create the renderer with new THREE.WebGLRenderer({ antialias: true }). Antialiasing smooths jagged edges on geometry. Set the renderer size to the window dimensions, set the pixel ratio with renderer.setPixelRatio(window.devicePixelRatio) for sharp rendering on high-DPI displays, and append the renderer's canvas element to the document body.

Step 3: Add a 3D Object

A visible object in Three.js is a Mesh, which combines a Geometry (the shape) with a Material (the surface appearance). Three.js includes many built-in geometries: boxes, spheres, cylinders, torus knots, planes, and more. For your first scene, a box or torus knot provides good visual feedback because their shapes make rotation visible.

Create a geometry with new THREE.TorusKnotGeometry(1, 0.3, 128, 32). The parameters control the size and detail level. Pair it with a material like new THREE.MeshStandardMaterial({ color: 0x6c63ff, roughness: 0.4, metalness: 0.6 }). MeshStandardMaterial uses physically-based rendering (PBR), meaning it responds to lights realistically based on roughness and metalness properties.

Combine them into a mesh with const mesh = new THREE.Mesh(geometry, material) and add it to the scene with scene.add(mesh). At this point, the object exists in the scene but nothing is visible yet because there are no lights and no rendering loop.

Step 4: Add Lighting

PBR materials like MeshStandardMaterial require light to be visible. Without lights, everything renders as black. Three.js provides several light types: ambient light illuminates all surfaces equally, directional light simulates distant sources like the sun, point lights emit from a single position, and spot lights create focused cones.

Add an ambient light with new THREE.AmbientLight(0xffffff, 0.4) to provide baseline illumination. The second parameter is intensity. Then add a directional light with new THREE.DirectionalLight(0xffffff, 1.0) and position it above and to the side with light.position.set(5, 10, 7). The directional light creates highlights and shadows that give your object three-dimensional depth.

For a more polished look, add a second directional light from the opposite side with lower intensity to fill in the shadows. You can also use HemisphereLight instead of ambient light for a more natural sky-to-ground color gradient that looks better in outdoor scenes.

Step 5: Create the Animation Loop

A static scene renders once and stops. Games need continuous rendering at the display's refresh rate. Three.js provides renderer.setAnimationLoop(callback), which calls your function every frame (typically 60 times per second) and handles pausing when the browser tab is not visible.

Define your animation function to update object properties and then render the scene. Rotate the mesh each frame with mesh.rotation.x += 0.01 and mesh.rotation.y += 0.015. Then call renderer.render(scene, camera) to draw the frame. Pass this function to renderer.setAnimationLoop.

For proper frame-rate independence, use a THREE.Clock and multiply rotation speeds by the delta time returned by clock.getDelta(). This ensures the object rotates at the same speed regardless of whether the browser runs at 30fps or 144fps. Frame-rate independence is essential for games, where inconsistent frame times are common on varying hardware.

You should now see a spinning torus knot with realistic lighting in your browser. This is the foundation that every Three.js game builds upon.

Step 6: Handle Window Resizing

When the browser window resizes, the camera's aspect ratio and the renderer's size must update to match. Without this, the scene stretches or crops when the window changes shape. Add a window resize event listener that updates camera.aspect to the new ratio, calls camera.updateProjectionMatrix() to apply the change, and sets the renderer size to the new dimensions.

Also update the pixel ratio in the resize handler in case the user moves the window between displays with different DPIs. Call renderer.setPixelRatio(window.devicePixelRatio) and renderer.setSize(window.innerWidth, window.innerHeight). This keeps the scene looking sharp on any display configuration.

Consider debouncing the resize handler if your scene is complex, because rapid resize events during window dragging can cause frame drops. A simple approach is to use requestAnimationFrame inside the resize handler to batch the update into the next frame.

Next Steps After Your First Scene

With a working scene in place, you are ready to start building toward a game. The next concepts to learn are loading 3D models instead of using primitive geometries, adding player controls so the user can interact with the scene, and building a proper game loop that separates update logic from rendering. Each of these topics is covered in depth in the guides linked below.

Experiment with different geometries and materials to build visual intuition. Try adding shadows by enabling them on the renderer (renderer.shadowMap.enabled = true), the light (light.castShadow = true), and individual meshes (mesh.castShadow = true, mesh.receiveShadow = true). Add a ground plane to catch shadows and create a sense of physical space. Each small experiment builds the knowledge base you need to tackle more complex game features.

Key Takeaway

Every Three.js application starts with the same three objects: a Scene to hold your world, a Camera to define the viewpoint, and a Renderer to draw each frame. Master this foundation and every other Three.js concept is an extension of it.