Three.js and TypeScript
- 8 hours on-demand video
- 10 downloadable resources
- Full lifetime access
- Access on mobile and TV
- Certificate of Completion
Get your team access to 4,000+ top Udemy courses anytime, anywhere.Try Udemy for Business
- Learn the Basics of Threejs with many demonstrations and example code
- Setup a Development Environment using VSCode, Git and NodeJS
- Install TypeScript
- Do a TypeScript mini course learning about Types, Interfaces, Classes and see it run in NodeJS and in the browser.
- Create a Threejs project using NPM and package json
- Import the Threejs libraries into our TypeScript code and serve via our NodeJS server
- Learn about NodeJS, Express and serving ES6 modules to the browser clients.
- Set up NodeJS to auto recompile and generate project code upon changes
- Create (or optionally Install) a Threejs TypeScript Boilerplate for use throughout the course
- Learn about the Threejs Scene, Camera and Renderer
- Learn about the Animation loop
- Learn about the Stats and Dat GUI panels
- Learn about Object3D base class, and the Rotation, Position, Scale, Visibility and Matrix properties
- Learn about Geometries such as Box, Sphere, Icosahedron, Plane, TorusKnot and more
- Learn about the Basic, Normal, Lambert, Phong, Standard, Physical, Matcap and other materials
- Learn about the highlighting options with the SpecularMap, RoughnessMap and MetalnessMap
- Learn about the Bumpmap and Displacement Maps
- Learn about modifying the texture and displacement map UVs using the material options.
- Learn about lighting using the Ambient, Directional, Hemisphere, Point and Spot lights.
- Learn about shadows using both the Perspective and Orthographic shadow cameras.
- Learn about the Orbit, Trackball and Pointerlock mouse and touch interaction controls
- Learn about the model loaders such as the OBJ, MTL, GLTF, DRACO and more
- The Raycaster and how to use it for mouse picking 3D objects in the scene,
- Mipmaps, Custom Mipmaps and Anistropoc Filtering
- Physics with Cannonjs
- The Cannonjs Debug Renderer
- Understanding ConvexPolyhedrons versus Compound Shapes for Collision Detection
- Provision, Deploy and Start our Threejs Projects to a Production server
- Install Nginx Proxy, Point a Domain Name and Install SSL
- And many more very useful examples of Threejs
The course is in 4 main sections,
1. Setting up the development environment and installing TypeScript
2. An quick introduction course to TypeScript suitable for Beginners, which is optional and useful only if you've never seen TypeScript before.
3. Create the Three.js master project template with the client HTML and the NodeJS server that we will use for all the examples in the course.
4. Install the Threejs Course Boilerplate (If you didn't already create it in part 3) and continue with main course content with demonstrations and code examples.
Since this course is written in TypeScript, section 2 and 3 contain very useful information that will help you to understand the additional TypeScript syntax and concepts I use throughout this course much better.
This is a code heavy course, and we want our code to be robust, So we will be writing it in typescript. This will also enable advanced IntelliSense features in our VSCode IDE so that we can quickly see the available methods and properties in our Three.js scripts, and also have extra documentation available to us much quicker.
Install TypeScript globally and confirm which version is installed
$ npm install -g typescript
$ tsc -v
TypeScript 3.7.5 was used during the creation of this course.
Create yourself working a folder somewhere, and next create a new file in it called foo.js
We can run this file directly in Nodejs or include it in a web page, and it will run inside the browser. But this isn't typescript.
Rename the foo.js to foo.ts
We can then compile it
And then we can run it using Node.
That is your very first typescript file.
Initialise the New Project
Open a command prompt and create a new folder on your system somewhere.
$ mkdir Three.js-TypeScript-Tutorial
Initialise the project with NPM
$ npm init
Press enter several times to accept all defaults.
Install Three.js Library
$ npm install three
Create Extra Project Files and Folder structure
This is predominantly a Three.js course, but we are writing the code using TypeScript, and we are also hosting the code though a NodeJS server. So we will also learn about those two things as well and how to merge these three technologies so that they work effortlessly together.
First of all, lets get the server side code running first so that it at least serves some code, and then move onto solving the problems of the client in the next video.
See Video for all npm commands and the order of execution.
The core of Three.js is focused on the most important components of the 3D engine.
Many extra modules such as loaders and controls are part of the examples directory.
If you want to use these extra modules in your project, then you will need to import them separately.
We will use the ES6 import syntax and we will import them from the examples/jsm directory which was installed when we began creating the Three.js Project.
We continue to setup our project, so that any changes we make to the source code are automatically recompiled and servable from the NodeJS server.
When compiling using TSC, when can also set the watch flag so that any changes to the source code are automatically recompiled.
$ tsc -p src/server/ -w
We can host using
$ node dist/server/server.js
The NodeJS doesn't restart when there are changes to the compiled output, so we can install nodemon
$ npm install --save-dev nodemon
Now host the server using
$ nodemon dist/server/server.js
Rather than typing these compile and nodemon commands all the time, we can create a single command to start both processes at the same time.
$ npm install --save-dev concurrently
Add this line to the package.json scripts section
"dev" : "concurrently -k \"tsc -p ./src/server -w\" \"nodemon ./dist/server/server.js\"",
And start using
$ npm run dev
This sections is optional. If you completed all the sections before this, then you already have the project created. The boilerplate is useful if you have chosen to bypass all the preceding sections, or you already completed the course and you want to create a brand new Three.js TypeScript project and you would like to use a pre created project boilerplate to start with.
Three.js, at it's core, is a library that allows you to add and describe data in 3 dimensions, eg, as meshes and lights, and then convert that data into a 2d representation onto a HTML canvas.
Before we can do anything with Three.js, we need 3 things,
In this video, in order to understand these things better, we discuss and experiment with some of the options we have with each of them.
The window.requestAnimationFrame() method tells the browser that you wish to perform an animation and requests that the browser calls a specified function to update an animation before the next repaint. The method takes a callback as an argument to be invoked before the repaint
The number of callbacks is usually 60 times per second, but will generally match the display refresh rate in most web browsers as per W3C recommendation. requestAnimationFrame() calls are paused in most browsers when running in background tabs or hidden <iframe>s in order to improve performance and battery life.
The Dat GUI is another very useful tool that we can use to learn about Three.js as it allows us to quickly add a very basic user interface which allows us to interact with our 3d scene and the objects within it.
The Three.js install includes a copy of dat.gui.module.js so we will use that. And we can also add a copy of the type definitions file.
$ npm install @types/dat.gui
Then copy the file index.d.ts from the node_modules/@types/dat.gui folder into the node_modules/three/examples/jsm/libs folder and rename it to dat.gui.module.d.ts.
The VSCode IDE should now be able to find the types definitions/declarations file for the file listed in the import statement /jsm/libs/dat.gui.module
Object3D is the base class for many objects in Three.js provides methods and properties for manipulating objects in 3D space.
Most common examples are Meshes, Lights, Cameras and Groups of Object3Ds.
The full list of methods and properties can be found in the Three.js documentation at Object3D
In this video I will demonstrate the most common things you will do with an Object3D and that is change,
A list of Three.js objects that derive from the Object3D base class are,
Some of the above classes are also derived from parent classes that derive from the Object3D.
Three.js has many classes for creating common geometries.
Most of the above geometries have a BufferGeometry equivalent constructors. Whether you use the BufferGeometry equivalent constructor is up to you. They are created as buffer geometries behind the scenes anyway. A BufferGeometry is a more efficient way of representing meshes, line, and point geometries since the data is stored in single arrays rather than arrays of Vector3 objects. This means that it is harder to quickly read from a human perspective, but it is faster, in the majority of cases, from the computers perspective.
An introduction to the Three.js Material base class.
All these classes below inherit methods and properties from the Material base class.
In this lecture we experiment with the Three.js MeshPhongMaterial.
It uses the Blinn–Phong reflection model,
It is useful for simulating shiny objects such as polished wood.
It is more computationally-expensive to use than the MeshLambertMaterial, MeshNormalMaterial and MeshBasicMaterial so if performance need to be considered, then one option you have is to only use it when necessary.
The Specular map is a texture image that affects the specular surface highlight, and in the case of the MeshPhongMaterial, it also affects the environment map.
The MeshLambertMaterial, MeshPhongMaterial and the MeshToonMaterial have the SpecularMap option.
To adjust the intensity of the specular surface highlight, then use the materials specular and shininess properties.
To adjust the environment map intensity, use the materials reflectivity property.
A displacement map, is an image that can be used to alter the geometry of a mesh. The value of each pixel is used to change the position of the vertices of the mesh.
Where material textures sit on a geometry can be changed by changing their UV co-ordinates. It can also be stretched, repeated, rotated and offset.
In this video I demonstrate zooming into our 3D world plane by changing the texture UV co-ordinates using the repeat and center material options.
There are various kinds of lights in Threejs.
They all extend from the THREE.Light base class, which in turn also extends from the Object3D base class.
The base class properties
isLight (Read Only)
Lighting gives you many more options to change the appearance of meshes within the scene. Meshes will need materials added to them in order for the lighting adjustments to take effect.
If a scene has no lighting, most materials won't be visible. The meshBasicMaterial, meshNormalMaterial and the MeshMatcapMaterial are self illuminating so they don't need lighting to be visible within a scene, but most of the other materials do, such as the meshLambertMaterial, meshPhongMaterial, MeshStandardMaterial, MeshPhysicalMaterial and MeshToonMaterial.
In these next examples, I will demonstrate how the different lighting affects the different materials.
Lights all objects in the scene equally, except for self illuminating objects such as MeshBasicMaterial, meshNormalMaterial and MeshMatcapMaterial.
Doesn't cast shadows.
Light is spread equally in all directions and distances. So positioning the light different than default position of [0, 0, 0] will make no difference.
Materials won't show shading depending on geometry normals and there will be no specular affect, so meshes in front of other meshes will be invisible if they have identical materials or even a single colour map texture.
distance - Maximum range of the light. Default is 0 (no limit).
angle - Maximum angle of light dispersion from its direction whose upper bound is Math.PI/2.
penumbra - Percent of the spotlight cone that is attenuated due to penumbra. Takes values between zero and 1. Default is zero.
decay - The amount the light dims along the distance of the light.
The PointerLockControls implements the inbuilt browsers Pointer Lock API. It provides input methods based on the movement of the mouse over time (i.e., deltas), not just the absolute position of the mouse cursor in the viewport. It gives you access to raw mouse movement, locks the target of mouse events to a single element, eliminates limits on how far mouse movement can go in a single direction, and removes the cursor from view. It is ideal for first person 3D games, for example.
The OBJ Loader is used for loading 3d models saved in the Wavefront OBJ format.
There are many DCC (Digital Content Creation) tools that can create models in OBJ format.
In Threejs, when importing an OBJ, the default material will be a white meshPhongMaterial so you will need at least one light in your scene.
A loader for loading gLTF models into the Threejs scene.
gLTF is a specification for the efficient transmission and loading of 3D scenes and models.
glTF minimizes both the size of 3D assets, and the runtime processing needed to unpack and use those assets.
A glTF file may contain one or more scenes, meshes, materials, textures, skins, skeletons, morph targets, animations, lights and cameras.
Assets can be provided in either JSON (.gltf) or binary (.glb) format.
In this video I show you how to create a gLTF JSON and Binary file using Blender, import the scene with and without lighting and create shadows.
The DRACO loader is used to load geometry compressed with the Draco library.
Draco is an open source library for compressing and decompressing 3D meshes and point clouds.
gLTF files can also be compressed using the DRACO library, and they can also be loaded using the gLTF loader. We can configure the gLTF loader to use the DRACOLoader to decompress the file in such cases.
Compressed geometry can be significantly smaller, but at the cost of additional decoding time on the client side browser.
Raycasting allows you to create a vector from a 3D point in the scene, and detect which object(s) the vector intersects.
The raycasting class is almost always used for mouse picking objects in the 3D scene.
We can setup the raycaster position and direction using the set or setFromCamera methods and then call its intersectObject or intersectObjects methods to tell us many things about the scene objects that were intersected by the ray, including,
the distance of the intersect from the raycaster position,
the position of the intersection in the 3D scene,
the face of the object that was intersected,
the direction of the faces normal,
the UV coordinate of the intersect on the face
and a reference to the intersected object itself.
A tween (from in-between) is a concept that allows you to change the values of the properties of an object in a smooth way. We can decide how long it should take, and if there should be a delay, and what to do each time the tween is updated, whether it should repeat and other things.
In this lesson, I will demonstrate using a mixture of the concepts demonstrated in the previous lessons GLTF Animations, Raycaster, tween.js and SpotLight Shadow
I will import a GLTF model, import several animations clips, add the RayCaster and tween the location of the GLTF model to the clicked mouse coordinates so that the model animates to the new location.
Animation can also be achieved using a Physics library. I will use Cannon.js. Cannon.js is a rigid body simulation library. It can be used to make objects move and interact in a realistic way and provide collision detection possibilities.
Shape : A geometrical shape, such as a sphere, cube or plane, used for the the physics calculations.
Rigid Body : A rigid body has a shape and a number of other properties used in the calculations such as mass and inertia.
Constraint : A 3D body has 6 degrees of freedom, 3 for position and three to describe the rotation vector. A constraint is a limit on one of the degrees of freedom.
Contact constraint : A type of constraint to simulate friction and restitution. These are like the faces of an object where the constraint is applied.
World : A collection of bodies and constraints that interact together.
Solver : The algorithm that is passed over the bodies and constraints to calculate there physical properties and adjust them accordingly.
Collision detection algorithms determine what pairs of objects may be colliding. Collision detection is a computationally expensive process, so various methods can be used to simplify the collision detection.
Narrowphase : Outright body vs body collision detection. This is the most computationally expensive.
Broadphase : Is a compromise on Narrowphase where various techniques can be used to improve collision detection performance.
Cannonjs provides several options for broadphase detection.
NaiveBroadphase : Default. The NaiveBroadphase looks at all possible pairs without restriction, therefore it has complexity N^2. It is similar to the Narrowphase technique, except it decides first whether objects are close enough before checking if there bodies touch. NaiveBroadphase is the default and is suitable for the most common use cases, but becomes less performant if there are many objects in the physics world.
SAPBroadphase : The Sweep and Prune algorithm sorts bodies along an axis and then moves down that list finding pairs by looking at body size and position of the next bodies. For best performance, choose an axis that the bodies are spread out more on. Set to 0 for X axis, and 1 for Y axis. Default axisIndex is 0 (X axis).
GridBroadphase : Axis aligned uniform grid broadphase. Divides space into a grid of cells. Bodies are placed into the cells they overlap and bodies in the same cell are paired. GridBroadphase needs to know the size of the space ahead of time. Set number of cells when you create the object. Default number of cells is X = 10, Y = 10, Z = 10.
In this video I will demonstrate several different methods of creating collision boundaries, also sometimes called collision meshes, using various ConvexPolyhedrons and Compound Shapes. I will also compare the performance and differences between them.
When positioning the parts of a compound shape, you can use a 3d graphics tool to help estimate the positioning. It is is important to know though, that if you use Blender, then be aware that Blender, by default, uses a different coordinate system. In Blender, Z is UP, and the Y axis is used for Near/Far and it is also negative compared to Threejs. So you will need to swap around the coordinates for Y and Z and negate the new Z.
Eg, If the 3D coordinates in Blender are [1,2,3], then in Threejs, the equivalent is [1,3,-2]
In this next several lessons, I will show you how to deploy your Threejs project to a production server on the internet.
The next lessons will cover,
Create the Start Script in the package.json
Provision a Cloud Server for Production
Deploy Files to the Server
Start the Games on the server
Set up an Nginx Proxy
Set up and Point a Domain Name
Install an SSL certificate
At the end, our Threejs project, developed using TypeScript, will be officially on the internet for the public to see.
You can use any example from any section of the course as your project to deploy. Or even a project that you've written yourself along the way.
For this example, I will use the code from the ballgame branch of my Three.js-TypeScript-Boilerplate.
The ballgame branch is a good example to use since it is significantly more sophisticated that the default boilerplate master branch.
Some of the features of The ballgame branch are
It uses the familiar Boilerplate Client and Server TypeScript structure with the Nodejs server
It is a multiplayer game
It demonstrates server side Cannonjs physics
It uses SocketIO for the game multiplayer communications
It demonstrates using several materials including the MeshMatcapMaterial, MeshBasicMaterial and MeshPhongMaterial with environment maps.
It demonstrates the Reflector object used for the floor mirror effect
It demonstrates the CubeCamera which can also be used for more realistic reflections
It demonstrates loading a pre built 3d model
It demonstrates a Custom Camera controller which is a cross between the Orbit and trackball controls.
It demonstrates modifying the UI in case of Desktop or Mobile browser. (PointerLock API or XYControllers)
All these things together make a much more impressive Threejs project that demonstrates many of the considerations needed when building a Threejs project from the ground up.
When running on production, we don't need to use nodemon, concurrently or have TSC watching our source code for any changes we make to the files.
We can create a more simplified starting script that will just start the main server.js in NodeJS.
I want a publicly accessible server on the internet so that I can share my game with the public and my friends.
I will use a Linux server with the Ubuntu 20.04 LTS operating system and It will be setup using Digital Ocean (FREE $50 - 30 Day Credit) as the cloud provider.
We could get an internet connected server from many different cloud providers, such as GCP, Azure, AWS, Hetzner, and many many more.
On Digital Ocean, I will use choose the $5 a month Standard Ubuntu 20.04 64 bit LTS.
If you register using my link https://m.do.co/c/23d277be9014, you will get $50 worth of Credit for 30 days, and often the deal can be even better. So be sure to check just in case.
We first should SSH onto our new server.
On Windows we can use Putty as our SSH client. SSH means 'Secure Shell'.
Download and Install Putty, and add your server to the Session configuration page.
Now connect to your brand new server.
First thing to do, is to run apt-update to ensure that your server has an up to date list of all the latest packages available.
$ sudo apt update
Now to deploy the files using Secure File Transfer Protocol (SFTP).
On windows, you can use WinSCP
Download it from https://winscp.net/eng/index.php and install it.
Add your servers configuration and then connect.
Using the WinSCP explorer interface, navigate to the /var/ folder on your server and create a new folder called www (If it doesn't exist already)
Then create another folder, inside the www called ballgame.your-domain.tld
Now copy your project into the new ballgame.your-domain.tld folder.
You will only need the package.json and the ./dist/ folder and all of it's contents. We do not need the ./src/ folder and any of it's contents since we won't be compiling TypeScript on the server.
Go back to your SSH session in Putty again, and check for npm
$ npm -v
On a new server, it may not be installed, so if it says,
> Command 'npm' not found, but can be installed with: apt install npm
Then we should install npm
$ apt install npm
Now check for npm again
$ npm -v
And you should see a version number displayed.
Navigate into the folder on your new server that contains the package.json
$ cd /var/www/ballgame.your-domain.tld
Now, install the packages from the package.json by using the command,
$ npm install
Now, you can start the The Ball Game game server.
$ npm start
Now open a browser and visit http://[your ip address]:3000
Go back into SSH and press Ctrl-C to stop the server.
We will now start it in a separate screen session so that the nodejs server continues to run in the background when we close our main ssh session.
Navigate to the ballgame folder again while in the new screen session.
$ cd /var/www/ballgame.your-domain.tld
And start the node js server
$ npm start
Press CTRL-A and CTRL-D to detach from the screen session.
The nodejs server is still running in the background and will still continue to run if we close our main SSH session.
To go back into an existing screen session, type
$ screen -r
See video for more details about using screen.
If you want to end and exit a screen session fully so that it no longer is running in the background. Then, while in the screen session, type exit. The screen session will now end and you will not be able to reconnect or reattach to the old session, since it no longer exists, until you create a new session.
Remember, screen is useful when you want your process to continue after you close your main ssh client, putty in our case.
I also want to point a domain name and an SSL certificate to the game server. We can add settings inside our server.js which is being run by NodeJS to manage this, but it is very common to use a proxy instead for this purpose. We can use Nginx. Nginx will be able to manage proxying for all your domain names and SSL certificates for this server, in case you ever want to have several websites running on it.
I have a domain already, and I can add subdomains to it, so I will create a new subdomain, ballgame.sbcode.net.
In my domain name provider, I will create a new A name record called ballgame for my main domain sbcode.net that will point to the IP address of the new server.
Note that you will be using a domain name that you manage and not sbcode.net.
Give it some time to propagate, and then visit
http://ballgame.your-domain.tld or perhaps you just pointed your main domain to your IP address, and you can then access you games without the subdomain, eg,
- A Computer that you can install VSCode, Git and NodeJS
- A desire to code 3D web applications in Threejs and TypeScript
Welcome to my course on Three.js and Typescript.
In this course we will learn all about Three.js, write it in TypeScript, and also write a HTML client and server component using NodeJS.
The course is in 4 main sections,
1. Setting up the development environment and installing TypeScript
2. An quick introduction course to TypeScript suitable for Beginners
3. Creating the three.js master project template with the client HTML and the NodeJS server
4. The main threejs course content with demonstrations and code examples.
If you have experience with TypeScript, then you can skip part 2.
At the beginning of part 4, I also provide a pre created copy of the project template that was created in part 3. So you can also bypass section 3 in case you want to get straight into the details of Threejs.
Since this course is written in TypeScript, section 2 and 3 contain very useful information that will help you to understand the additional TypeScript syntax and concepts I use throughout this course.
All code is provided in the accompanying documentation so that you can easily copy and paste, in case you don't want to pause the video and copy from the screen.
TypeScript introduces type safety in our code which makes it much more robust and gives the IDE extra tools such as intellisence that we can use to help us find and understand the available Threejs properties and methods and code much faster.
Thanks for taking part in my course, and I will see you there.
- People interested in learning Threejs
- People interested in learning TypeScript
- People interested in creating interactive 3D applications, games or visualisations on the web
- People who want to learn enough about Threejs, TypeScript and NodeJS for it to be useful