Three.js: WebGL for Humans

As Web developers, we are always adapting to changes. Our primary language, Javascript, has evolved from being a limited language to handling DOM modifications and form validations to a language that allows us to perform outstanding tasks, such as reading the sensors of a battery, accelerometer or gyroscope to rendering 3D graphics and interacting with them.

So, what is WebGL?

WebGL is an API available on browsers that allows us to render graphics just like most games and 3D software do with OpenGL or DirectX. In detail, WebGL is based on OpenGL ES 2.0. The “ES” means that it’s the version for mobile phones, which has differences with the desktop version for performance’s sake.

As you might already know, when someone starts creating a game or 3D animation, they don’t write it directly for OpenGL. Some people use an Engine and some people use a Graphic Software that can handle it, because writing Directly for OpenGL implies having low level considerations of the hardware, really well acknowledge of math and most important is a overkill for what we're trying to build. All of this applies for WebGL too.

uniform mat4 u_worldViewProjection;
uniform vec3 u_lightWorldPos;
uniform mat4 u_world;
uniform mat4 u_viewInverse;
uniform mat4 u_worldInverseTranspose;

attribute vec4 a_position;
attribute vec3 a_normal;
attribute vec2 a_texcoord;

varying vec4 v_position;
varying vec2 v_texCoord;
varying vec3 v_normal;
varying vec3 v_surfaceToLight;
varying vec3 v_surfaceToView;

void main() {
v_texCoord = a_texcoord;
v_position = (u_worldViewProjection * a_position);
v_normal = (u_worldInverseTranspose * vec4(a_normal, 0)).xyz;
v_surfaceToLight = u_lightWorldPos - (u_world * a_position).xyz;
v_surfaceToView = (u_viewInverse[3] - (u_world * a_position)).xyz;
gl_Position = v_position;

Above you can see an example of the code needed to run a small sample, this subset is called "Vertex Shader" and you'll need the "Fragment Shader" and Javascript & Html to wire it up. I am not going to aim to do this right now, even if what you have in mind is to draw figures (which is basically the idea behind Webgl), you shouldn’t do it. But if you want to create your own Engine/Library, or you already know something about OpenGL, you can check out this link for more information:

Ok, having in mind that writing for WebGL directly is unreliable for most of our practical uses, we had to find an alternative, and this is where Three.js kicks in.

What is Three.js and what does it offer us?

Three.js is a Javascript 3D library, which provides us with canvas, svg, CSS3D and WebGL Renderers to render whatever we want to put in the screen.

This library is built in a way that it's familiar for the people that have worked with 3D software, like blender. Basically using a Renderer, a Scene, a Camera and Mesh Objects we can describe what the user will see.

The basic "Hello World" here is a spinning cube, so let's do it:

The funniest "Hello World" ever

Renderers, Cameras and Scene

I'm going to show a description about what I did above, with some small information about how to start with this.


Basically, we have an engine that will make the content appear on the screen allowing us to take one of the existent ones (WebGL on this case) set up the size and give us a DOMElement, which we'll use to tie the render onto the HTML.

// Create and Set our Renderer
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);

Later, when our scene and camera are ready, we'll trigger a render. This could happen once (just an only call) or inside a function called by requestAnimationFrame (which will render on each frame available, more likely to be used).

// Finally, we render in the screen
// A key point here, is to see how the render connects
//the scene & camera
renderer.render(scene, camera);


The camera aims to give information to the renderer about what should render from the scene and how. We have a few cameras available but we'll focus on Two currently PerspectiveCamera and OrthographicCamera.

While the first one aims to mimic how the human eyes see a 3D Object, the second one makes the objects size invariant regardless of its distance from the camera, so we can use it if we aim to render 2D.

// Create a New Camera, set up his z position
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.z = 1000;

The first Parameter is the field of view or field of vision (abbreviated FOV) to the extent of the observable image that is seen on the display at any given moment. A natural FOV stands between 60 ~ 75.

A example of what FOV is

The second one is the aspect ratio, used as width / height . There is no much science about this one, but if we want to use a fixed size instead of relying on the window size, we should define it fixed.

The 3rd and 4th parameters define what will get rendered on the screen. Something nearer than the first parameter will not be shown on the screen, and the same thing happens if it is farther than the 4th parameter. We could use this to tweak and get some performance improvements of our animation if it comes to clunky or certain elements are not showing up.


Imagine the scene as some sort of container where we'll be putting our elements (Meshes) and Lights. It will be used by the renderer to get information about what to show.

Meshes: A compound of Materials and Geometries

So far so good, until now we had been able to choose a renderer, setup our camera and define a scene, but all of that is useless if we don't have anything to show right? Well, all objects that we will show are called Meshes, and they are constructed by a Material and a Geometry, if we're going to create an application using Three.js I recommend using the Factory Pattern to create these meshes to avoid writing unmaintainable code on the long-term.


A Geometry is the shape that the object will have, we have a lot of Geometries that you could check under the Three.js documentation, and ever more, using a Loader and ShapeGeometry you can be able to import your own shapes from 3D Modeling Softwares.

const cubeGeometry = new THREE.BoxGeometry(width, height, depth);

On our case, we created a BoxGeometry to define our Mesh, if you follow the Link of the Geometries, you could see an example of how they should look.


The material defines the appearance and how the light will affect of our objects. Their configurations go simply from picking a color, to set up its roughness, metalness and reflectivity. Even some of its properties will allow us to upload a Texture, so we can use images to define how our component should look.

const cubeMaterial = new THREE.MeshBasicMaterial({
color: color,
wireframe: showWireframe

Here we're creating a MeshBasicMaterial with a defined color, and wireframe option, the first one will accept a hex value, like 0xff0000 and the second one marks if the object should be solid or we should only show his wireframes.

Different kind of materials applied onto the same object

A Simple explanation of the image above:

MeshBasicMaterial is a material that is not affected by Lights, so even if the source of light was there (it was), you'll not be able to see it.

MeshNormalMaterial map has vectors in RGB colors, which is the reason for the distortion you see.

MeshLambertMaterial doesn’t use specular lights, it uses a non-physically based Lambertian model for calculating reflectance and it’s good for simulating untreated wood or stone.

MeshStandardMaterial uses Physically based rendering (PBR) which means that to get the type of material you can tweak its metalness/roughness, it is the standard of Unity, Unreal and 3D studio among others.

After this introduction post, you should be able to have an idea about what is behind WebGL and Three.js, and use them to render your own 3D Graphics, There are many keypoints that you should check once you understand this like Lights, Animations, Controls. Try creating your own examples, it is pretty fun and doesnt’ take you much time to do it.

If you want to know more about technology and innovation, check us out at Lateral View or subscribe to our newsletter!