I have been wanting to write a series of posts on three.js for a while now, and I do not care to put it off any longer. I have fiddled with three.js in the past, but never really got into it, that is until now. I have enough experience with it to know that it helps making projects that involve 3d objects very easy, yet it is still something that takes a significant investment of time to get fairly solid with. Also there is not just what there is to know about the various feature of the library, but also what there is to known when it comes to working with 3d in general. For example when it comes to really getting into 3d at some point sooner or later I am going to want to also get into using blender as a way to go about making external files that I can then load into a scene.
There is a lot that should be covered first before moving on to three.js, and I do not think I can cover all of it in a single blog post such as this. However I will try my best to cover at least some of the most impotent topics that one should know about before getting started with three.js.
One thing that I think should be worth mentioning is that three.js and any additional assets should be hosted via http rather than the file protocol. In other words it is not a good idea to just copy and past files into a folder and then open up an index html file in a browser by way of ctrl + o. It is then a good idea to host what is being worked on via http, even when working on it locally.
Three.js is a project where the version number matters a lot, very significant changes are still being made all the time. When I first wrote this post I was using version r91, and the last time I cam around to do a little editing I was using version r127.
It seems like new revisions come out as often as once a month, and when they do there are a whole lot of changes. So I decided to structure things in a way in which I can make demos for each revision when I am working out my source code demos in my git hub repo where I store the source ode examples for this post.
Although it is not required for getting started at least, at some point you might want to install a 3d modeling program of some kind such as blender. As you get into the depth of three.js there will come a time where you will want to create assets externally, and then import theme into three.js. There are official plug-ins for doing so, and the best supported and easiest to use one I have found is the one for blender.
So three.js is very much a front end resource, so installing will not likely involve npm, unless you want to do something involving webpack in which I guess it would involve npm. For me I did not use any package manager, and I wanted to set up a situation in which I have multiple versions of three.js in a name space, so I just grab versions of three.js manually from the github repo, and pasted them in all low tech like.
In my test threejs Github repository I have the source code examples that I am using for this post. In time I aim to hav a corresponding for post folder for each of my threejs posts as I get around to editing each of my older threejs posts.
This is one of the first blog posts that I have wrote on threejs way back in 2018, at that time I was using r91 of the library. The last time I came around to do a little editing I made some major changes to the examples here and they are working fine with r140 of the library. Although I do what I can to keep my content on threejs up to date, many of the posts might still be a bit dated. Always be mindful of what version of threejs you are using as this is still a fast moving project.
Three.js will contain a whole lot of constructors that each have a certain importance. There is no way that I can even touch base on all of them, let alone do them justice without having this starting to resemble a dissertation rather than a blog post.
However it is possible to touch base on all of the constructors that will be in use in just about any three.js project, including the most basic examples.
As such a three.js project will typically always contain at least one of the following:
- An instance of THREE.Scene
- At least one camera typically THREE.PerspectiveCamera
- There will need to be a renderer such as with THREE.WebGLRenderer
- A Mesh that will contain a Geometry, and a Material. Such as with THREE.Mesh, THREE.BoxGeometry, and THREE.MeshBasicMaterial.
In any case you want to get three.js available in the browser one way or another, including the plain old simple way of having a script tag linking to the location of three.js. In addition you might want some kind of container element in your layout where you will inject the dom element created by the renderer that is used, unless you are okay with just appending to body.
As such the html of one of my demos looks like this for the moment.
A very typical example for getting started with three.js indeed, but still it works to cover the basics of everything if you are new to three.js. Every project will involve a scene, a camera, at least one Object to look at which will be a mesh composed of a geometry, and a material. Also in order to actually see anything you will also need a render as well. That may seem like a lot at first, but once you get into this it all starts to make sense. Trust be this is one of the easiest ways to get into working with 3d objects, and can become a whole lot of fun if you give it a chance.
This example will just draw a cube on the screen. So lets have a break down on everything that is going on here.
Full post on Scene
The Scene is the space in which everything will go, your objects, cameras, and anything else that would be placed in a scene like a light source. Once you have a scene we will want to add things into it, like an object of some kind to look at with a camera.
To do this I will want to call the Object3D add method, and give it a Mesh, that is composed of a Geometry, and a Material. I will touch base on all of that, because you should have at least a basic knowledge of all of those things, but not get into depth here, as each of these things could use there own posts.
Full post on Camera
There is a core class Called Camera that has some methods and properties that are shared across all camera types that are used in three.js.
Like most objects in three.js, a Camera inherits from Object3D which gives it methods to help make changing the position, and orientation of the Camera pretty easy.
There are then four camera types to choose from, in this post I am only briefly covering the perspective camera.
To make some kind of object to look at I need it’s geometry, I will also want to skin that geometry with some kind Of Material, and I will want to tie those two things together into a Mesh. In the example in this Post I used BoxGeometry to quickly create a Cube, and Just a basic Material with a Mesh.
In order to see anything I will need to render it using something like Canvas, or webGL. In this post I just used the webGL renderer, but there are additional renderer’s available in three.js, such as the canvas renderer that uses the 2d drawing context. That will be a lot slower, but it will give greater support on platforms that do not support webGL that well.
I am of course going to want to have at least one simple animation loop example for this getting started post, I just have to do that. Thinking back to when I was first starting out with this library, yeah that was a must. With that said there are a few things to be aware of when it comes to creating a basic animation loop, not just with threejs, but in general when it comes to any kind of canvas project. For one thing the method that is general used is the requestAnimationFrame method, rather than one of the alternatives methods such as setTimeout.
For a basic animation loop example I then took the source code for the general overview example that I start this post with, and just added an animation loop function at the end. There are a number of things that I could do inside the body of the animation loop function, but because this is a getting started post for now I am just updating the instance of THREE.Euler stored at the rotation property of the mesh object to create a simple rotation effect.
For this animation loop example I have two values for FPS, one of which will be used to set the target rate at which the update method will be called. The other FPS rate is used to update the rate at which a frame value will be stepped that will be used to update the state of things in the update method. This allows for me to set the rate at which the update method is called at a low rate as only about 12 frames per second, while updating the frame rate that is used to update state at a rate that is say 30 frames per second. For certian projects in which I am doing something in real time in a web page I might want to make a user interface that will allow the user to adjust the rate at which updating happens to allow them to set how much CPU overhead they would like to use or not.
Three.js is the kind of library where you really need to devote at least a solid month or more in order to start to get a little solid with it. I am still learning myself, but I think there are some additional aspects of this library that are very important, while others are kind of optional depending on the kind of projects I aim to make. For example if I want to make games I might want to know about the lambert material, as it is more efficient then the standard material. However if I aim to make something that does not need to run in real time I might choose to go with the standard material, as it gives a more realistic look.
I first wrote this post back in April of 2018, and as of this writing it is now February of 2022. Sense I first started this post much has changed with three.js sense then, and with that said I will continue to update this post when I get some time to do so. As my content on three.js grows, and I edit posts such as this one, I often will link to this post as a way to just pipe people to something that is a good starting point for threejs.
If you are still fairly new to three.js but have some of the basics worked out maybe it would be a good idea to work out a whole bunch of examples where you are just using the Box Geometry Constructor. There is not just having a Cube on the screen, but doing a whole word of things with that cube. For example there is moving it, rotating it, using an array of materials rather than just one, changing what the index values are for those materials, doing things with light and shadow and so forth. With that said maybe my post on the Box Geometry Constructor will be a good next step from here.
A real good class to start really learning a thing ot two about would be the Object3D class, I wrote a post on Object3D, and there is also of course the official docs on Object3D. This is not something that you typically work with directly, but is a class that is used in many of the objects in three.js that helps to make working with three.js easy. It gives Objects like Camera, and Mesh methods like lookAT, and position.set.
Read my full post on Vector3
Another class of interest that you should at least be aware of is vector3, This is what you want to use when defining a point in 3d Space.
In the long run thought of course what really needs to happen sooner or later is to start making one or two real examples using three.js. That is some kind of game or animation type thing typically, so with that said maybe another step forward would be to look at some of my basic project examples.
For now I will cover some additional corners of three.js that I think stand out…