Getting started with three.js

Total
0
Shares
threejs - installation creating a scene

In this article I am going to show you how you can get started with three.js. We will look at installation, creating a scene and loading a 3d model. You will learn everything from code example and live demo.

Introduction to three.js

three.js is a javascript library which is used for handling the 3d stuff. This includes creating a game, movie, cartoons, anime etc.

Why library is called three.js?

Because all the 3d stuff is done by 3 things – Scene, Camera and Renderer. This library is named after these 3 things.

  • Scene – A scene is the complete area in 3d which holds all the objects in it. For example, a castle, trees, mountains, king, ironman, light source etc.
  • Camera – Out of a big 360 degree 3d scene the portion which you want to show on the screen is decided by camera. So, you can have multiple cameras in a scene to display different locations and objects based on some conditions like moving forward, teleportation, inside house etc.
  • Renderer – Renderer helps in rendering the scene and camera. For any movable picture like videos, games, animations there is need to render still images at the rate at which our eyes makes the perception of movement. So, a walking horse is actually a series of still images of different walking positions of horse. When they are rendered at the rate greater than 24 per second, our eyes could not distinguish them as still images. The renderer renders at 60 refresh rate which is know as FPS (Frame per second).

Installation

You can install the library either from Npm or using CDN.

Using Npm

npm install --save three

Now you can import the library in your project –

import * as THREE from 'three';

const scene = new THREE.Scene();

Or, you can import the specific component like this –

import { Scene } from 'three';

const scene = new Scene();

Using CDN

<script type="module">

  import * as THREE from 'https://cdn.skypack.dev/three';

  const scene = new THREE.Scene();

</script>
<script src="https://threejs.org/build/three.js"></script>

Creating a Scene

Our 3d project comprises of scene, camera and renderer. In this section, we will look at the scene. A scene will hold objects like cube, trees, house etc. Here we will create a scene and add a cube in it.

To initialize a scene –

const scene = new THREE.Scene();

Now, let’s create a cube. But first understand what cube is and how it get’s its shape. Every object has a geometry and a material.

  • Geometry – It defines the structure of an object. So cube is a figure with 8 vertices, 12 lines and 6 faces. This is the geometry of the cube.
  • Material – Material includes all the properties related to its look and feel like color, texture, gloss, shine etc.

So, for our cube we will need to define the geometry as well as material –

const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
const cube = new THREE.Mesh( geometry, material );

Here we have used the BoxGeometry which creates box. You can define the size and other properties but we are going with default. Second, we have created a MeshBasicMaterial which holds few parameters but we are okay with solid red color. In the next step, we combined the geometry and material together to make our cube.

We just created a cube which is isolated. It means there is no location of cube anywhere. We need to add it to our scene. In fact we need to add everything to our scene at desired locations. So, you can choose any co-ordinate to add. By default, it will add at (0,0,0).

scene.add( cube );

Now we need a camera to look at a portion of scene. Next section will deal with that.

Creating a camera

A camera works like an eye. You can’t see anything without an eye. So, we add cameras to our scene. There are different types of cameras but for this article, we are interested in perspective camera.

const camera = new THREE.PerspectiveCamera( fov, aspect_ratio, near_clip, far_clip);

The PerspectiveCamera function has 4 parameters –

  • fov – fov stands for field of view. It represents the degree of view.
  • aspect ratio – The width over height ratio of the image. It could be 16/9 or 4/3 but on webpage you will preferably go for window.innerWidth / window.innerHeight.
  • near clip – We need to limit our camera of how far and how near it can see. Therefore, we give a value to near clip which only show the object or part of objects greater than the distance provided here. If an ant is too near to camera then it will cover the whole camera view. To prevent it, we need a near clip value.
  • far clip – Similar to near clip, there is limitations to how far a camera can see. It will neglect the part of scene which is farther from the provided value.

Let’s put some values in our camera function –

const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );

The position of our camera will be at (0,0,0), same as our cube in the scene. So, they will overlap. To prevent this, we need to either move the camera or cube. Let’s move the camera –

camera.position.z = 5

Till here, our code will look like this –

<script src="https://threejs.org/build/three.js"></script>
<script type="module">

  const scene = new THREE.Scene();

  const geometry = new THREE.BoxGeometry();
  const material = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
  const cube = new THREE.Mesh( geometry, material );

  scene.add( cube );

  const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
  camera.position.z = 5;

</script>

Let’s work on our last part, the renderer.

Creating a renderer

Rendering is a 2 step process where the first step is to create a renderer and second step is to run a loop to rerender the scene at 60 fps.

Create render component

Let’s first create the render component –

const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );

Few things to note here – We are using WebGLRenderer which is the preferred renderer. Although there are several other types but this is the recommended one and all the modern browsers supports it.

In second step, we are setting the size of renderer. This is basically the size of canvas html component which three.js will create for us.

In third step, we are appending the canvas node to the html document. That’s it.

Animate renderer

Our renderer should repaint the scene at a frame rate of about 60 fps otherwise we won’t be able to see animations. For example, suppose the cube is rotating in x and y direction then it is needed to repaint the scene with new positions of cube at 60 fps. This will give us the perception of rotating cube.

You can run a setInterval() loop to run renderer.render() function at an interval of 1000 / 60. But three.js provides a better alternative requestAnimationFrame(). It’s better because it enhances performance. Suppose, you moved to another browser tab or window then the animation will stop and save CPU cycles while setInterval() keeps on running.

Also, the animation loop holds all the computations in the scene like rotating cube, moving boat, water waves, flowing clouds, flying birds, smoke, rolling eyes etc. Sometimes the things are so many that it gets hard to do all the work in 1000 / 60 seconds i.e. ~16ms. So, the frames are dropped to complete the animation. With setInterval() function will run always at 16ms and the thread may block. With requestAnimationFrame() it will take care of frame drops automatically.

Code for animation loop –

const animate = function () {
  requestAnimationFrame( animate );

  renderer.render( scene, camera );
};

animate();

This animate function has 2 important steps –

  1. Rerendering the scene and camera using renderer.render(scene, camera).
  2. Calling the animate function at appropriate frame rate using requestAnimationFrame(animate).

If you want to render any changes, you will need to do that in this function. So, suppose you want the cubes to rotate infinitely, then you may do something like this –

const animate = function () {
  requestAnimationFrame( animate );

  cube.rotation.x += 0.01;
  cube.rotation.y += 0.01;

  renderer.render( scene, camera );
};

animate();

With every frame, the cube angle in x and y position will increase by 0.01. So with fps of 60, the cube will be rotated in x and y direction by 0.60.

This is the end of the basics of library. Our whole code will look like this –

<script src="https://threejs.org/build/three.js"></script>
<script type="module">

  const scene = new THREE.Scene();

  const geometry = new THREE.BoxGeometry();
  const material = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
  const cube = new THREE.Mesh( geometry, material );

  scene.add( cube );

  const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
  camera.position.z = 5;

  const renderer = new THREE.WebGLRenderer();
  renderer.setSize( window.innerWidth, window.innerHeight );
  document.body.appendChild( renderer.domElement );

  const animate = function () {
    requestAnimationFrame( animate );

    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;

    renderer.render( scene, camera );
  };

  animate();
</script>

Live Demo

Open Live Demo

Loading 3d Models

There are a number of software which can create 3d models like sketchup, Blender, 3ds Max, Maya, Cinema 4D, Houdini, Toolbag etc. You can use any of these to generate files in formats like .obj, .dae, .fbx, .glTF etc.

In this article, we will deal with the glTF engine. This format is now more universally acceptable in web libraries as well as game engines like Unity 3d.

You can also download open source and creative common 3d models from websites like Sketchfab.

First load the GLTFLoader.js file –

<script src="https://threejs.org/examples/jsm/loaders/GLTFLoader.js"></script>

Now the next step is to load the model and add it to the scene –

const loader = new GLTFLoader();

loader.load( 'path/to/model.glb', function ( gltf ) {

	scene.add( gltf.scene );

}, undefined, function ( error ) {

	console.error( error );

} );

    Tweet this to help others