Diving into the world of WebGL with Three.js

Learn how to create amazing 3D experiences on the web with Three.js library.

Diving into the world of WebGL with Three.js

In this series of articles, we're going to dive deep into the world of WebGL with Three.js. We're going to start with bare theory and basics and move on to more advanced concepts as we move forward.

Honestly, I am not a professional myself in WebGL and Three.js, But as far as I have explored this amazing world, I have been fascinated by it, and I am here to fascinate you all as well 😉.

So are you ready to be fascinated? Let's begin!

What is WebGL?

WebGL stands for Web Graphics Library, it is a JavaScript API that allows us to render interactive 3D graphics within any compatible web browser without the need for plugins. It taps into the potential of your device's GPU, making it capable of handling complex graphical computations at high speeds.

What is Three.js?

Three.js is a javascript library that uses WebGL under the hood and renders 3D graphics on the HTML5 canvas.

Enough with the theory! Let's get practical💪.

But wait, Let's get ourselves familiar with some keywords and definitions to help us get started, shall we?

Well, there are three main elements that you are going to use in pretty much every Three.js application.

  1. A Scene

  2. A Camera

  3. and, A Renderer

A Scene is WHAT you see, A Camera is HOW you see it and a Renderer is what combines both the WHAT and the HOW.

For instance, You see all these beauties of nature every day (that is the WHAT) with your eyes (that is the HOW) while living in this beautiful yet chaotic world (that's where the WHAT and HOW get combined).

Sounds poetic, right? 😏

Well, In short, the Scene is everything around you, the Camera is your eyes and the Renderer is the world.

So what do we get from it?

  1. Without a Camera, The Scene might exist but you can't see it.

  2. Without a Renderer, The Scene and the Camera don't have any meaning.

  3. Without a Scene, even if you have eyes so sharp like an eagle, you still can't see anything.... because there is nothing to see, duh! 😂

There are more keywords and definitions but we will explore them as we move forward.

So without further ado, Let's dive into the code.

The Mighty Setup!

We'll be using Vite for our project setup, and the reason for this is that Vite makes it super easy to get started with a project without having to worry about all the configuration and stuff.

So here we go!

open your terminal and run the following command.

yarn create vite

It will ask you to select a template preset to create a simple boilerplate for you. Just select 'Vanilla' and for the programming language I am going to use 'Javascript', but you can select 'Typescript' if you want.

Then answer a few questions like project name, project author etc. and press 'Enter' and it will install all the necessary packages and set up the boilerplate for you.

After everything is installed correctly, open your project directory in your favorite code editor, I am going to be using VS Code, but you can use any code editor you like.

Delete the counter.js file, and delete everything inside main.js and style.css file

Install Three.js

To Install Three.js open the terminal and run the following command:

yarn add three

Make sure to run the command in your project directory.

Once the three.js package is installed, we are ready to take off the flight.

Creating a SCENE:

As we discussed above, A scene is where all the 3D elements reside. We are going to create a Scene first and then we will add the 3D elements inside that scene later.

Fortunately, It's pretty simple to create a Scene, but first, we need to import Three.js

In main.js file, Import Three.js with the following command:

import * as THREE from 'three';

after importing Three.js, create a scene with the following one-liner.

// After import
const scene = new THREE.Scene();

That's how simple it is to create the scene.

Now let's create the camera:

Creating a Camera:

Creating a camera is not as simple as creating a scene, that's because in Three.js we have two common types of Cameras, and both have different parameters that we have to provide.

  1. Perspective Camera

  2. Orthographic Camera

Perspective Camera:

The perspective camera is like a human eye. For Instance, The closer the element is to the camera the larger it appears and vice versa.

Orthographic Camera:

Whereas, the orthographic camera does not have perspective. The elements appear to have the same size regardless of their distance from the camera.

Perspective Camera is more commonly used because of its realistic nature, and for our case, we are also going to use a perspective camera.

To create a Perspective Camera write the following line of code:

// ...
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
1, 
2000
);

let's explain the 4 parameters that PerspectiveCamera accepts

  1. FOV (field of view): As the name suggests it is a vertical field of view. In simple terms, it helps in deciding how wide or narrow the scene would be visible. We have given the value of 75 to FOV.

  2. Aspect Ratio: it is self-explanatory, we have given the aspect ratio of our entire window so that everything inside the window would be visible as long as it is inside the provided field of view.

The other 2 values are Near and Far, they decide the boundary limit on the z-axis as to how much the object near to or far from the camera should be visible, For instance, we have given a near value of 1 and a far value of 2000 so any element between 1 and 2000 units will be visible.

Now that we have created a camera, we have to add it to the scene.

Add the camera to the scene, by the following line of code:

//...
scene.add(camera)

Our camera is added to the scene, and there is one more thing left to complete the setup and that is to create the renderer

Creating a Renderer:

There are many different types of renderers in three.js, and they all serve different purposes, for this example, we will be using the most common renderer called WebGLRenderer.

To create a WebGLRenderer, write the following lines of code:

const renderer = new THREE.WebGLRenderer()
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
document.body.appendChild(renderer.domElement);

In the above lines of code:

We first initialized a renderer and then set its size to be the size of our window (you can pass any arbitrary value), and pixel ratio, note that I have used Math.min(window.devicePixelRatio, 2) the reason for this is that some devices have a higher pixel ratio sometimes more than 2 or 3, we don't need that much pixel ratio, because the higher the pixel ratio, the more work the GPU needs to do. So that's why we have used a pixel ratio, a maximum of 2 and not more than that.

Lastly, we have appended renderer.domElement to our document body, it'll create a canvas element inside our body tag. There is another approach to creating a canvas element and that is to create a canvas element manually in your html file and pass the canvas to the renderer.

This is how you pass the canvas to the renderer, first, create a canvas element in your index.html file and then pass the canvas to the renderer like this:

//...
const canvasEl = document.querySelector(".class_of_your_canvas_el")
const renderer = new THREE.WebGLRenderer({
    canvas: canvasEl
})

With this approach, you don't need to append the renderer.domElement to the body as we did above.

Finally, when everything is set let's render the scene by the following line of code:

renderer.render(scene, camera);

And with this, you should see a black canvas covering the entire screen of your window.

If you don't see the black screen, or if you have any questions feel free to ask in the comment section.

I would love to help.

That's it for this article, in the second article we are going to create a cube, add it to the scene and animate it.