Alexm
Log in

Use your e-mail or user name and the password to identify yourself

Sign up

You will receive an e-mail with an activation link. Last field is optional


🠉

Repo of the week: ThreeJS

Let's have a look at one of the most popular 3D libraries for the web, how to get started and what we can do with it

Ever since platforms like GitHub, Gitlab or SourceForge (the first to do this, I believe) offered developers the possibility to host and share their projects or repositories on the Internet, the community has kept giving and giving. From huge projects that have impacted the world to small jewels that save us time and the headache of reinventing the wheel: all you have to do is clone the code and just use it. You can also contribute in many ways or get your own copy of the source and go your own way according to your needs.

I like exploring the vast world of open-source development and I try to stay up to date with what's new or popular. Which is why I decided to test a public repository that I find interesting from the several platforms out there and dedicate an article to it every week.

This first time I want to start with something that I already had the chance to test a few times so far: a JavaScript library that can be used to created amazing 3D experiences for web users.

ThreeJS

ThreeJS is a pretty compact library for what it has to offer. It comes accompanied by different add-ons and third-party plug-ins that can be imported only when necessary. At the core of ThreeJS stand a few rendering engines, the most important of them and the default one being based on the WebGL API. But the library is practically a fully featured game engine that has it all: cameras, lighting, objects loaders, materials and textures, animation and audio.
Creating and using all these components is straightforward and convenient, as you will see in a moment.

Getting started

You don't have to clone the repository if you just want to use the library. To bring it to your project, you can either use NPM to install the module or (even easier) just import it from the CDN (saves space and bandwidth and you won't have to worry about future updates, unless you want to specify a fixed version).

Without further ado, let's create an index.html file inside an empty folder and add this boilerplate


<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Getting started with ThreeJS</title>
    <style>
      body { margin: 0; overflow: hidden }
    </style>
    <script type="importmap">
    {
      "imports": {
        "three": "https://unpkg.com/three@/build/three.module.js",
        "three/addons/": "https://unpkg.com/three@/examples/jsm/"
      }
    }
    </script>
  </head>
  <body>
    <script type="module" src="/main.js"></script>
  </body>
</html>

With this we are ready to use ThreeJS. One important thing to mention: the web application has to run on a server (local or remote). Just opening the HTML file will not work. With NPM this is easy as cake. With only two commands, install the serve module and run it

npm install --global serve npx serve .

Now that we have a server running, let's open http://localhost:3000 and see the web application in the browser. As simple as this. Now, we can play with ThreeJS and see what can we do with it.

First, let's create the main.js file and open it. This is where we add all the logic behind our application. The core elements of a ThreeJS based application are: the scene, the camera and the renderer.


// import ThreeJS
import * as THREE from 'three';

// create our basic scene
const scene = new THREE.Scene();
// give the background a light color
scene.background = new THREE.Color(0xeaeaea);
// add a camera in perspective mode (75 degrees field of view, aspect ratio proportional to screen size, near and far clipping plane)
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
// finally create the renderer that will show the scene through the camera
const renderer = new THREE.WebGLRenderer();
// use the entire window for rendering
renderer.setSize(window.innerWidth, window.innerHeight);
// assign the renderer to the canvas element that will be used to display the scene
document.body.appendChild(renderer.domElement);

// render the scene
renderer.render(scene, camera);

At this point, if we refresh the browser, we still don't see anything. Let's try to load and show a 3D object in GLTF format. We will have to import this loader, which is not included by default with the library. Add this at the top, below the first import.


import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';

I have quickly created a simple torus object in Blender with a basic BSDF material (you can download it from here or use your own GLTF object). Now, let's create the loader and add the object to the scene. You can add this portion after the renderer's instancing.

...
const renderer = new THREE.WebGLRenderer();
...

const loader = new GLTFLoader();

loader.load("lava_torus.gltf", function (gltf) {
  // once loaded, add it to the scene
  scene.add(gltf.scene);
}, undefined, function (error) {
  console.error(error);
});

We still don't see anything, because we have to render the scene again after adding the object.

...

  // once loaded, add it to the scene
  scene.add(gltf.scene);

  renderer.render(scene, camera);

...

Wow, the object is too close to the camera. Let's move the camera back a little and rotate it so that the object fits properly inside the view bounds.

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

// let's move the camera few steps backs
camera.position.z = .5;
camera.position.y = .5;
camera.rotation.x = -.8;

...