Building 3D in the browser with Three.js

We have capabilities in our browsers that we wouldn’t have dreamt of 5 or 10 years ago. Entire 3D game worlds can run in the browser and interactive websites can be more immersive experiences.

With a certain virtual reality company being purchased by a certain social media company, now is the perfect time to start working with 3D. Amazingly, we can now create 3D with pure JavaScript, including meshes and materials.

Of course, even though it’s possible, it does require a huge amount of code, and that’s where Three.js comes in, allowing us to build 3D environments simply and with less code.


Browser compatibility

Unfortunately, because it’s new, 3D isn’t supported by all browsers. We’re currently restricted to Chrome, Safari and Firefox.

As time goes by, support on IE will improve, but for now you’ll need a fallback for Microsoft devotees.


Getting started

The first thing we need to do is head over to the three.js website and download the latest version of the library.

Next, reference it in the head of your document like you would any other JavaScript file, and we’re ready to go.


Creating our first scene

The first thing we need to do, to render anything with three.js is to create a scene, a camera, and a renderer. Starting with a scene:

var scene = new THREE.Scene();

Next, we need a camera. Think of this as the point of view that the user is looking from. Three.js actually has a lot of options here, but for simplicity’s sake we’re going to use a perspective camera:

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

This method takes four parameters: the first is the field of view, the second is the aspect ratio (I’d recommend always basing this on the user’s viewport), the near clipping plane, and lastly the far clipping plane. These last two parameters determine the limits of rendering, so that objects that are too close or too far away aren’t drawn, which would waste resources.

Next up, we need to set up the WebGL Renderer:

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

As you can see, the first thing here is to create an instance of the renderer, then set its size to the user’s viewport, finally we add it to the page to create a blank canvas for us to work with.


Adding some objects

So far, all we’ve done is set up the stage, now we’ve going to create our first 3D object.

For this tutorial it’s going to be a simple cylinder:

var geometry = new THREE.CylinderGeometry( 5, 5, 20, 32 );

This method also takes 4 parameters: the first is the radius of the top of the cylinder, the second is the radius of the bottom of the cylinder, the third is the height, the last is the number of height segments.

We’ve set up the mathematics of the object, now we need to wrap it in a material so that it actually looks like something on screen:

var material = new THREE.MeshBasicMaterial( { color: 0x0000ff, wireframe: true} );

This code adds a simple material for the object, in this case a blue color. I’ve set wireframe to true because it will show the object more clearly once we get to animating it.

Finally, we need to add our cylinder to our scene, like so:

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

The last thing to do before we render the scene is to set the camera position:

camera.position.z = 20;

As you can see, the JavaScript involved is extremely simple, that’s because Three.js is dealing with all the complicated stuff, so we don’t have to.


Rendering the scene

If you test the file in a browser now you’ll see that nothing is happening. That’s because we haven’t told the scene to render. To render the scene we need the following code:

function render() {
  renderer.render(scene, camera);

If you now take a look at the file in your browser you’ll see it does indeed render a cylinder, but it’s not very exciting.

To really enhance the value of 3D you need to start animating, which we can do with a couple of small changes to our render function:

function render() {
        cylinder.rotation.z += 0.01;
        cylinder.rotation.y += 0.1;
  renderer.render(scene, camera);

If you test in your browser now you’ll see a properly animating 3D cylinder.



If you want to see a demo and play around with the code you can do so here.

As you can see, creating this (admittedly very simple) scene took less than two dozen lines of code, and there’s very little math involved.

If you check out the examples on the three.js website you’ll see some incredible work that has been done.

This amazing library for JavaScript has really lowered the entry-level for coding 3D to the point that anyone who can write basic JavaScript can get involved.

Featured image/thumbnail, 3D image via Shutterstock.

  • Andre Darafarin

    Cool tutorial! Can you please extend the browser compatibility list with mobile browsers? Thank you

  • TestShoot

    “Chomp” in VRML by Mondo Media back in 1997 was a lot of fun for the time. It was you playing as a shark, swimming around eating people and ducks. It was built with help from Silicon Graphics just as they rebranded as “SGI”.

  • Nodws

    why go to all that trouble to conceal the demo?

    post screens on your articles, not everyone can compile and interpret code to image in our minds

    • Energy Mud

      there wouldn’t be anything to see until you render it anyways

      • Nodws
      • Energy Mud

        I’m positive. How would she have screenshots of anything up until “Rendering the scene”? There would be nothing but a black screen. And anyways, what’s so difficult about parsing 15 or so lines of code? Get with it man.

      • Nodws

        screenshots/demo of the final render, not of code being typed pretty damn obvious.

  • Louis

    looks great fun, would love to have a crack at a 3d game in the browser.

  • Byron Houwens

    Really excited about using 3D in the browser, and Threejs makes things waaay easier! Now just to get it adopted by other browsers. It’s also good to note that WebGL takes advantage of your machine’s physical hardware, the same way desktop apps and games do, so the stronger your machine is the better performance you’ll get in WebGL environments.

    So to use this kind of technology we have to not only check a user’s browser but also their hardware capabilities (a laptop might not be able to render complex scenes as well as a dedicated desktop machine).

  • pixelbeat

    The pen has an annoying alert dialog that says:

    “This website abuses You should complain to its owner.”

    So, the example doesn’t work. You should use CDNJS and don’t have to link to directly to rawgithub ;)

  • P

    Your demo seems to run fine on IE 11…

  • Widy Graycloud

    Great tut but where’s the screenshot? a picture desctibe thousand of word
    if you make tutorial you must make readers to do your tutorial.

  • Bruce Sherwood offers 3D WebGL programming even simpler than threejs. Here’s a program roughly equivalent to the posted program:

    var cyl = cylinder( {pos:vec(0,-10,0), size:vec(20,5,5),
    axis:vec(0,1,0), texture:textures.metal} )
    while (true) {
    rate(50,wait) // no more than 50 iterations per second
    cyl.rotate( {angle:0.01, axis:vec(0,0,1), origin:vec(0,0,0)} )
    cyl.rotate( {angle:0.1, axis:vec(0,1,0), origin:vec(0,0,0)} )

    This works because there are lots of intelligent defaults (lighting, camera position, ctrl-drag to rotate and alt-drag to zoom). Note that you can write synchronous code, though you can also write callback code. There is operator overloading so that you can for example add two vectors A and B as A+B. You can choose to write in CoffeeScript instead of JavaScript.

    The rotationa behavior of this GlowScript program is different from the threejs behavior; I’m guessing there’s some difference in the semantics of the rotation statements.

  • Themesrefinery

    Great Article now its easy to work with 3d. Its fun to be young 3D game worlds can run in our browsers. plzzzzz extend the browser compatibility list.
    thanks for sharing..
    Rehman ali

  • Lx

    Hellow! How can I create rules of texture mapping for my own geometry:

    function lxRingGeometry(r, width, height, angle, sectors) {

    var step = angle / sectors;

    var innerR = r – width;

    var vertices = [];

    for (var i=0; i<sectors+1; i++) {

    vertices.push( new THREE.Vector3(innerR * Math.cos(i * step), height/2, innerR * Math.sin(i * step)) );

    vertices.push( new THREE.Vector3(innerR * Math.cos(i * step), -height/2, innerR * Math.sin(i * step)) );

    vertices.push( new THREE.Vector3(r * Math.cos(i * step), height/2, r * Math.sin(i * step)) );

    vertices.push( new THREE.Vector3(r * Math.cos(i * step), -height/2, r * Math.sin(i * step)) );


    var faces = [];

    for (var i=0; i<sectors*4; i+=4) {

    faces.push( new THREE.Face3(i, i+1, i+5) );

    faces.push( new THREE.Face3(i, i+5, i+4) );

    faces.push( new THREE.Face3(i+2, i+7, i+3) );

    faces.push( new THREE.Face3(i+2, i+6, i+7) );

    faces.push( new THREE.Face3(i, i+6, i+2) );

    faces.push( new THREE.Face3(i, i+4, i+6) );

    faces.push( new THREE.Face3(i+1, i+3, i+7) );

    faces.push( new THREE.Face3(i+1, i+7, i+5) );


    var geom = new THREE.Geometry();

    geom.vertices = vertices;

    geom.faces = faces;



    return geom;