JavaScript 3D Modeling with Three.js

Jawara Gordon
6 min readMay 1, 2023

--

3d rendered cartoon style home with a car driving by surrounded by trees on a floating island

Getting Started

Three.js is a 3D library for JavaScript that enables developers to create interactive 3D experiences on the web.

Whether you want to create a game, visualization, or just add some cool 3D elements to your website, Three.js is a great option!

Three.js was created by Ricardo Cabello in 2010, and has since grown into a very popular library (you’ll understand why very soon). Cabello, also known as Mr.doob, initially created the library to showcase his work and experiment with 3D graphics. Three.js has been continually updated over the years with contributions from a large community of developers.

Follow along to the step-by-step coding example below to learn more about this fantastic library and how to build your very first 3D scene.

Setting up Three.js

Before we can start creating 3D scenes, we need to set up our environment. First, we need to install the Three.js library, which we can do by downloading it from their website, using a CDN or the Node package manager (npm).

We’ll use npm for this coding example.

From the docs:

1. Install Node.js. We’ll need it to load manage dependencies and to run our build tool.

2. Install three.js and a build tool, Vite, using a terminal in your project folder. Vite will be used during development, but it isn’t part of the final webpage. If you prefer to use another build tool, that’s fine — we support modern build tools that can import ES Modules.

# three.js
npm install --save three

# vite
npm install --save-dev vite

Once we have the library files, we can create an index.html file with this code:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>three-js-demo</title>
<style>
body { margin: 0; }
</style>
</head>
<body>
<script type="module" src="/main.js"></script>
</body>
</html>

Next, we’ll create a main.js file and import the Three.js library:

import * as THREE from 'three';

Finally, we can start the app by running this command in the terminal:

npx vite

If all goes well, you’ll see a URL like http://localhost:5173 appear that you can click on to open in your browser.

The page will be blank — you’re ready to create a scene!

Building Your First Scene

Now that we have our environment set up, we can start building our first 3D scene, which is like a container for all the 3D objects we’ll be adding.

Add this line below your library imports:

const scene = new THREE.Scene();

Next, we can then add a camera that defines the perspective for how we view our 3D scene.

The first argument is for field of view (FOV) — represented in degrees and is the extent of the scene that is seen on the display at any given moment.

The second argument is the aspect ratio. You should use the width of the element divided by the height when you’re getting started.

The final arguments in this camera class are the near and far clipping plane. Objects further away or closer than these numbers won’t be rendered.

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

Next, we need to add a renderer to our scene, which is responsible for rendering our 3D objects onto the canvas element we created earlier.

You should use the width and height of the area we want to fill — in this case, the width and height of the browser window.

const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);

Then we’ll use the appendChild method to attach the app to a <canvas> element:

document.body.appendChild(renderer.domElement);

We can then add a shape to our scene, which is a 3D object made up of vertices and fill. Let’s also add a hex value color and then wrap them in a mesh that we’ll save to a variable called cube:

const geometry = new THREE.BoxGeometry(1, 1, 1);

const material = new THREE.MeshBasicMaterial({ color: 0x0000ff });

const cube = new THREE.Mesh(geometry, material);

Now we can set our z positioning to move the camera from inside of the shape’s starting position (feel free to experiment with Y and X positions):

camera.position.z = 5;

Finally, we can add our cube to the scene with the .add() method:

scene.add(cube);

Animating Your Scene

Now that we’ve built our first 3D scene, we can add some animation to make it more interesting.

Add the animate() function below the previous code. It will run every frame (about 60 times per second), to give the cube a rotation animation:

Pro Tip: Anything you want to move or change has to go through the animate loop.

function animate() {

requestAnimationFrame(animate);

cube.rotation.x += 0.01;
cube.rotation.y += 0.01;

renderer.render(scene, camera);
}

animate();

We can also add interaction to our scene by listening for user input events like mouse clicks or key presses.

This code will allow a user to click and drag on the screen to change the position of the cube.

First import OrbitControls from the library:

import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

Then add this to your main.js file (outside of the animate function):

const controls = new OrbitControls(camera, renderer.domElement);

Using Custom Models

If you want to start having fun with using your own custom 3D models, visit Sketch Fab where you can sign up for a free account and start looking for assets to download. You can also create your own with tools like Blender — just be sure to follow the Three.js guidelines for suggested file types.

Here’s the flow for using your own custom models.

Once you’ve downloaded a zip file with a custom .gltf format model, import the GLTFLoader from the library:

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

You will need to adjust the background color to your liking:

scene.background = new THREE.Color('white');

Then add some lighting to the scene so you can see your model:

let light = new THREE.DirectionalLight(0xffffff, 50);
scene.add(light);

Next, initialize a new variable for your model:

let model;

Create a new loader:

const loader = new GLTFLoader();

Then add it to the scene with the .load method:

loader.load(
'assets/crystal_skull/scene.gltf',
function (gltf) {
model = gltf.scene;
scene.add(model);
},
undefined,
function (error) {
console.error(error);
}
);

You may need to make some changes to the previous camera positioning such as changing the FOV (try small or larger numbers for the first PerspectiveCamera argument), updating the position of the z, y, and x-axis, or removing other shapes from the scene if they are blocking your view.

Once you can see the custom model, have some fun with adding the same kind of rotation effects we used on the cube (don’t forget to add them inside of the animate() function):

 model.rotation.x += 0.01;

Summary

I hope this post helped to fast-track your introduction to Three.js. There were quite a few challenging steps that I had to overcome so I felt inspired to create this easy-to-follow guide. Once you get through the initial setup, you can get really creative with the capabilities of this outstanding library. Learning how to import and create your own custom models is the next place to go from here. The code for this example can be found on my GitHub at this repo along with my contact info — I’m looking forward to checking out your results!

Sources

https://threejs.org/docs/?q=material#api/en/materials/MeshDepthMaterial

https://observablehq.com/@grantcuster/understanding-scale-and-the-three-js-perspective-camera

Resources

https://sketchfab.com/feed

https://discourse.threejs.org/t/how-to-load-multiple-texture-into-one-gltf-object/40075/2

https://stackoverflow.com/questions/42297885/three-js-rotating-a-3d-object-using-mouse-events

https://github.com/mrdoob/three.js/blob/master/examples/webgl_geometry_text.html

https://discourse.threejs.org/t/how-to-add-a-png-texture-to-a-cube/15040

https://www.adobe.com/express/feature/video/convert/mp4-to-gif

--

--

Jawara Gordon

Jawara (jah-WAH-rah): Full-Stack Web Developer | Audio Engineer JavaScript, React, HTML, CSS/SASS, Ruby on Rails | Ableton Live