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.
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:
Three.js offers several types of cameras:
The most common ones are the Perspective and Orthographic 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:
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.
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:
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:
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:
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:
*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:
For a sphere, the SphereGeometry class is used, which takes the following parameters:
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:
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:
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(); ...
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:
If you want to start learning 3D in JavaScript, you can find everything you need here.