April 9, 2020 • by Sergiusz & Dora

Introduction to 3D: Three.js basics

JS & Frameworks
Tech Staff

The complexity of the Web is changing daily, and its scope is growing just as fast, especially with 3D rendering.

 

WebGL is a JavaScript library for rendering 2D graphics and interactive 3D graphics within browsers. It is based on the architecture of the OpenGL. WebGL uses the GLSL shader language with C- syntax. WebGL uses HTML5 <canvas> element to get 3D graphics into the browser page.

 

Working with WebGL, and with shaders in particular, is a rather time-consuming. In the development process, you need to describe each point, line, face, and so on. To render all this, we need to write a rather bulky piece of code. To increase the speed of development, Three.js library was developed.

 

Three.js is a JavaScript library containing a set of predefined classes for creating and displaying interactive 3D graphics in WebGL.

 

Three.js for WebGL is the same as jQuery for JavaScript. The library offers declarative syntax, and relieves the headache associated with 3D in the browser.

 

Let’s look have a general overview of Three.js and see how to get started if you are new to the 3D world.

 

More about Three.js

 

Three.js library, as already mentioned, makes work with WebGL easier. When using Three.js, there is no need to write shaders (but the possibility remains), and it becomes possible to work with familiar concepts.

 

A large number of developers work on the library. The mastermind and developer is Ricardo Cobello, known under the creative pseudonym Mr.Doob.

 

Graphics modeling using Three.js can be compared with a film set, as we have the opportunity to manage concepts such as scene, light, camera, objects and their materials.

 

Three so-called pillars of the library include:

 

  • Scene – a kind of a platform where all the objects that we create are placed;
  • Camera – this is the “eye” that will be directed to the scene. The camera takes and displays objects that are located on the stage;
  • Renderer – a visualizer that allows you to display the scene captured by the camera.

 

Three.js offers several types of cameras:

 

  • Perspective Camera
  • Stereo Camera
  • Orthographic Camera
  • Cube Camera

 

The most common ones are the Perspective and Orthographic Camera.

 

Perspective Camera

 

This is the most common projection mode used to render a 3D scene.

 

The perspective camera is designed to simulate what the human eye sees. The camera perceives all objects in a perspective projection: the further the object is, the smaller it seems.

 

 

The perspective camera takes 4 parameters:

 

  • FOV of Field Of View – defines the angle that you can see around the center of the camera.
  • Aspect ratio – the proportion or ratio of the width to the height of the screen. With large values of the field of view, the apparent size of objects quickly decreases at a distance. For small values, on the contrary, the apparent size of objects barely depends on distance.
  • Near & Far – minimum and maximum distance from the camera that gets into rendering. Thus, very distant points will not be rendered at all, as well as points that are very close.

 

 

Orthographic Camera

 

In this projection mode, the size of the object remains constant, regardless of its distance from the camera. That is, it is a camera remote to an infinite distance from objects.

 

In this case, all perpendicular lines remain perpendicular, all parallel remain parallel. If we move the camera, the lines and objects will not be distorted.

 

This can be useful when displaying 2D scenes and UI elements.

 

 

Light

 

Without light on the stage, it seems we are in a dark room, as only silhouettes are visible. In addition, by lighting the stage we add more realism. Technically, each light can be colored.

 

Types of Light:

 

  • Ambient light – background lighting that is used to illuminate all objects on the scene equally; cannot be used to create shadows, as it has no direction.
  • Directional light gets emitted in a specific direction. This light will behave as though it is infinitely far away and the rays produced from it are all parallel. It can cast shadows, as it is directed at a specific object.
  • Point light is emitted from a single point in all directions. A common use for this is to repeat light emitted from a simple light bulb.
  • Spot light is emitted from one point in one direction, along a cone, expanding as you move away from the light source.

 

 

Creating objects

 

The object created on the scene is called Mesh. A Mesh is a class that presents objects made up of a triangular polygons.

 

Mesh is built using 2 objects:

 

  • Geometry – defines the object shape (position of vertices, faces, radius, etc.)
  • Material – defines object appearance (color, texture, transparency, etc.)

 

Let’s try to create 2 simple shapes: a cube and a sphere.

 

First of all, we go to threejs.org, and download the latest version of the library. Then we connect the library in the head section or in the beginning of the body section of our document, and we’re done:

 

<html>
  <head>
    <meta charset=utf-8>
    <title>First Three.js app</title>
    <style>
      body { margin: 0; }
      canvas { width: 100%; height: 100% }
      </style>
  </head>
  <body>
    <script src="/js/three.js"></script>
    <script>
      // Javascript code here.
    </script>
  </body>
</html>

 

To be able to display our future object, first we need to create a scene, add a camera and set up a render.

 

Adding a scene:

 

var scene = new THREE.Scene();

 

Now we add perspective camera:

 

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

 

The camera takes on 4 parameters, which were mentioned above:

 

  • FOV or field of view, in our case it is a standard angle of 75;
  • the second parameter is the aspect ratio;
  • the last 2 parameters are the near and far clipping plane (the objects further away from the camera than the value of far or closer than near won’t be rendered)

 

Adding and setting up a renderer:

 

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

 

What do we have here: we created a renderer first, then set its size according to the visible area size, and finally add it to the page to create an empty canvas element we will work with.

 

To create the cube itself, first we define a geometry:

 

var geometry = new THREE.BoxGeometry( 10, 10, 10);

 

BoxGeometry class is used to create cuboids or boxes. This is a class that contains the vertices and faces of a cube. Here we have three variables set:

 

  • width: the length of the edges parallel to the X axis
  • height: the length of the edges parallel to the Y axis
  • depth: the length of the edges parallel to the Z axis

 

*All the variables default to 1

 

To color the cube, we need to set up a material:

 

var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );

 

In our case, we have MeshBacisMaterial and 0x00ff00 color attribute, i.e. green color. This material is basically used to make the object of a uniform color. The downside is that the object loses depth. But this material is quite useful when creating wireframe objects using the {wireframe:true} parameter.

Now we need a Mesh, that takes a geometry, and applies a material to it:

 

var cube = new THREE.Mesh( geometry, material );
scene.add( cube );

camera.position.z = 25;

 

We inserted Mesh to the scene and then moved the camera out a bit. That is needed to avoid the camera and the cube to be at the same point, since by default, when we call scene.add(), the figure will be added to the coordinates (0,0,0).

 

In order to animate the cube, we need to draw everything inside the render loop using requestAnimationFrame:

 

    function render() {
            requestAnimationFrame( render );
      cube.rotation.x += 0.01;
      cube.rotation.y += 0.01;      
      renderer.render( scene, camera );
    }
render();

 

requestAnimationFrame is a request to the browser that you wish to animate something. We pass a function to call, that is, the render ().

 

Here we also set the rotation speed parameters. As a result, the loop renders our scene 60 times per second and makes the cube to rotate.

So here is the result:

 

 

Let’s create a sphere

 

For a sphere, the SphereGeometry class is used, which takes the following parameters:

 

  • radius (default value is 1);
  • widthSegments – the number of horizontal segments (triangles). The minimum value is 3, the default value is 8;
  • heightSegments – the number of vertical segments. The minimum value is 2, the default value is 6.

 

var geometry = new THREE.SphereGeometry(1, 32, 32);

 

By the way, the higher is the number of segments or triangles, the smoother is the surface of the sphere.

 

Now let’s use another material – MeshNormalMaterial – a multicolor material that maps the normal vectors to RGB colors:

 

var material = new THREE.MeshNormalMaterial();
var sphere = new THREE.Mesh( geometry, material );
scene.add( sphere );
camera.position.z = 3;

 

Three.js provides about 15 types of material, some of them can be combined and applied simultaneously to one object. Read more here.

 

The last step is setting up the render loop:

 

function render() {
	requestAnimationFrame( render );
	sphere.rotation.x += 0.01;
  sphere.rotation.y += 0.01;
  renderer.render( scene, camera );
}
render();

 

And here is what we get:

 

 

An object of a bit more complex shape , and apply another material

 

As an example, we’ll take the MeshPhongMaterial, which is affected by light. Therefore, we need to add some light to the scene first. Below we add a SpotLight with a yellow tint and set its position on the coordinate axis:

 

var scene = new THREE.Scene();
var spotLight = new THREE.SpotLight(0xeeeece);
spotLight.position.set(1000, 1000, 1000);
scene.add(spotLight);
var spotLight2 = new THREE.SpotLight(0xffffff);
spotLight2.position.set( -200, -200, -200);
scene.add(spotLight2);

 

SpotLight, as mentioned above, gets emitted from a single point in one direction, along a cone that increases in size the further from the light it gets. In addition to color, spotlight can take the following parameters: intensity, distance, angle, penumbra, and decay. It also can cast shadows.

 

Now it’s time for a material:

 

var material = new THREE.MeshPhongMaterial( {
color: 0xdaa520,
specular: 0xbcbcbc,
 } );

 

This material is used for shiny surfaces. We passed a gold-ish color here, and added a specular property, which defines brightness and color of reflexion. The default color is 0x111111 which is dark gray.

 

Now we render it all and get the following:

 

 

A little bit more about Three.js

 

All you need to do to include Three.js into your project is run npm install three.

 

If you’re bundling your files with Webpack or Browserify, which allow you to “require(‘modules’)” in the browser by bundling up all of your dependencies, you are able to import the module into your source files and continue to use it as per normal.

 

var THREE = require('three');

var scene = new THREE.Scene();
...

 

You’re also able to leverage ES6 import syntax:

 

import * as THREE from 'three';

const scene = new THREE.Scene();
...

 

If you need, you can import only select parts of Three.js library, for example:

 

 

import { Scene } from 'three';

const scene = new Scene();
...

 

Conclusion

 

With the help of almost a couple of lines of code, we created 2 simple shapes, and one a bit more complicated. Naturally, Three.js has a lot more features. Three.js has a lot of out-the-box shapes, materials, types of lighting, etc. This is just a small part of the basics.

 

Three.js library allows you to create really great things. Here are some catchy examples:

 

Example 1
Example 2
Example 3

 

If you want to start learning 3D in JavaScript, you can find everything you need here.

Written by

Sergiusz

Software Engineer

Dora

Marketing Manager

FAVORITES OF THE MONTH

Don't miss our updates

    Exit mobile version