3D Rendering Using Three.js

A step-by-step guide to rotating a 3D cube with three.js and a challenge for the reader.
Vihar Kurama
July 11, 2021
Updated: July 13, 2021
Vihar Kurama
July 11, 2021
Updated: July 13, 2021

3D graphics programming is useful in a wide variety of applications, including elucidating a topic through 3D diagrams, designing games, AR, VR, and many others. To embed 3D graphics in a webpage, however, we need some sort of specialised programming. For this, we can use WebGL, which lets you access the computer’s graphics hardware — including the GPU — using JavaScript.

WebGL isn’t a magic wand, though. While it’s good with simple 3D objects like lines and points, we don’t generally deal with such uncomplicated structures in the real world. In dealing with more complex objects, WebGL encompasses big code chunks. To accomplish our goals with fewer lines of code, we turn to three.js, which is a JavaScript library that helps in getting 3D content on a webpage. In this piece, we’ll look at an example of how to use three.js in rendering 3D objects, and then I’ll present you with a challenge to work through on your own. One note before we begin: three.js internally uses a WebGL renderer by exposing a simple API.

 

A Simple Example: Rotating a Cube

Let’s start off by creating a repository named animations_threejs. Next, go to the repository, and create another repository named js to store all the js files.

We need to import three.js code into the js repository to make use of all the API calls that it provides. To do that, we include the three.js library code in a file and import it in the html file. Create a file named three.js and copy the code from this link.

In the animations_threejs repository, create a file named rotatecube.html. This is what the repository structure looks like:

 animations_threejs/

├── js

│   └── three.js

└── rotatecube.html

Let’s now write the rotatecube.html file by coding our application to rotate a cube.

Step 1 - Creating the HTML template

 <!DOCTYPE html>

<html>

      <head>

            <title>Rotating a Cube</title>

      </head>

      <body>

            <script src="js/three.js"></script>

            <script>

                  ...

            </script>

      </body>

</html>

This is the basic HTML template. Now, we write all our code in the <script> tag.

Step 2 - Initiating the objects

 var camera, scene, renderer, geometry, material, mesh;

init();

animate();

function init() {

    scene = new THREE.Scene();

        camera = new THREE.PerspectiveCamera(50, window.innerWidth /
        window.innerHeight, 1, 10000);

    camera.position.z = 500;

    scene.add(camera);

    geometry = new THREE.CubeGeometry(200, 200, 200);

    material = new THREE.MeshNormalMaterial();


    mesh = new THREE.Mesh(geometry, material);

    scene.add(mesh);

    renderer = new THREE.WebGLRenderer();

    renderer.setSize(window.innerWidth, window.innerHeight);

    document.body.appendChild(renderer.domElement);

}

The first line describes the various objects that we use in this application.

In the next two lines, we describe two functions (init() and animate()) that are defined below.

In the function init(), we create a scene first, and then define the camera that we would be using, which is perspective camera in this case. The first attribute is the field of view, that is, the extent of the scene that’s seen on the display. The second attribute is the aspect ratio, which is width divided by height. The third and fourth attributes denote the near and far clipping plane. These planes set the bounds of the objects which are rendered: objects that are farther than the value of the far plane or nearer than the value of the near plane aren’t rendered.

The next line defines the camera position that’s projected to be 500 points above the origin. We then add the camera to the scene defined above.

The object to be displayed is a cube, which we import using CubeGeometry. This object has all the vertices and faces of the cube.

MeshNormalMaterial colors the cube. Many materials are available, but for now we’ll use this one, wherein the normal vectors are mapped to RGB colors. This will produce the multi-color display that we’ll eventually see.

A Mesh applies material to the geometry.

We then insert this object in our scene at the coordinates (0,0,0). As a result, the camera is shifted to get a better view of the cube. Thereafter, a renderer forms the bedrock to display the cube in action. The innerWidth and innerHeight are the dimensions of the browser window on which we want to render our app. We then add the renderer to our HTML document, which is a <canvas> element.

Step 3 - Animate

 function animate() {

    requestAnimationFrame(animate);

    render();

}

This function draws the scene whenever the screen is refreshed. The requestAnimationFrame stops the animation as soon as the user moves onto a new tab or window.

The render() function is called repetitively.

Step 4 - Render

 function render() {

    mesh.rotation.x += 0.01;

    mesh.rotation.y += 0.02;

    renderer.render(scene, camera);

}

Mesh.rotation.x and mesh.rotation.y give an animation effect to the cube.

In the next line, the render() function takes in scene and camera as arguments to render on the browser window.

Step 5 - Run

The whole code looks like this:

 <!DOCTYPE html>

<html>

    <head>

        <title>Rotating a Cube</title>

    </head>

    <body>

        <script src="js/three.js"></script>

        <script>

            var camera, scene, renderer, geometry, material, mesh;

            init();

            animate();

            function init() {

                scene = new THREE.Scene();

                camera = new THREE.PerspectiveCamera(50,
                window.innerWidth / window.innerHeight, 1, 10000);

                camera.position.z = 500;

                scene.add(camera);

                geometry = new THREE.CubeGeometry(200, 200, 200);

                material = new THREE.MeshNormalMaterial();

                mesh = new THREE.Mesh(geometry, material);

                scene.add(mesh);

                renderer = new THREE.WebGLRenderer();

                renderer.setSize(window.innerWidth, window.innerHeight);

                document.body.appendChild(renderer.domElement);

            }

            function animate() {

                requestAnimationFrame(animate);

                render();

            }

            function render() {

                mesh.rotation.x += 0.01;

                mesh.rotation.y += 0.02;

                renderer.render(scene, camera);

            }

        </script>

    </body>

</html> 

To play the animation that we just coded, open the html file in a browser, and there it is: our multi-colored, rotating cube. It looks amazing, right? Congratulations! You’ve coded your first 3D application using three.js. Now, let’s try something more complicated.

 

A Complex Example: Fanning the Lion

Now that we’ve gone over some of the basics in using three.js, I’m going to give you a project to help you expand your skills by creating a complex animation. First, take a look at the code here. The JS code is the one which we need to focus on.

All the objects are designed and created, after which the animation loop and render functions are defined. There are a good many functions present to define the physics of this animation.

To help get you started, here’s what the repository structure should look like:

 animations_threejs/

├── fanthelion.html

├── js

│   ├── OrbitControls.js

│   └── three.js

└── rotatecube.html

Now, for practice, try executing this on your machine by putting all the chunks in the right sections of your HTML template, then peruse the code, and seek to fully understand what’s going on. Once you do, you can fan the lion!

Expert Contributors

Built In’s expert contributor network publishes thoughtful, solutions-oriented stories written by innovative tech professionals. It is the tech industry’s definitive destination for sharing compelling, first-person accounts of problem-solving on the road to innovation.

Learn More

Great Companies Need Great People. That's Where We Come In.

Recruit With Us