Introduction
If you imagine a film set, there's a guy pointing a camera at a scene of different props, and he can do so from different angles. It's all pretty similar in three.js, which is made up of objects that make coding 3D experiences much more natural to us. For example, three of the tools we have at our disposal when using three.js are below:
- Scene - this contains all the 3D object data (all the props)
- Camera - this has a field of view, position and rotation
- Renderer - this figures out what objects look like from the camera's point of view
Three.js simplifies WebGL, enabling us to use simple concepts such as those above to produce 3D experiences with minimal code. The same would have required hundreds of lines of JavaScript when using WebGL directly.
In this tutorial, we'll be setting up the three.js environment in step 1, then using the Scene, Camera and Renderer objects listed above, getting an understanding of each in step 2. In the final step 3, we'll add an animating cube to the scene we've created.
The Outcome
Here's what we'll end up with - if you just want the code you can grab it from the codepen below or github. Otherwise, to learn about what's going on, continue reading from step 1.
Step 1: Download three.js & setup the HTML project
Download three.js
First, get a copy of three.js from its GitHub repository, and save it locally.
The reason I'm storing this locally is to prevent the applicaiton breaking if a different release of three.js is used. The latest version at the time of this tutorial was revision 71, so you should use r71 if you're having any issues.
Apart from three.js, we're just going to be coding everything else within a single HTML file for simplicity.
Create the HTML project file
All we're doing below is including our local three.js library, and opening some script tags where most of the code will go.
<!doctype html> <html lang="en"> <head> <title>Three.js Tutorial</title> <meta charset="utf-8"> </head> <body> <script src="three.js"></script> <script> //code will go here... </script> </body> </html>
Step 2: Create a Scene, Camera and Renderer
Now, we'll declare 3 global variables, and assign each of them with a three.js object. First we'll create a Scene, then add a Camera, followed by the Renderer.
Create the Scene
The scene is really simple:
//declare scene variable var scene; //create the scene scene = new THREE.Scene();
Add the Camera
To add the camera, we assign a PerspectiveCamera object to a camera variable. There's a few different other camera options, but we'll use the PerspectiveCamera above:
//declare camera variable var camera; //assign three.js perspective camera to variable camera = new THREE.PerspectiveCamera(75, window.innerWidth/ window.innerHeight, 0.1, 1000);
Let's step through the arguments provided to the PerspectiveCamera:
- The first argument we have provided,
75
, is the field of view for the camera. - Second,
window.innerWidth/ window.innerHeight
is the aspect ratio. - The final two arguments are the clipping plane for far and near.
Add the Renderer
For rendering, we'll use the WebGLRenderer object, which will display our scene using WebGL. Alternatively, canvasRenderer() could have been used, which uses the canvas element - it's a good fallback for when WebGL is not available.
//declare renderer variable var renderer; //assign WebGL renderer object renderer = new THREE.WebGLRenderer(); //set the size of the renderer renderer.setSize( window.innerWidth, window.innerHeight ); //add the renderer to the html document body element document.body.appendChild( renderer.domElement );
Bring it all together
You can then combine all of the above code into something more manageable as seen in the snippet below. The variables are declared globally, and then we have an init()
function, which we call at the bottom to build our scene.
//Declare three.js variables var camera, scene, renderer; //assign three.js objects to each variable function init(){ //camera camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); //scene scene = new THREE.Scene(); //renderer renderer = new THREE.WebGLRenderer(); //set the size of the renderer renderer.setSize( window.innerWidth, window.innerHeight ); //add the renderer to the html document body document.body.appendChild( renderer.domElement ); }
At this point, you still won't actually see anything if you run the code as there's nothing on the scene, and it isn't actually rendered. So let's fix that in the next step:
Step 3: Rendering a cube onto the scene
In this step, we'll first create a cube and add it to our scene, and then create a rendering loop which will run our scene.
Create the Cube
First, we declare the cube variable globally, so it can be used in other methods if necessary, then create the cube within an addCube
function. To do this, we use BoxGeometry
to create a geometry object, then create some material with a colour, and then Mesh
them together to create to cube. After we add the cube to the scene, we have to set the camera position so that the cube becomes visible.
If that sounded complicated, it's actually really simple if you look at it line by line:
var cube; function addCube(){ //create box geometry object var geometry = new THREE.BoxGeometry( 1, 1, 1 ); //create material with colour var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } ); //combine geometry with material to create the cube cube = new THREE.Mesh( geometry, material ); //add the cube to the scene scene.add( cube ); //set the camera position camera.position.z = 5; }
Render the scene
Here, we define a render()
function, which basically acts as a loop, firing 60 times a second:
function render() { //get the frame requestAnimationFrame( render ); //render the scene renderer.render( scene, camera ); }
Now to run all of this, just add the following to the bottom of your script:
init(); addCube(); render();
Animate the cube
To demonstrate how this render loop is actually working, we can animate the cube just by adding a couple lines within the render function:
function render() { //get the frame requestAnimationFrame( render ); //animate the cube cube.rotation.x += 0.1; cube.rotation.y += 0.1; //render the scene renderer.render( scene, camera ); }
Because the render function acts in a loop, it adds 0.1 to the x and y rotations of the cube 60 times a second, creating a rotating animation.
Well done
Good work, you've learned some of the very basics of three.js. I'll be adding a new tutorial to further manipulate the cube in the future.