Beginner 3D in WebGL using JavaScript and Three.js

Posted by

Spinning 3D blue cylinder inside a spinning wireframe ball
A spinning 3D blue cylinder inside a spinning wireframe ball, with the code responsible (explained in this article).

In this article I will focus on the absolute basics of 3D in WebGL to get you started. You’ll learn about the main concepts of the world of 3D-development. With the emergence of 3D right in your browser the threshold to start learning just got lowered - a lot! Now is the chance for everyone that at least knows some Javascript to start playing with 3D. No installs. No downloads. Just Javascript and the library Three.js.

Introduction to 3D

After reading this article you will know some of the lingo used in the world of 3D-development. It’s a universal terminology that works for all things 3D, be it on the web, for video games, or for a blockbuster movie. As an added bonus you will also have some spinning objects in 3D - in your browser - with just a few lines of code.

Browser 3D is already supported in modern desktop browsers like Chrome, Firefox, Safari, and Opera. 3D will work in Internet Explorer, but only the Canvas-rendering type (I will explain about rendering types later), but in this article we will focus on the WebGL renderer.

WebGL

WebGL is the open standard for 3D in the browser, started at the Mozilla Foundation, and based on OpenGL (that some of the games we play these days use). The main advantage of WebGL compared to Canvas rendering is that WebGL will take advantage of your computer’s 3D-graphics card to basically run things much much faster and smoother.

Browser 3D with Three.js

You could start writing JavaScript right now and produce some cool 3D. But the thing is that 3D-programming is complex, and you’ll need a lot of code, and sprinkle that with loads of math. That makes the threshold for getting started pretty steep. A beginner to 3D-programming, especially coming from the web developing community, would most likely run away cursing.

Javascript library Three.js to the rescue! It will abstract a lot of the 3D-programming for us. We will be able to create all the things we need with just single rows of code. Instead of hundreds of lines of Javascript to get some spinning objects in different colors, we’re down to maybe 20 lines at most.

The documentation for Three.js is very good for the experienced user, and thus a bit too complex for a beginner. It requires you to already know about 3D-programming, all the terminology, and a lot of other related things. In this article I’m assuming you know basically nothing about 3D-programming - but I do assume that you know the basics of Javascript and HTML.

First things first

Start your favorite modern browser and create an empty html-file in your filesystem. Add the basic HTML5-structure in that file and save. Open it in your browser. Voila - blank page! Now give yourself a pat on the back. Then add this script inside your head tag. It’s the Three.js library:

<script src="https://rawgithub.com/mrdoob/three.js/master/build/three.js"></script>
 

Also, create an open script-block in the code after the inclusion of Three.js. In this block I want you to add the code as you progress through this article.

<script>
    // 3D magic woop woop!
</script>
 

3D Terminology

We need to digest a lot of new terminology to understand the basics of 3D, no matter if it’s for your desktop browser or for making a multi million dollar blockbuster movie. Let’s start with the most basic terms we need to understand from the get go. There’s a whole bunch of them, so bare with me. I’ve deliberately simplified my explanation and left out some of the more advanced terms for this article.

Scene

The scene is where everything 3D exists, it’s like in a real world theater and it’s stage. This is the place we will place our 3D models and other things on. Unlike a real theater we will only have a big empty place and absolutely nothing in it. And it’s basically infinite. Just like the vastness of outer space.

Create a Scene by placing this into your script-tag:

Camera

This is pretty much what you’d expect it to be. It’s a camera. If I told you to draw “space” for me you might wanna know “what part”. By defining a Camera in your Scene and placing it at a specific position, you will know what part of space (Scene) you’re watching. And not only will it have a position inside the Scene, it will also be directed towards something in a specific angle and with a specific viewing distance.

Three.js have a few different types of cameras to choose from, but we’ll settle for the most basic one - the Perspective Camera. It works just like one of your own eyes: it has a position, maybe 1,75 meters off of the ground, and looking in a specific direction at a certain angle.

What’s special with a Camera when talking about 3D is that they also have a line of sight. It can’t see into infinity, just like your eyes cannot do that either. As an added benefit this helps us with easing the next step - Rendering - for the computer. I’m sure you’ve played a video game and looked into the horizon and actually seen the end of the gaming world far far away, but as you run towards it new things pop up in the horizon, as if the world was expanding. This is the line of sight. The computer only tries to render what the Camera actually sees, so if you limit the Camera’s line of sight you help the computer to catch up when drawing a lot of complex things, like whole 3D cities for example.

The values we just used are the units we use in 3D, like pixels are used for 2D. I can’t really say how long “1 unit” is, but after working with WebGL for some time you get a feel for how far it is and can be able to adjust it till perfection.

Renderer / Rendering

I just barely mentioned this earlier: a Renderer, and Rendering / to Render.

The thing is computers does a lot of things only inside its memory. It works extremely fast when things stay there. But it’s not so much fun for us because we can’t see anything. That’s why we always Render the Scene using the Camera we created. The computer will - faster than you can see - “draw” all the visible things for us. This is called Rendering, or "to Render".

Rendering is not automatically done by the computer, it involves some complex computation. Luckily we don’t need to learn any of that with Three.js. The Renderer processes the code for the Scene and everything in it and displays an image of it which is updated very fast, perhaps 60 times per second, making it look like things move around. As said before, the Renderer we’re gonna use is WebGL (there are different types with different support and different characteristics).

Geometry

3D is all about math and Geometry. If you see something like a tree, a bird, or a shoe, in 3D you would recognize it as such. But in fact, if we were to look very close at a 3D object we would see that these things are built up by hundreds or thousands of perfectly straight lines. All these lines are represented by a lot of math inside the computers memory. That’s why it’s called Geometry. It’s like the blueprint for a 3D object. Old computer games (like the first Quake) couldn’t handle too complex Geometry and that’s basically why they tend to look more block-like when playing. Modern games are often built by very complex Geometry, because modern computers can handle it, and this makes things look better - more real.

Primitives

You can create very complex Geometry in advance 3D modelling programs like Maya, or open source Blender. But Primitives are such simple Geometry that we can create them with just a line of code. They are something simple, as a cube, a cylinder, or a ball (called a Sphere in 3D). With code we can auto generate all the Geometry for any of the Primitives Three.js has built in.

Let’s create a Sphere:

And now, let’s add a Cylinder: 

This is all we need to actually create a Sphere and a Cylinder in 3D. We’ve defined the radius of the Sphere, and then something we simply could call level of detail. Low detail would mean that the ball would look bulky, you would see all the sharp edges and corners very clearly. With high detail we would get a ball that appears to be round, but actually isn’t because, as I mentioned before, all things 3D are built up by a lot of perfectly straight lines connected to each other. More detail equals more lines, and thus more math for your computer to handle, so be gentle.

Geometry detail differences

Wireframe

A Wireframe is all the lines of a Geometry displayed for you as just that - lines. Just like a blue print. It’s even explained in the word itself: a frame for anything 3D, consisting of only wires - lines.

Nothing covers the surface of a Wireframe so you can see right through everything. Like when watching a new building being built, it’s the steel bars stabilizing it all, the basic structure, or the “skeleton”. A lot of game developers post images of their game characters built up by all these lines to show how complex and detailed they are.

Material

Wireframes aren’t that sexy. They’re just straight lines with nothing but space between them. They are even hidden by default, not even having any color. We need some kind of Material to cover it with - our “building” needs “walls”, our frame needs a painting. It needs to be covered with something. But it could also be just one simple color.

Material types

There are many different types of Material. But for the purpose of this first demonstration we won’t go into more advanced scenarios where you add complex Materials - or Textures - to your Wireframe. We’ll first color the lines of our Wireframes to make them visible.

 

That’s all short and sweet. But let’s try a more real world Material too. The Lambert Material, which will respond to lights by casting shadows over its colored surface according to where the Light actually hits. This is much cooler, and more like something you’ll actually be using when progressing.

Texture

Material is a single color all over your Geometry, be it only on the Wireframe or also in the spaces between those lines. A Texture is actually an image, like a JPG-file, placed on top of the Wireframe like a wallpaper. Texturing could get kind of complex so I won’t talk more about that here. But this is how 3D professionals can make life like characters in games.

Mesh

Mesh is hard to explain without throwing even more words at you. But I’ll try.

A Mesh is what you would call any object in 3D. It’s the combination of a Geometry and its Material (or Texture). The Geometry or Material doesn't do much by themselves, so we combine them, glue them together, creating the Mesh.

It’s the Mesh that you’ll be positioning inside your Scene. You can have any number of them in a Scene as long as the computer can cope. They don’t even have to be in front of the Camera (but won’t be visible to the viewer then).

Create two different Meshes out of the two different Geometries and respective Materials, then add them to your Scene:

Lights

Adding Light is very important as that will create the dynamic 3D shadows and such. Lights are a very complex and big part of 3D and I’m not gonna explain much of it. But basically you could see it as placing different types, sizes, and colors of lamps floating throughout your scene shining light at different strengths.

Good lighting is one of the important factors for achieving high realism in 3D. That’s why big movie companies often have dedicated employees that focus only on the Lights.

For the sake of example we’ll add a PointLight. It’s like a real world flashlight. You set the color the Light will shine with (let’s set that to white), and then position it in your Scene.

Axis (X, Y, and Z)

All the things we placed in our Scene so far has just been added to the default location, the absolute center in space. Except for the Camera and the Light. For the Light we specified three different values for position. X, Y, and Z. These are three different Axis starting from zero in the middle. In one direction the Axis increases in value from zero, in the other direction it decreases below zero.

X and Y are kind of basic for a web developer, it’s where on a flat plane something is located. But in 3D we have three dimensions (3D) so the Z-axis is added - the height above that invisible plane we placed it on.

Imagine you’re laying on a floor in a perfectly square room, looking out over the floor. Placing a small red ball on the floor would need for you to actually decide it’s X and Y position. This is done by placing it somewhere between the two opposing walls at your side, and then somewhere between the other two walls (one behind you, the other in front of you). With only these two Axis you can place the ball absolutely anywhere on the floor. The Z-axis would then be used to place it above the floor, up in mid air.

All things in 3D needs a position along the Axis of a Scene, but they can also have their own rotation Axis defined. The rotation Axis is attached to the object itself (and not the Scene) and sets the angle, or rotation, of the object. Like setting where an eye looks at, or if a cylinder should stand or lay down (accomplished by rotating the cylinder around its own Axis).

Make the 3D happen

To view your creations so far we need to Render the Scene with everything in it. To tell the computer exactly what to Render from our Scene we’ll add our Camera to it as well. That’s all. 3D is made!

The function requestAnimationFrame we are using is native JavaScript in Blink and Webkit browsers. It’s a lot like a setInterval timer, but smarter. It only executes when the current browser tab is visible so we won’t waste resources. It calls the given function when it’s capable of rendering again, thus creating a never ending loop.

But to make it a bit more interesting than just some things sitting still in the Scene, we’ll put a spin to our Meshes between each rendering cycle (one cycle is done when all functions for animating have finished and requestAnimationFrame fires again). Now things all of a sudden starts to move.

Done

Running all this code actually produces some working 3D, right in your browser! No installs, no downloads. With just a few lines of JavaScript you actually created all the things needed for a basic animation in 3D: a Renderer, a Scene, a Camera, a couple of Meshes (Geometry with an attached Material), and topped it off with a Light. Welcome to the world of 3D programming!

Confused by all the terms? When I first got interested in 3D and game developing some years ago I found nailing all the terms helped me immensely in learning more.

There is even more terminology for the ones that feel this is too basic. Things like Shaders, Bump maps, Polygons, Vertices, Faces, and Blending also play a big part of 3D. But this is an article about 3D for an absolute beginner.

Do try and play around with the things you’ve just created. Created more Meshes, change their Materials, move them around, animated them differently in the “drawThings()”-function, adjust the Light, add more Lights, animate the Light, and so on.

Related links:

All our code

Comments