Multithreaded.Link
menu close

Start making 3D web apps with three.js

Overview

three.js is an open-source 3D rendering library for browsers. Using three.js you can create complex and interactive 3D animations that run smoothly in the browser. The library uses WebGL, a cross-browser JavaScript API for creating 3D graphics in the browser. WebGL is a powerful technology but it is difficult and labor-intensive to directly work with it. three.js provides a simpler and more-productive way of working with WebGL, like how jQuery provides a simpler and more-productive way of manipulating web pages instead of vanilla JavaScript.

You can do most anything visually in three.js and it has support for expert-level 3D animation features like custom shaders. This is a valuable library to know. Many large companies have developed super-premium web applications using three.js. Two of my favorite ones are the Ford Mustang Customizer and the 3D Middle-Earth from the Hobbit movie. This article will get your feet wet with three.js and building a simple scene. As a prerequisite you should have a working familiarity with JavaScript. You don’t need to know anything special about 3D modeling or anything like that. At the end of it you should be ready to go off and make more involved projects.

Preparing to begin

The very first thing you should do is download the three.js file. Next, create an empty folder for this project to live in and put the three.js file into it. Third, create an empty index.html file and add this boilerplate to it:

<html>
    <head> 
        <style> 
            /* Make the render take up the entire screen. */
            canvas { width: 100%; height: 100% } 
        </style> 
        <script src="three.js"></script> 
    </head> 
    <body> 
        <script> 
           /* We'll be working here. */
        </script> 
    </body>
</html>

The first render

Every page needs three things at minimum: A scene, a camera, and a renderer.

The scene is where all of the 3D objects will live. You can have multiple scenes like a movie has multiple scenes, and you can add and remove objects from the scene at any time. If you want to add fog effects those are also part of the scene.

The camera determines the angle and position that the application will be rendered from. You can think of it like a movie camera. You can have close-up cameras, overhead cameras, moving cameras, etc. It is possible to have multiple cameras in your scene and switch between them. You can even make mouse-controlled first-person shooter cameras.

The renderer handles, well, rendering. It draws the scene onto the screen. There are a few different types of renderers. My preferred one is the WebGLRenderer because it allows the computer’s graphics card to handle animation processing, but there is also a CanvasRenderer for slower, more cross-browser compatible rendering.

Let’s go ahead and add these:

/**
 * We're using a perspective camera.
 * This makes far things look smaller and close ones bigger.
 * Param 1: The field of view of the camera.
 * Param 2: The aspect ratio.
 * Param 3: Minimum distance from camera to render.
 * Param 4: Maximum distance from camera to render.
 */
var camera = new THREE.PerspectiveCamera( 90, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.z = 20; // Position the camera at 0, 0, 20.

/**
 * Standard scene and renderer.
 */
var scene = new THREE.Scene();
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );

/**
 * Add the renderer to the DOM.
 * This creates a canvas that will have the rendered content.
 */
document.body.appendChild( renderer.domElement );

/**
 * Start and run the animation loop.
 * This renders the screen 60 times a second.
 */
function animate() {
    requestAnimationFrame( animate );
    renderer.render( scene, camera );
}
animate();

Save the page and load it up in the browser. It’s pretty boring so far. If you inspect the page using the web inspector, you should see there is a blank canvas taking up the whole page.

Meshes

Let’s add a mesh to the scene. A mesh is a 3D shape covered by a material. three.js has a few simple built-in shapes like cubes and cylinders, etc. You can also load up custom ones created with 3D animation software like Blender. That will be covered in a future article, and I’ll provide a link here when that’s ready.

We are going to add a cone:

/**
 * ConeGeometry defines the shape of the cone.
 * Param 1: Radius.
 * Param 2: Height.
 * Param 3: Number of radius segments.
 * Param 4: Number of height segments.
 */
var cone_geometry = new THREE.ConeGeometry( 5, 15, 50, 20 );

/**
 * The material defines the cone's covering.
 * MeshBasicMaterial does not interact with light.
 */
var cone_mesh = new THREE.MeshBasicMaterial({color:0xff0000});

/**
 * Create the mesh and add it to the scene.
 */
var cone = new THREE.Mesh( cone_geometry, cone_mesh );
scene.add( cone );

Save your work and take a look.

Getting there. Our cone looks very flat and not very 3D, though. We need to really get it looking 3D.

Light

What we need now is some light. three.js has a few different types of lights for all your light needs, including spotlights, ambient lights, and point lights. For this example we are going to use a directional light. Add the following code:

/**
 * Add the light.
 * DirectionalLight is a light that goes in one direction.
 * Set the position and rotation to get it pointed how you want.
 * Param 1: Light color.
 * Param 2: Light intensity.
 */
var light = new THREE.DirectionalLight( 0x4444FF, 5 );
light.position.x = 10;
light.position.z = 20;
scene.add( light );

Save your work and take another gander.

Hold up now. This looks just like the last one! This is because we used the MeshBasicMaterial, and it doesn’t interact with light. Let’s take a look at materials and see if there isn’t a better one to use.

Materials

A material is a fabric, texture, or other such covering for a model. It’s essentially the fabric that gets stretched over the geometric wireframe. It determines what color something is and how it interacts with the light. There are a few different types of materials in three.js, but there are three main ones that I use the most:

MeshBasicMaterial doesn’t interact with light, so it’s a good one to use for prototyping since you don’t have to set up lights.

MeshLambertMaterial is a good one for regular surfaces.

MeshPhongMaterial is a high-gloss material excellent for shinier surfaces.

For this cone we will use the MeshPhongMaterial to give it a hard, shiny look. Change the material line you previously had to this one:

var cone_mesh = new THREE.MeshPhongMaterial({color:0xff0000});

Save your work and behold.

Motion

This is looking good, but it’s not moving or anything. Let’s add some action by making the cone move.

/**
 * Rotate the cone if any key is held down.
 * rotate() should be called in the animate() function.
 */
var key_is_down = false;
function rotate() {
    if ( key_is_down ) {
        cone.rotation.y += .1;
        cone.rotation.z += .1;
    }
}
document.addEventListener( 'keydown', function(){
    key_is_down = true;
});
document.addEventListener( 'keyup', function(){
    key_is_down = false;
});

Add a call to rotate() inside the animate() function.

Hold down any key on the keyboard and watch the cone spin around.

That concludes this quick overview. If you want to compare your code or are having problems here is the full source code.

A more complex example.

You can play around with this cool Mars Rover simulation I developed in three.js. It uses these concepts and a few other ones. Here is the source code.

Next steps

three.js is a powerful library, so this quick guide can’t cover all of the features. The official three.js documentation has the source code for many more examples. My recommendation would be to decide on a project that you want to do and learn the concepts as you are doing the project. Unless you already have experience writing software for 3D rendering there are going to be many concepts that you don’t even know you don’t know, so learning things when you get stuck is the best way of learning this library.