News

Create amazing HTML5 3D effects pt2

Part two of this feature takes the practical approach and reveals how to create a 3D scene with WebGL and the three.js library

HTML5Logo

CREATE A 3D EARTH SCENE

While WebGL itself is pretty inaccessible for novice users, by using a specialist library that abstracts a lot of the complexity it’s possible to very quickly generate a 3D scene that’s rendered by WebGL!

In this tutorial we’re going to create a pseudo space scene. We’ll use a bit of smoke and mirrors to generate the final piece, but the final result will be an impressive animation that features the earth rotating about its axis and a randomly generated star field. Once you’ve completed working through the steps below, you’ll have a good sense of how to create your own 3D scene and populate it with objects, apply textures, and create simple animations.

Download three.js

To make it much easier to get started with WebGL, we’re going to use the excellent three.js library. This abstracts a lot of the complexity associated with the WebGL API, and makes a light and simple task out of assigning renderers, shaders, cameras and objects to our 3D world. Download the library from github.com/mrdoob/three.js

Create a simple page

We only need the most basic of HTML pages to test our effect, so create that now. You’ll want to include the three.js library you downloaded in step one, and a smattering of CSS to define the size of your canvas element.

001 < !DOCTYPE html>
002 < html lang=”en”>
003 < head>
004 < meta charset=”UTF-8” />
005 < title>Create a 3D scene with WebGL and Three.js
006 < script type=”text/javascript” src=”scripts/jquery.js”>
007 < script type=”text/javascript” src=”scripts/three.min.js”> 
008 < style type=”text/css”>
009 body {
010 background-color: #000000;
011 margin: 0px;
012 overflow: hidden;
013 }
014
015 #scene {
016 width: 100%;
017 height: 100%;
018 position: relative;
019 margin: auto;
020 }
021 < /style>
022 < script>
023
024< /script>
025
026 < body>
027 < div id=”scene”>
028
029 < /div>
030
031< /html>

The basics

To create a 3D scene using WebGL you need at minimum a scene, a camera and something to put in the scene – an item of some sort. We’ll start by defining our basic properties and objects to be used in our scene. Add the code shown below to generate the basic scene dimensions variables.

 001 // set the scene size
002 var sWIDTH = 800,
003   sHEIGHT = 600;

Camera properties

As well as a scene, we’re going to need a camera through which we can view the scene. A camera has a number of properties that we need to set – including a field of view (how much of a scene the camera can see), the focal distance, and the aspect ratio (such as 16:9, 4:3 etc). Add the code below to set variables up for these properties:

 001 var cVIEW_ANGLE = 45,
002  cASPECT = sWIDTH / sHEIGHT,
003  cNEAR = 0.1,
004  cFAR = 10000;

Create the renderer

As we’ve already discussed, to create a 3D scene we need a renderer to draw the scene onto the screen. Let’s set that up now. Three.js supports multiple different renderers including the standard Canvas API, but we’re going to use WebGL to draw our scene. Add the code below to create the renderer:

001 var renderer = new THREE.WebGLRenderer();

Create the camera

Now we’ve got our renderer set up using the three.js library, let’s set up the camera ready to view our scene! We’ve already set up all the properties earlier on, so all we need to do is add in a call to the perspectiveCamera method to generate our camera:

 001 var camera =
002  new THREE.PerspectiveCamera(
003    cVIEW_ANGLE,
004    cASPECT,
005    cNEAR,
006    cFAR);

Make a scene!

Now we’ve got both a renderer and a camera, we’re ready to generate a scene that will hold our elements and appear on our page! In vanilla WebGL this is a bit of an undertaking, but with three.js it’s as simple as writing a single line of code:

001 var scene = new THREE.Scene();

Set it running!

We’re now ready to set our scene rendering out to screen. We start by setting the camera position, then the width and height of the renderer, and finally appending the resulting element to our page DOM using jQuery, before using the renderer to draw the scene. Make sure you’ve grabbed the jQuery library from jquery.com before testing the following code in your browser!

001 // set the default position for the camera
002 camera.position.z = 300;
003
004 // start the renderer
005 renderer.setSize(sWIDTH, sHEIGHT);
006
007 // attach the render-supplied DOM element to the page
008 $(“#scene”).append(renderer.domElement);
009 renderer.render(scene, camera);

Test nothing

If you test your page at this stage, you’ll see that although there aren’t any errors thrown up, there’s also nothing displayed. This is because while we’ve successfully created a scene and camera, we haven’t actually placed anything inside our scene yet – so there’s nothing to draw! We’ll fix that next…

Add a primitive

In three.js there are a series of primitive shapes you can add to your scene as basic building blocks for your items. We’re going to use the sphere primitive to create the earth, but we need to start off by defining how big we’d like the sphere to be. As everything in 3D is split into flat segments, we’ll also define how many segments to break our sphere into.

001 var earthRadius = 50,
002    earthSegments = 16,
003    earthRings = 16;

Generate the mesh

Now we’ve got our variables defined we can create the shape using the Mesh() method within three.js. A Mesh is a way of describing simple geometry. Add the code below to generate your mesh sphere, passing in the variables we just defined as arguments to define the properties of the sphere.

001 var earth = new THREE.Mesh(
002
003  new THREE.SphereGeometry(
004    earthRadius,
005    earthSegments,
006    earthRings),
007
008 earthMaterial);

Add a material

You’ll have noticed we added a final argument to the Mesh object call that referenced a variable we haven’t set up yet – earthMaterial. This will define the texture that we wrap around our sphere to make it look like the planet earth rather than a ball. We’ll define the material now by applying an image we downloaded from the web as a texture:

001 var texture = THREE.ImageUtils.loadTexture( “images/earth_clouds.jpg” );
002 var earthMaterial =
003  new THREE. MeshBasicMaterial( { 004map:texture } ));
005
006 scene.add(earth);

Add light to your scene

< img class="alignnone size-full wp-image-15152" title="step13" src="https://www.gadgetdaily.xyz/wp-content/uploads/2013/04/step13.jpg" alt="" height="400" width="608" />

To help our scene render we need to illuminate it with a light – otherwise we’ll be looking in the dark! Lights work much like cameras in that they take a set of co-ordinates, but they also have a colour setting. We’re going to set ours to give off white light:

001 // add lighting
002 var light = new THREE.DirectionalLight(0xFFFFFF);
003 light.position.x = 150;
004 light.position.y = 250;
005 light.position.z = 150;
006 scene.add(light);

Create an animation

So far our earth is looking pretty good but it’s sitting in our scene without any movement. To get the earth moving, we need to set it up to rotate about the Y axis. We’ll create a simple animation function that rotates the earth a small amount each time the function is called:

001 function animate() {
002 earth.rotation.y += -0.0025;
003 renderer.render(scene, camera);
004 }

Call the animation

We could use the time-honoured setInterval method to call our animation function every X milliseconds, but that continues to use computer resources even when the tab isn’t active in the browser, leading to uneccessary processor and battery use. Instead we’ll use the requestAnimationFrame method which doesn’t suffer the same issues. Add the code below inside the animate() function:

001 requestAnimationFrame(animate);

Start it off

The final missing piece is to kick-start our animation by calling the animate() function from the main scene setup code. Once it’s been called once, the animate function will continue to be called as a result of the code we added in the previous step. Add a simple call to the function beneath all the existing code:

001 animate();

Reach for the stars!

Our earth is now rotating beautifully about its axis, but we can do more to make our scene look like space – let’s add some stars! We’ll start off by creating a simple particle system that will contain all of our stars’ co-ordinates. Add the code below to generate a random set of co-ordinates for 500 stars:

001 for (var i=0;i<500;i++){
002 var star = new…; // Create mesh object
003 star.position.x = (Math.random()*sWIDTH-(sWIDTH/2));
004 star.position.y = (Math.random()*sHEIGHT-(sHEIGHT/2));
005 }

Add the stars

Now we’ve got our co-ordinates, we need to create them and add each to the scene. This is simply a case of copying our earlier code, and making sure we call the appropriate three.js object in each case to generate the star for each instance. We’re also positioning each in Z space so that it sits behind the earth:

001 for (var i=0;i<500;i++){
002 var star = new THREE.Mesh(new THREE.SphereGeometry(1,1,1),new THREE. MeshLambertMaterial({color: 0xFFFFFF}));
003 star.position.x = (Math.random()*sWIDTH-(sWIDTH/2));
004 star.position.y = (Math.random()*sHEIGHT-(sHEIGHT/2));
005 star.position.z = 0;
006 scene.add( star );
007}

Test and review

Our code is now complete, so fire up your browser for one final test and make sure everything is working as it should. You should see a random pattern of stars spread over the canvas, and these will change each time you refresh the page!

×