Search icon CANCEL
Subscription
0
Cart icon
Close icon
You have no products in your basket yet
Save more on your purchases!
Savings automatically calculated. No voucher code required
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletters
Free Learning
Arrow right icon
$9.99 | ALL EBOOKS & VIDEOS
Save more on purchases! Buy 2 and save 10%, Buy 3 and save 15%, Buy 5 and save 20%
Learn Three.js - Fourth Edition
Learn Three.js - Fourth Edition

Learn Three.js: Program 3D animations and visualizations for the web with JavaScript and WebGL, Fourth Edition

By Jos Dirksen
$39.99 $9.99
Book Feb 2023 554 pages 4th Edition
eBook
$39.99 $9.99
Print
$49.99
Subscription
$15.99 Monthly
eBook
$39.99 $9.99
Print
$49.99
Subscription
$15.99 Monthly

What do you get with eBook?

Product feature icon Instant access to your Digital eBook purchase
Product feature icon Download this book in EPUB and PDF formats
Product feature icon AI Assistant (beta) to help accelerate your learning
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
Buy Now
Table of content icon View table of contents Preview book icon Preview Book

Learn Three.js - Fourth Edition

Creating Your First 3D Scene with Three.js

In recent years, modern browsers have acquired powerful features that can be accessed directly from JavaScript. You can easily add video and audio with HTML5 tags and create interactive components through the use of HTML5 Canvas. Together with HTML5, modern browsers also support WebGL. With WebGL, you can directly make use of the processing resources of your graphics card and create high-performance 2D and 3D computer graphics. Using WebGL directly from JavaScript to create and animate 3D scenes is a very complex, verbose, and error-prone process. Three.js is a library that makes this a lot easier. The following list shows some of the things that are very easy to do with Three.js:

  • Create simple and complex 3D geometries and render them in any browser
  • Animate and move objects through a 3D scene
  • Apply textures and materials to your objects
  • Use different light sources to illuminate the scene
  • Use models from 3D modeling software and export generated models into these programs
  • Add advanced post-processing effects to your 3D scene
  • Create and work with custom shaders
  • Create, visualize, and animate point clouds
  • Create virtual reality (VR) and augmented reality (AR) scenes

With a couple of lines of JavaScript (or TypeScript, as we’ll see later in this book), you can create anything, from simple 3D models to photorealistic scenes, all of which are rendered in real time in the browser. For instance, Figure 1.1 shows an example of what can be done with Three.js (you can see the animation for yourself by opening https://threejs.org/examples/webgl_animation_keyframes.html in your browser):

Figure 1.1 – Three.js rendered and animated scene

Figure 1.1 – Three.js rendered and animated scene

In this chapter, we’ll directly dive into Three.js and create a couple of examples that will show you how Three.js works, and that you can use to play around with and get to know Three.js a little bit. We won’t dive into all the technical details yet; you'll learn about those in the following chapters. By the end of this chapter, you’ll be able to create a scene, and run and explore all the examples in this book.

We’ll start this book with a short introduction to Three.js and then quickly move on to the first few examples and code samples. Before we get started, let’s quickly look at the most important browsers out there and their support for WebGL (and WebGPU).

Note

All modern browsers on desktop, as well as on mobile, currently support WebGL. Older versions of IE (those before version 11) won’t be able to run WebGL-based applications. On mobile, most browsers support WebGL. So, with WebGL, you can create interactive 3D visualizations that run very well on desktops, as well as on mobile devices.

In this book, we’ll focus on the WebGL-based renderer provided by Three.js. There is, however, also a CSS 3D-based renderer, which provides an easy API to create CSS 3D-based 3D scenes. A big advantage of using a CSS 3D-based approach is that this standard is supported on all mobile and desktop browsers and allows you to render HTML elements in a 3D space. We won’t go into the details of this browser but will show an example in Chapter 7, Points and Sprites.

Besides WebGL, a new standard for using the GPU to render in your browser called WebGPU is being developed, which will provide even better performance than WebGL and, in the future, become the new standard. When you use Three.js, you don’t have to worry about this change. Three.js already partly supports WebGPU and as that standard matures, so will the support of this standard in Three.js. So, everything you create with Three.js will also work out of the box with WebGPU.

In this first chapter, you’ll directly create a 3D scene and be able to run it on a desktop or mobile device. We’ll explain the core concepts of Three.js, and if there are more advanced topics, we’ll mention in what chapter we’ll explain these in more detail. In this chapter, we’ll create two different scenes. The first one will show a basic geometry rendered in Three.js, as shown in the following figure:

Figure 1.2 – Default geometries rendered

Figure 1.2 – Default geometries rendered

After that, we’ll also quickly show you how you can load external models, and how easy it is to create realistic-looking scenes. The result of the second example will look like this:

Figure 1.3 – Rendering an externally loaded model

Figure 1.3 – Rendering an externally loaded model

Before you start working on these examples, in the next couple of sections, we’ll look at the tools you need to easily work with Three.js and how you can download the examples shown in this book.

In this chapter, we’ll cover the following topics:

  • Requirements for using Three.js
  • Downloading the source code and examples used in this book
  • Testing and experimenting with the examples
  • Rendering and viewing a 3D object
  • Introducing a couple of helper libraries for statistics and controlling the scene

Technical requirements

Three.js is a JavaScript library, so all you need to create Three.js WebGL applications is a text editor and one of the supported browsers to render the results. I would like to recommend the following text editors, which I’ve used extensively over the last couple of years for various projects:

  • Visual Studio Code: This free editor from Microsoft runs on all major platforms and provides great syntax highlighting and smart completion based on types, function definitions, and imported libraries. It provides a very clean interface and is great for working on JavaScript projects. It can be downloaded from here: https://code.visualstudio.com/. If you don’t want to download this editor, you can also just navigate to https://vscode.dev/, which will launch an editor directly in your browser, from which you can connect to a GitHub repository or access directories on your local filesystem.
  • WebStorm: This editor from JetBrains offers great support for editing JavaScript. It supports code completion, automatic deployment, and JavaScript debugging, directly from the editor. Besides this, WebStorm has excellent GitHub (and other version control system) support. You can download a trial edition from http://www.jetbrains.com/webstorm/.
  • Notepad++: Notepad++ is a general-purpose editor that supports code highlighting for a wide range of programming languages. It can easily lay out and format JavaScript. Note that Notepad++ is only for Windows. You can download Notepad++ from http://notepad-plus-plus.org/.
  • Sublime Text Editor: Sublime is a great editor that offers very good support for editing JavaScript. Besides this, it provides many very helpful selections (such as multi-line select) and edit options, which, once you get used to them, provide a really good JavaScript-editing environment. Sublime can also be tested for free and can be downloaded from http://www.sublimetext.com/.

Even if you don’t use any of these editors, there are a lot of editors available, both open source and commercial, that you can use to edit JavaScript and create your Three.js projects, since all you need is the ability to edit text. An interesting project you might want to look at is AWS Cloud9 (http://c9.io). This is a cloud-based JavaScript editor that can be connected to a GitHub account. This way, you can directly access all the source code and examples from this book and experiment with them.

Note

Besides these text-based editors, which you can use to edit and experiment with the sources from this book, Three.js currently also provides an online editor.

With this editor, which you can find at http://threejs.org/editor/, you can create Three.js scenes using a graphical approach.

I suggest picking up Visual Studio Code. It is a very lightweight editor with great support for JavaScript and has several other extensions that make writing JavaScript applications easier.

Earlier, I mentioned that most modern web browsers support WebGL and can be used to run Three.js examples. I usually run my code in Firefox. The reason is that, often, Firefox has the best support and performance for WebGL and it has a great JavaScript debugger. With this debugger, as shown in the following screenshot, you can quickly pinpoint problems using, for instance, breakpoints and console output:

Figure 1.4 – Firefox debugger

Figure 1.4 – Firefox debugger

Note

All the examples in this book will work just as well with Chrome as they do with Firefox. So, if that’s your browser of choice, you can, of course, use that one instead.

Throughout this book, I’ll give you pointers on debugger usage and other debugging tips and tricks. That’s enough by way of an introduction for now; let’s get the source code and start with the first scene.

Getting the source code

All the code for this book is available on GitHub (https://github.com/PacktPublishing/Learn-Three.js-Fourth-edition). GitHub is a site that hosts Git repositories. You can use these to store, access, and version source code. There are a couple of ways that you can get the sources for yourself. You can do either of the following:

  • Clone the Git repository. This means you use the git command-line tool to get the latest version of the sources for this book.
  • Download and extract an archive from GitHub, which contains everything.

In the following two subsections, we’ll explore these options in a bit more detail.

Using git to clone the repository

One way to get all the examples is to clone this repository using the git command-line tool. To do this, you need to download a Git client for your operating system. If you’ve got an up-to-date operating system, you probably already have Git installed. You can quickly check this by running the following in a terminal:

$ git --version
git version 2.30.1 (Apple Git-130)

If the command isn’t installed yet, you can get a client and instructions on how to install it from here: http://git-scm.com. After installing Git, you can use the git command-line tool to clone this book’s repository. Open a command prompt and go to the directory where you want to download the sources. In that directory, run the following:

$ git clone https://github.com/PacktPublishing/Learn-Three.js-Fourth-edition.
git clone git@github.com:PacktPublishing/Learn-Three.js-Fourth-edition.git
Cloning into 'learning-threejs-fourth'...
remote: Enumerating objects: 96, done.
remote: Counting objects: 100% (96/96), done.
remote: Compressing objects: 100% (85/85), done.
fetch-pack: unexpected disconnect while reading sideband packet
...

After doing this, all the source code will be downloaded into the learning-threejs-fourth directory. From that directory, you can run all the examples explained throughout this book.

Downloading and extracting the archive

If you don’t want to use git to download the sources directly from GitHub, you can also download an archive. Open https://github.com/PacktPublishing/Learn-Three.js-Fourth-edition in a browser and click on the Code button on the right-hand side. This will give you the option to download all the sources in a single ZIP file by clicking on the Download ZIP option:

Figure 1.5 – Downloading the archive from GitHub

Figure 1.5 – Downloading the archive from GitHub

After extracting this to a directory of your choice, all the examples will become available.

Note

You can also download the example code files from your account at http://www.packtpub.com for all the Packt Publishing books you have purchased. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files emailed directly to you.

Now that you’ve downloaded or cloned the source code, let’s quickly check whether everything is working and familiarize you with the directory structure.

Testing and experimenting with the examples

The code and examples are organized per chapter and, with the examples, we will provide a simple integrated server that you can use to access all the examples. To get this server up and running, we need to install Node.js and npm. These tools are used to manage JavaScript packages and build JavaScript applications and make it easier to modularize our Three.js code and integrate existing JavaScript libraries.

To install these two tools, go to https://nodejs.org/en/download/ and select the appropriate installer for your operating system. Once installed, open a terminal and check whether everything is working. On my machine, the following versions are being used:

$ npm --version
8.3.1
$ node --version
v16.14.0

Once these tools have been installed, we need to perform a few steps to get all the externally needed dependencies before we can build and access the examples:

  1. First, we need to download the external libraries used in the examples. For instance, Three.js is one of the dependencies we need to download.

To download all the dependencies, run the following command in the directory where you downloaded or extracted all the examples:

$ npm install
added 570 packages, and audited 571 packages in 21s

The preceding command will start downloading all the required JavaScript libraries and store these in the node_modules folder.

  1. Next, we need to build the examples. Doing so will combine our source code and the external libraries into a single file, which we can show in the browser.

To build the examples using npm, use the following command:

$ npm run build
> ltjs-fourth@1.0.0 build
> webpack build
...

Note that you only have to run the two preceding commands once.

  1. With that, all the examples will have been built and are ready for you to explore. To open these examples, you need a web server. To start a server, simply run the following command:
    $ npm run serve
    > ltjs-fourth@1.0.0 serve
    > webpack serve –open
    <i> [webpack-dev-server] Project is running at:
    <i> [webpack-dev-server] Loopback: http://localhost:8080/
    <i> [webpack-dev-server] On Your Network (Ipv4): http://192.168.68.144:8080/
    <i> [webpack-dev-server] On Your Network (Ipv6): http://[fe80::1]:8080/

At this point, you’ll probably notice that npm has already opened your default browser and shows the content of http://localhost:8080 (if this isn’t the case, just open your browser of choice and navigate to http://localhost:8080). You’ll be presented with an overview of all the chapters. In each of these subfolders, you’ll find the examples that are explained in that chapter:

Figure 1.6 – Overview of all the chapters and examples

Figure 1.6 – Overview of all the chapters and examples

One very interesting feature of this server is that we can now see the changes we make to the source code immediately reflected in the browser. If you have started the server by running npm run serve, open up the chapter-01/geometries.js example from the sources you’ve downloaded in your editor and change something; you’ll see that this is also changed at the same time in your browser after you have saved the change. This makes testing changes and fine-tuning colors and lights much easier. If you open the chapter-01/geometries.js file in your code editor, and you open the http://localhost:8080/chapter-01/geometries.html example in your browser, you can see this in action. In your editor, change the color of the cube. To do so, find the following code:

initScene(props)(({ scene, camera, renderer, orbitControls }) => {
  const geometry = new THREE.BoxGeometry();
  const cubeMaterial = new THREE.MeshPhongMaterial({
    color: 0xFF0000,
  });

Change it to the following:

initScene(props)(({ scene, camera, renderer, orbitControls }) => {
  const geometry = new THREE.BoxGeometry();
  const cubeMaterial = new THREE.MeshPhongMaterial({
    color: 0x0000FF,
  });

Now, when you save the file, you’ll immediately see that the color of the cube in the browser changes, without you having to refresh the browser or do anything else.

Note

The setup we’re working with in this book is one of many different approaches you can use to develop web applications. Alternatively, you can include Three.js (and other libraries) directly in your HTML file or use an approach with import-maps, as is done with the example on the Three.js website. All of these have advantages and disadvantages. For this book, we’ve chosen an approach that makes it easy to experiment with the sources and get direct feedback in the browser, and closely resembles how these kinds of applications are built normally.

A good starting point to understand how everything works together is by looking at the HTML file that we opened in the browser.

Exploring the HTML structure for Three.js applications

In this section, we’ll look at the source of the geometries.html file. You can do this by looking at the source in the browser or opening the file from the dist/chapter-1 folder in the same location where you downloaded the source for this book:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <style>
    body {
      margin: 0;
    }
  </style>
  <script defer src="../js/vendors-node_modules_three_
    build_three_module_js.js"></script>
  <script defer src="../js/vendors-node_modules_lil-gui_
    dist_lil-gui_esm_js.js"></script>
  <script defer src="../js/vendors-node_modules_three_
    examples_jsm_controls_OrbitControls_js.js"></script>
  <script defer src="../js/geometries.js"></script>
</head>
<body>
</body>
</html>

This code is generated when you run the npm run build step. This will combine all the sources and external libraries you’ve used into separate source files (called bundles) and add them to this page. So, you don’t need to do this yourself. The first three <script> tags refer to any of the external libraries we use. Later in the book, we’ll introduce other libraries such as React.js and Tween.js. Those will be included in the same manner automatically. The only other elements here are <style> and <body>. <style> is used to disable any margins in the page, so we can use the complete browser viewport to show our 3D scenes. Furthermore, we’ll add the 3D scene programmatically into an empty <body> element, which we’ll explain in the next section.

If you do want to add custom HTML elements here, you can, of course, do that. In the root of the downloaded code, you’ll find a template.html file, which is used by the build process to create the individual HTML files for the examples. Anything you add there will be added to all the examples. We won’t dive too deep into how this works since that’s outside the scope of this book. However, if you want to learn more about how this works, a couple of good resources on webpack (which we use for this) are as follows:

  • The getting started with webpack guide: https://webpack.js.org/guides/getting-started/. This site contains a tutorial that explains the reason why we need webpack for JavaScript development, and how the basic concepts work.
  • Information on the HTML webpack plugin: https://github.com/jantimon/html-webpack-plugin. Here, you can find information on the webpack plugin we use to combine the sources into the separate HTML pages you see when you open the browser after running npm run build and then running npm run serve.

Note that we don’t have to explicitly initialize our scene or call JavaScript. Whenever we open this page and the geometries.js file is loaded, the JavaScript from that file will run and create our 3D scene.

Now that we’ve set up the basic structure, we can create and render our first scene.

Rendering and viewing a 3D object

In this section, you’ll create your first scene, which is a simple 3D scene that looks like this:

Figure 1.7 – First scene with two standard geometries

Figure 1.7 – First scene with two standard geometries

In the preceding screenshot, you can see two objects that rotate. These objects are called meshes. A mesh describes the geometry of an object – that is, its shape – and contains information about the material of the object. A mesh determines how the shape gets shown on screen through traits such as color, or whether the object is shiny or transparent.

In the previous screenshot, we can identify three of these meshes:

Object

Description

Plane

This is a two-dimensional rectangle that serves as the ground area. In Figure 1.7, you can see this since it shows the shadows cast by the two meshes. We will create this as a very large rectangle so that you don’t see any edges.

Cube

This is a three-dimensional cube and is shown on the left of Figure 1.7. It is rendered in red.

Torus knot

This is the TorusKnot you can see to the right of Figure 1.7. This one is rendered in green.

Figure 1.8 – Overview of the objects in the scene

To get all this on screen, we need to perform a couple of steps, which we’ll explain in the upcoming sections.

Setting up the scene

Each Three.js application at least needs a camera, a scene, and a renderer. The scene is the container that holds all the objects (meshes, cameras, and lights), the camera determines what part of the scene is shown when it is rendered, and the renderer takes care of creating the output on the screen, taking into account all the information from the meshes, cameras, and lights in the scene.

All the code we’ll be discussing can be found in the chapter-1/getting-started.js file. The basic structure of this file is as follows:

import * as THREE from "three";
import Stats from 'three/examples/jsm/libs/stats.module'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
// create a scene
...
// setup camera
...
// setup the renderer and attach to canvas
...
// add lights
...
// create a cube and torus knot and add them to the scene
...
// create a very large ground plane
...
// add orbitcontrols to pan around the scene using the
   mouse
...
// add statistics to monitor the framerate
...
// render the scene

If you look through the preceding steps, you might have noticed that a lot of these steps are the same for each scene you create. Since we’ve got a lot of examples in this book that show different features of Three.js, we’ll extract this code into a couple of helper files. We’ll show how we did this at the end of this chapter. For now, we will walk through the different steps and introduce you to the basic components of a Three.js scene.

First, we must create a THREE.Scene. This is a basic container that will hold all of the meshes, lights, and cameras and has a couple of simple properties, which we’ll explore in more depth in the next chapter:

// basic scene setup
const scene = new THREE.Scene();
scene.backgroundColor = 0xffffff;
scene.fog = new THREE.Fog(0xffffff, 0.0025, 50);

Here, we will create the container object that will hold all our objects, set the background color of this scene to white (0xffffff), and enable the fog effect in this scene. With fog enabled, objects further away from the camera will slowly get hidden by fog.

The next step is creating the camera and the renderer:

// setup camera and basic renderer
const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
);
camera.position.x = -3;
camera.position.z = 8;
camera.position.y = 2;
// setup the renderer and attach to canvas
const renderer = new THREE.WebGLRenderer({ antialias: true
  });
renderer.outputEncoding = THREE.sRGBEncoding;
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.VSMShadowMap;
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0xffffff);
document.body.appendChild(renderer.domElement);

In the preceding code, we created a PerspectiveCamera, which determines what part of the scene is rendered. Don’t worry too much about the parameters at this point, since we’ll discuss those in detail in Chapter 3, Working with Light Sources in Three.js. We also positioned the camera at the specified x-, y-, and z-oordinates. The camera will, by default, look at the center of the scene (which is 0, 0, 0), so we don’t need to change anything for that.

In this code fragment, we also created a WebGLRenderer, which we will use to render the view from the camera on the scene. Ignore the other properties for now; we’ll explain these in the next few chapters when we dive into the details of WebGLRenderer and how you can fine-tune the colors and work with shadows. One interesting part to notice is document.body.appendChild(renderer.domElement). This step adds an HTML canvas element to the page, which shows the output of the renderer. You can see this when you inspect the page in your browser:

Figure 1.9 – Canvas added by Three.js

Figure 1.9 – Canvas added by Three.js

At this point, we’ve got an empty THREE.Scene, a THREE.PerspectiveCamera, and a THREE.WebGLRenderer. If we add some objects to the scene, we can already show some output on the screen. Before we do this, though, we’ll add a couple of additional components:

  • OrbitControls: This will allow you to use the mouse to rotate and pan around the scene
  • Lights: This allows us to use some more advanced materials, cast shadows, and generally make our scene look better

In the next section, we’ll first add the lights.

Adding lights

If we don’t have lights in the scene, most materials will be rendered in black. So, to see our meshes (and get shadows), we’re going to add some lights to the scene. In this case, we’re going to add two lights:

  • THREE.AmbientLight: This is just a simple light that affects everything with the same intensity and color.
  • THREE.DirectionalLight: This is a light source whose rays are cast in parallel to one another. This is pretty much how we experience the light of the Sun.

The following code fragment shows how to do this:

// add lights
scene.add(new THREE.AmbientLight(0x666666))
const dirLight = new THREE.DirectionalLight(0xaaaaaa)
dirLight.position.set(5, 12, 8)
dirLight.castShadow = true
// and some more shadow related properties

And once again, these lights can be configured in various ways, the details of which we’ll explain in Chapter 3. At this point, we’ve got all the components ready to render a scene, so let’s add the meshes.

Adding the meshes

In the following code fragment, we create the three meshes in our scene:

// create a cube and torus knot and add them to the scene
const cubeGeometry = new THREE.BoxGeometry();
const cubeMaterial = new THREE.MeshPhongMaterial({ color:
  0x0000FF });
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube.position.x = -1;
cube.castShadow = true;
scene.add(cube);
const torusKnotGeometry = new THREE.TorusKnotBufferGeometry(0.5, 0.2, 100, 100);
const torusKnotMat = new THREE.MeshStandardMaterial({
  color: 0x00ff88,
  roughness: 0.1,
});
const torusKnotMesh = new THREE.Mesh(torusKnotGeometry, torusKnotMat);
torusKnotMesh.castShadow = true;
torusKnotMesh.position.x = 2;
scene.add(torusKnotMesh);
// create a very large ground plane
const groundGeometry = new THREE.PlaneBufferGeometry(10000,
  10000)
const groundMaterial = new THREE.MeshLambertMaterial({
  color: 0xffffff
})
const groundMesh = new THREE.Mesh(groundGeometry, groundMaterial)
groundMesh.position.set(0, -2, 0)
groundMesh.rotation.set(Math.PI / -2, 0, 0)
groundMesh.receiveShadow = true
scene.add(groundMesh)
);

Here, we have created a cube, a torus knot, and the ground. All these meshes follow the same idea:

  1. We create the shape – that is, the geometry of the objects: a THREE.BoxGeometry, a THREE.TorusKnotBufferGeometry, and a THREE.PlaneBufferGeometry.
  2. We create the material. In this case, we use a THREE.MeshPhongMaterial for the cube, a THREE.MeshStandardMaterial for the torus knot, and a THREE.MeshLambertMaterial for the ground. The color of the cube is blue, the color of the torus knot is greenish, and the color of the ground is white. In Chapter 4, Working with Three.js Materials, we’re going to explore all these materials, where they can best be used, and how to configure them.
  3. We tell Three.js that the cube and the torus knot cast shadows and that the ground will receive shadows.
  4. Finally, from the shape and the material, we create a THREE.Mesh, position the mesh, and add it to the scene.

At this point, we just have to call renderer.render(scene, camera). You will see the result on your screen:

Figure 1.10 – Geometries renderer – static

Figure 1.10 – Geometries renderer – static

If you’ve got the source file (chapter-01/getting-started.js), open it in your editor; now is also a good time to experiment a bit with the settings. By changing the torusKnot.postion.x, torusKnot.position.y, and torusKnot.position.z settings, you can move the torus knot around the scene (changes are applied after you save the file in the editor). You can also easily change the color of the meshes by changing the color property of the materials.

Adding an animation loop

At this point, the scene is very static. You can’t move the camera around, and nothing is moving. If we want to animate the scene, the first thing that we need to do is find some way to re-render the scene at a specific interval. Before HTML5 and the related JavaScript APIs came along, the way to do this was by using the setInterval(function,interval) function. With setInterval, we could specify a function that, for instance, would be called every 100 milliseconds. The problem with this function is that it doesn’t take into account what is happening in the browser. If you were browsing another tab, this function would still be fired every couple of milliseconds. Besides that, setInterval isn’t synchronized when the the screen is redrawn. This can lead to higher CPU usage, flickering, and generally poor performance.

Luckily, modern browsers have a solution for that with the requestAnimationFrame function.

Introducing requestAnimationFrame

With requestAnimationFrame, you can specify a function that is called at an interval. However, you don’t define this interval. This interval is defined by the browser. You do any drawing you need to do in the supplied function, and the browser will make sure it is painted as smoothly and efficiently as possible. Using this is simple. We just add the following code:

function animate() {
  requestAnimationFrame(animate);
  renderer.render(scene, camera);
}
animate();

In the preceding animate function, we called requestAnimationFrame again, to keep the animation going. The only thing we need to change in the code is that instead of calling renderer.render after we’ve created the complete scene, we call the animate() function once to initiate the animation. If you run this, you won’t see any changes yet compared to the previous example because we haven’t changed anything in this animate() function. Before we add additional functionality to this function though, we will introduce a small helper library called stats.js, which gives us information about the frame rate the animation is running at. This library, from the same author as Three.js, renders a small graph that shows us information about the rate at which the scene is rendered.

To add these statistics, all we need to do is import the correct module and add it to our page:

import Stats from 'three/examples/jsm/libs/stats.module'
const stats = Stats()
document.body.appendChild(stats.dom)

If you leave it at this, you’ll see a nice stats counter in the top left of your screen, but nothing will happen. The reason is that we need to tell this element when we’re in the requestAnimationFrame loop. For this, we just need to add the following to our animate function:

function animate() {
  requestAnimationFrame(animate);
  stats.update();
  renderer.render(scene, camera);
}
animate();

If you open the chapter-1/getting-started.html example, you’ll see that it shows a frames per second (FPS) counter in the top left of your screen:

Figure 1.11 – FPS statistics

Figure 1.11 – FPS statistics

In the chapter-1/getting-started.html example, you can already see that the torus knot and cube are moving around their axes. In the following section, we’ll explain how you do this by extending the animate() function.

Animating the meshes

With requestAnimationFrame and the statistics configured, we’ve got a place to put our animation code. All we need to do is add this to the animate() function:

cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
cube.rotation.z += 0.01;
torusKnotMesh.rotation.x -= 0.01;
torusKnotMesh.rotation.y += 0.01;
torusKnotMesh.rotation.z -= 0.01;

That looks simple, right? What we do is increase the rotation property of each of the axes by 0.01 every time the animate() function is called, which shows up as the meshes smoothly rotating around all of their axes. If we change the position instead of the rotation around the axes, we can move the meshes around:

let step = 0;
animate() {
  ...
  step += 0.04;
  cube.position.x = 4*(Math.cos(step));
  cube.position.y = 4*Math.abs(Math.sin(step));
  ...
}

With the cube, we have already changed the rotation property; now, we’re also going to change its position property in the scene. We want the cube to bounce from one point in the scene to another with a nice, smooth curve. For this, we need to change its position on the X-axis, as well as the y-axis. The Math.cos and Math.sin functions help us create a smooth trajectory using the step variable. I won’t go into the details of how this works here. For now, all you need to know is that step+=0.04 defines the speed of the bouncing sphere. If you want to enable this for yourself, open up the chapter-1/geometries.js file and uncomment the section from the animate() function. Once you’ve done this, you’ll see something like this on screen, where the blue cube is dancing around the scene:

Figure 1.12 – Jumping blue cube

Figure 1.12 – Jumping blue cube

Enabling orbit controls

If you try and move the scene around with your mouse, nothing much will happen. That is because we added the camera to a fixed position, and we didn’t update its position in the animate loop. We can, of course, do this in the same manner as we did to the position of the cube, but Three.js comes with several controls that allow you to easily pan around the scene and move the camera around. For this example, we’ll introduce THREE.OrbitControls. With these controls, you can use your mouse to move the camera around the scene and look at different objects. All we need to do to get this working is create a new instance of these controls, attach them to the camera, and call the update function from our animation loop:

const orbitControls = new OrbitControls(camera, renderer.
  domElement)
// and the controller has a whole range of other properties we can set
function animate() {
  ...
  orbitControls.update();
}

Now, you can use your mouse to navigate around the scene. This is already enabled in the chapter-1/getting-started.html example:

Figure 1.13 – Zooming in with orbit controls

Figure 1.13 – Zooming in with orbit controls

Before wrapping up this section, we will add one more element to our basic scene. When working with 3D scenes, animations, colors, and properties, it often requires a bit of experimenting to get the correct color, animation speed, or material property. It would be very easy if you had a simple GUI that allowed you to change these kinds of properties on the fly. Luckily, you do!

Using lil-gui to control properties and make experimenting easier

In the previous example, we added a little bit of animation for the torus knot and the cube. Now, we’ll create a simple UI element that allows us to control the speed of the rotations and the movement. For this, we’re going to use the lil-gui library from https://lil-gui.georgealways.com/. This library allows us to quickly create a simple control UI to make experimenting with the scene easier. It can be added as follows:

import GUI from "lil-gui";
...
const gui = new GUI();
const props = {
  cubeSpeed: 0.01,
  torusSpeed: 0.01,
};
gui.add(props, 'cubeSpeed', -0.2, 0.2, 0.01)
gui.add(props, 'torusSpeed', -0.2, 0.2, 0.01)
function animate() {
  ...
  cube.rotation.x += props.cubeSpeed;
  cube.rotation.y += props.cubeSpeed;
  cube.rotation.z += props.cubeSpeed;
  torusKnotMesh.rotation.x -= props.torusSpeed;
  torusKnotMesh.rotation.y += props.torusSpeed;
  torusKnotMesh.rotation.z -= props.torusSpeed;
  ...
}

In the preceding code fragment, we created a new control element (new GUI) and configured two controls: cubeSpeed and torusSpeed. In each animation step, we’ll just look up the current values and use those to rotate the meshes. Now, we can experiment with the properties without having to switch between the browser and the editor. You’ll see this UI in most of the examples in this book where we provide it so that you can easily play around with the different options provided by the materials, the lights, and the other Three.js objects. In the following screenshot, you can see the controls you can use to control the scene in the top-right part of the screen:

Figure 1.14 – Using controls to modify the properties of the scene

Figure 1.14 – Using controls to modify the properties of the scene

Before we move on to the last section of this chapter, here’s a quick note on what we’ve shown so far. You can imagine that most scenes will need pretty much the same setup. They all need some lights, a camera, a scene, and maybe a ground floor. To avoid having to add all this to each example, we’ve externalized most of these common elements to a set of helper libraries. That way, we can keep the examples nice and clean so that they only show you the code relevant to that example. If you’re interested in how that’s set up, you can look at the files from the bootstrap folder, which brings this approach together.

In the previous example, we rendered some simple meshes in the scene and positioned them directly. Sometimes, though, it is hard to determine where to position objects, or how far we should rotate them. Three.js provides several different helpers that provide you with additional information about the scene. In the next section, we’ll look at a couple of these helper functions.

Helper objects and util functions

Before we move on to the next chapter, we’re going to quickly introduce a couple of helper functions and objects. These helpers make it easier to position objects and see what is happening in a scene. The easiest way to see this in action is to open the chapter-01/porsche.html example in your browser:

Figure 1.15 – Porsche example with helper

Figure 1.15 – Porsche example with helper

On the right-hand side of the screen, at the bottom of the menu, you will see three buttons in the controls: Toggle AxesHelper, Toggle GridHelper, and Toggle PolarGridHelper. When you click on any of them, Three.js will add an overlay to the screen that can help you orient and position meshes, determine needed rotations, and check the sizes of your objects. For instance, when we toggle AxesHelper, we will see the x-, y-, and z-axes in the scene:

Figure 1.16 – Porsche example with AxesHelper enabled

Figure 1.16 – Porsche example with AxesHelper enabled

Note that in this example, you can see a more extensive control UI, where you can also control various aspects of WebGLRenderer.

Summary

That’s it for this first chapter. In this chapter, you learned how to set up your development environment, how to get the code, and how to get started with the examples provided in this book. Then, you learned that to render a scene with Three.js, you have to create a THREE.Scene object and add a camera, a light source, and the objects that you want to render. We also showed you how you can expand this basic scene by adding animations. Lastly, we added a couple of helper libraries. We used lil-GUI, which allows you to quickly create control UIs, and we added an FPS counter, which provided feedback on the frame rate and other metrics using which your scene is rendered.

All these items will help you understand the examples in upcoming chapters and make it easier for you to experiment with the more advanced examples and start modifying those to your liking. Should stuff break or not result in what you expect in the next few chapters when you experiment, remember what we showed you in this chapter: use the JavaScript console to get additional information, add debug statements, use the helpers provided by Three.js, or add custom control elements.

In the next chapter, we’ll expand on the basic setup shown here and you’ll learn more about the most important building blocks that you can use in Three.js.

Left arrow icon Right arrow icon
Download code icon Download Code

Key benefits

  • Enhance your 3D graphics with light sources, shadows, advanced materials, and textures
  • Load models from external sources, visualize and, animate them directly using JavaScript
  • Create your own custom WebGL shader, explore Three.js' postprocessing feature, and learn how to integrate with Blender, React, and Typescript

Description

Three.js has become the industry standard for creating stunning 3D WebGL content. In this edition, you’ll learn about all the features of Three.js and understand how to integrate it with the newest physics engines. You'll also develop a strong grip on creating and animating immersive 3D scenes directly in your browser, reaping the full potential of WebGL and modern browsers. The book starts with the basic concepts and building blocks used in Three.js and helps you explore these essential topics in detail through extensive examples and code samples. You'll learn how to create realistic-looking 3D objects using textures and materials and how to load existing models from an external source. Next, you'll understand how to control the camera using the Three.js built-in camera controls, which will enable you to fly or walk around the 3D scene you've created. Later chapters will cover the use of HTML5 video and canvas elements as materials for your 3D objects to animate your models. You’ll learn how to use morph targets and skeleton-based animation, before understanding how to add physics, such as gravity and collision detection, to your scene. Finally, you’ll master combining Blender with Three.js and creating VR and AR scenes. By the end of this book, you'll be well-equipped to create 3D-animated graphics using Three.js.

What you will learn

Implement the different camera controls provided by Three.js to navigate your 3D scene Discover working with vertices directly to create snow, rain, and galaxy-like effects Import and animate models from external formats, such as glTF, OBJ, STL, and COLLADA Design and run animations using morph targets and bone-based animation Create realistic-looking 3D objects using advanced textures on materials Interact directly with WebGL by creating custom vertex and fragment shaders Make scenes using the Rapier physics engine, and integrate Three.js with VR and AR

Product Details

Country selected

Publication date : Feb 17, 2023
Length 554 pages
Edition : 4th Edition
Language : English
ISBN-13 : 9781803233871
Category :

What do you get with eBook?

Product feature icon Instant access to your Digital eBook purchase
Product feature icon Download this book in EPUB and PDF formats
Product feature icon AI Assistant (beta) to help accelerate your learning
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
Buy Now

Product Details


Publication date : Feb 17, 2023
Length 554 pages
Edition : 4th Edition
Language : English
ISBN-13 : 9781803233871
Category :

Table of Contents

21 Chapters
Preface Chevron down icon Chevron up icon
1. Part 1: Getting Up and Running Chevron down icon Chevron up icon
2. Chapter 1: Creating Your First 3D Scene with Three.js Chevron down icon Chevron up icon
3. Chapter 2: The Basic Components that Make up a Three.js Application Chevron down icon Chevron up icon
4. Chapter 3: Working with Light Sources in Three.js Chevron down icon Chevron up icon
5. Part 2: Working with the Three.js Core Components Chevron down icon Chevron up icon
6. Chapter 4: Working with Three.js Materials Chevron down icon Chevron up icon
7. Chapter 5: Learning to Work with Geometries Chevron down icon Chevron up icon
8. Chapter 6: Exploring Advanced Geometries Chevron down icon Chevron up icon
9. Chapter 7: Points and Sprites Chevron down icon Chevron up icon
10. Part 3: Particle Clouds, Loading and Animating Models Chevron down icon Chevron up icon
11. Chapter 8: Creating and Loading Advanced Meshes and Geometries Chevron down icon Chevron up icon
12. Chapter 9: Animation and Moving the Camera Chevron down icon Chevron up icon
13. Chapter 10: Loading and Working with Textures Chevron down icon Chevron up icon
14. Part 4: Post-Processing, Physics, and Sounds Chevron down icon Chevron up icon
15. Chapter 11: Render Postprocessing Chevron down icon Chevron up icon
16. Chapter 12: Adding Physics and Sounds to Your Scene Chevron down icon Chevron up icon
17. Chapter 13: Working with Blender and Three.js Chevron down icon Chevron up icon
18. Chapter 14: Three.js Together with React, TypeScript, and Web-XR Chevron down icon Chevron up icon
19. Index Chevron down icon Chevron up icon
20. Other Books You May Enjoy Chevron down icon Chevron up icon

Customer reviews

Top Reviews
Rating distribution
Empty star icon Empty star icon Empty star icon Empty star icon Empty star icon 0
(0 Ratings)
5 star 0%
4 star 0%
3 star 0%
2 star 0%
1 star 0%
Filter icon Filter
Top Reviews

Filter reviews by


No reviews found
Get free access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

How do I buy and download an eBook? Chevron down icon Chevron up icon

Where there is an eBook version of a title available, you can buy it from the book details for that title. Add either the standalone eBook or the eBook and print book bundle to your shopping cart. Your eBook will show in your cart as a product on its own. After completing checkout and payment in the normal way, you will receive your receipt on the screen containing a link to a personalised PDF download file. This link will remain active for 30 days. You can download backup copies of the file by logging in to your account at any time.

If you already have Adobe reader installed, then clicking on the link will download and open the PDF file directly. If you don't, then save the PDF file on your machine and download the Reader to view it.

Please Note: Packt eBooks are non-returnable and non-refundable.

Packt eBook and Licensing When you buy an eBook from Packt Publishing, completing your purchase means you accept the terms of our licence agreement. Please read the full text of the agreement. In it we have tried to balance the need for the ebook to be usable for you the reader with our needs to protect the rights of us as Publishers and of our authors. In summary, the agreement says:

  • You may make copies of your eBook for your own use onto any machine
  • You may not pass copies of the eBook on to anyone else
How can I make a purchase on your website? Chevron down icon Chevron up icon

If you want to purchase a video course, eBook or Bundle (Print+eBook) please follow below steps:

  1. Register on our website using your email address and the password.
  2. Search for the title by name or ISBN using the search option.
  3. Select the title you want to purchase.
  4. Choose the format you wish to purchase the title in; if you order the Print Book, you get a free eBook copy of the same title. 
  5. Proceed with the checkout process (payment to be made using Credit Card, Debit Cart, or PayPal)
Where can I access support around an eBook? Chevron down icon Chevron up icon
  • If you experience a problem with using or installing Adobe Reader, the contact Adobe directly.
  • To view the errata for the book, see www.packtpub.com/support and view the pages for the title you have.
  • To view your account details or to download a new copy of the book go to www.packtpub.com/account
  • To contact us directly if a problem is not resolved, use www.packtpub.com/contact-us
What eBook formats do Packt support? Chevron down icon Chevron up icon

Our eBooks are currently available in a variety of formats such as PDF and ePubs. In the future, this may well change with trends and development in technology, but please note that our PDFs are not Adobe eBook Reader format, which has greater restrictions on security.

You will need to use Adobe Reader v9 or later in order to read Packt's PDF eBooks.

What are the benefits of eBooks? Chevron down icon Chevron up icon
  • You can get the information you need immediately
  • You can easily take them with you on a laptop
  • You can download them an unlimited number of times
  • You can print them out
  • They are copy-paste enabled
  • They are searchable
  • There is no password protection
  • They are lower price than print
  • They save resources and space
What is an eBook? Chevron down icon Chevron up icon

Packt eBooks are a complete electronic version of the print edition, available in PDF and ePub formats. Every piece of content down to the page numbering is the same. Because we save the costs of printing and shipping the book to you, we are able to offer eBooks at a lower cost than print editions.

When you have purchased an eBook, simply login to your account and click on the link in Your Download Area. We recommend you saving the file to your hard drive before opening it.

For optimal viewing of our eBooks, we recommend you download and install the free Adobe Reader version 9.