Hello World with Three.js

WebGL is a JavaScript API that allows us to create 3D graphics within the web browser, using the HTML <canvas> element. It is a low-level API, and can be challenging to use directly.

Three.js is a JavaScript library built on top of WebGL to make it simpler to use. It does an excellent job of abstracting away of a lot of the details of WebGL.

I’m going to walk through creating the simplest example of using three.js to render a 3 dimensional cube. To me, this is roughly the equivalent of a 3D Hello World app.

Let’s talk about some concepts used in three.js. First, we have a scene, a 3D world in which we place objects, lights, etc. This is where we’ll place our cube. We will also need a camera to create perspective, and give us a point from which to render the scene. A renderer is responsible for actually drawing our 3D world onto the flat surface of the canvas element.

Heres what that looks like in JavaScript:

In order to create an object, we need two things: a geometry and a material. We need a geometry to define the object’s shape. The geometry is composed of the vertices, or the points in space that define the corners of our object. The geometry gives us a skeleton or wireframe of our object.

In order to give our object some texture, we need a material. This defines what the surface of our object will look like. In this example, we will use three.js’ colorful Normal Material.

We apply the material to the geometry to create what’s called a mesh. This mesh is the virtual representation of our skinned object.

We render our scene in a function that’s known as the render loop. It is called once per frame, usually about 60 times per second. This is the function that draws our scene on the canvas and brings it to life.

A render loop

The requestAnimationFrame method asks the browser to call our render function when it’s ready to paint the next frame, thus creating a loop. Using requestAnimationFrame() is more efficient than calling render directly because it will only invoke our function when a new frame is ready to be drawn. If our browser tab is inactive, for example, we will not waste cycles rendering our scene.

The last step is to call our render() function to kick off the render loop.

And here it is in action:

You can find the complete code here.