SPACEto play / pause
Lto go forward
Jto go backward
ARROW UPto increase volume
ARROW DOWNto decrease volume
Fto toggle fullscreen
Mto toggle mute
0 to 9to go to the corresponding part of the video
,to decrease playback speed
;to increase playback speed
Want to learn more?
In this lesson, we will learn how to create a scene like the one on the home page of the Three.js Journey website. We are going to create a small landscape with a path leading to a magical portal with some objects along the way like fences, trees, rocks. When you are done, you will be able to use what you've learned to create rooms like the ones on Three.js Journey. Or anything else!
And, to make our scene look its best, we are going to use a technique called baking.
When you do a render in a 3D software like Blender, it usually looks better than the model you import into Three.js, no matter how hard you try to get the exact same lighting and colors. This is because of the technique used while making the render.
Ray Tracing consists of casting multiple rays toward each pixel of the render. These rays start with the geometry we are rendering. Next, they test the direction of each light in the scene to see which part of the geometry is illuminated as well as to test whether the directions of the light bouncing off the geometry are colliding with other objects in the scene. Then, for each of these collisions, more rays are being cast as they bounce off other objects. And it goes on and on like this multiple times. All of the information collected by these collisions is then computed to define the final color of that pixel.
The goal is to simulate real-life lighting and enable visual effects like indirect lighting and soft shadows. As an example, if you place a red object close to a white object, you'll see the white object being tinted with red because rays are bouncing from the red surface to the white surface. In the same way, you'll see that the red object looks brighter when the surface is close to the white object.
This process results in a beautiful realistic render, but doing one render can take many minutes, even hours.
When we are doing renders with WebGL, we need to do it as fast as possible in order to get a good frame rate. We don't have the luxury to spend minutes on just one render. For this reason, rendering in WebGL uses cheaper techniques that don't look as good but at least keep a decent frame rate.
The idea of baking is that we save those Ray Tracing renders into textures that we then use in WebGL instead of using the classic render techniques provided by Three.js.
Here is an example of baked texture:
And here is the result in Three.js:
There is no light, no real-time shadows. It's just the texture you see in the above example being placed on the geometries.
This way, we will see the Ray Tracing renders directly on the Meshes, and it looks awesome. And when we move around the scene, the performance will be great because all we did was to display a texture on a geometry.
Unfortunately, there are some drawbacks:
- We have to bake everything in the 3D software and it's a long process.
- We have to load the textures and if you have a complex scene with a lot of objects, you're going to need a lot of textures. This is bad for loading but it can also result in a short freeze at the beginning of the experience because we need to load those textures into the GPU.
- The lights aren't dynamic. We can't move the lights, and we can't change their intensity or color in real time. We have to do it in the 3D software and re-bake everything.
Choosing to use baking or not is up to you and the project. Keep in mind that you can still mix baked and non-baked materials but it's hard to keep a homogeneous result.
To create that baked scene, we need to go through multiple steps:
- Create the scene in 3D software.
- Optimize all the objects because we need clean geometries and only the surfaces we can see.
- UV unwrap everything.
- Bake the render into texture(s).
- Export both the scene and the texture(s). If we do this, we are going to have just one big texture. But, we can have multiple textures if there are a lot of objects and we want better quality.
- Import everything in Three.js and apply the texture on the mesh.
As a bonus, we will also add some details in Three.js to give more life to the scene like a cool portal effect with fireflies floating around.
We are going to use Blender to create our scene, bake it, and export it.
If you don't know Blender yet, you should follow the previous lesson dedicated to it. Assuming you now know the basics of Blender, the following steps are going to be a little more direct. Nevertheless, each part will be explained. Take your time and make sure to get everything right before moving forward.
If you are familiar with Blender and concepts like UV unwrapping, you can try to diverge from the lesson and create your own scene. If you're not familiar, you should try to follow the steps exactly. Then, once the project is over, you can try on your own and create your dream scene.
In this lesson, I'll be using the
2.92.0 version of Blender, but you'll probably use a more recent version. Keep an eye on potential changes in the interface or in the shortcuts.
To begin, we create a new Blender file. The default setup is the one we defined in the Blender lesson but you can use any setup you like.
If you want the same setup, you can also use the
portal.blend file in the starter:
Point Light is already present in the scene with the following parameters.
If the parameters are different from yours, you might be using
Eeevee as the
Renderer Engine. You can change it now. We will be changing it anyway a little further down.
Start by deleting the default cube or any default object you have in the scene, but keep the light. Use
X to delete objects.
You can now save the file. During the rest of the lesson, remember to save regularly.
We are going to start with the floor.
Create a simple plane with
Shift + A
Scale that plane so that it covers 4 units. You can look at the grid on the floor of the scene to see what 4 units looks like. Also, those units can be anything you want. Actually, you might see something like
4m because your Blender is configured to use meters. This doesn't matter because 4 units in Blender will result in 4 units in Three.js.
To do that, you can change its size in the small menu that shows up when creating it:
You can also scale it using
S after you've created it (you can use
CTRL to round the value):
Or you can go to the
Edit Mode with
TAB and then scale it the same way:
The result will actually be slightly different according to which technique you used. If you scale the object while not using the
Edit Mode, you'll apply a transformation on the object itself and not on the geometry.
This might become a problem later but, later on, we are going to fix it anyway for every object. So use the technique you prefer.
For the first objects in the scene, we can start with the fences. They are simple to create and will give some life to our scene.
We are going to create 2 flat boxes for the poles (posts) and 2 other flat and wide boxes for the planks (rails).
Create the first pole by making a cube with
SHIFT + A. Go into
Edit Mode with
TAB and start scaling it:
If you don't get the exact shape at first, it's not a problem. You can always change it later.
Right now, we are in
Edit Mode and we are going to stay in that mode for the rest of the fence. We can still create primitives and they will count as part of the same geometry. It's not mandatory but it might get handy to have only one geometry for each fence.
While in the
Edit Mode, select the box (if that's not already the case) with
A, duplicate it with
SHIFT + D and move it to the side. You can press
Y right after duplicating it to force the movement on the
Y axis only:
Again, duplicate it with
SHIFT + D, scale it with
S and move it with
G to create the two other planks:
Now that you have all the components of the fence, you can rearrange it any way you want. You can also center the whole geometry so that the origin (the small orange dot) is roughly at the bottom center of the fence:
Once you are happy with the result, leave the
Edit Mode by pressing
You can now duplicate the fence to create 6 fences with
SHIFT + D. Make sure you are in
Object Mode and add some randomness to their position and rotation:
As always, don't spend too much time on positioning stuff. You can always do that later once you have all the objects.
How to use it
(if your browser detects a menace, do not worry, it is not)
- Unzip it
- Open your terminal and go to the unzip folder
npm installcommand to install dependencies
npm run devto launch the local server
(your browser should start automatically)
You can now start coding.
- The JS is located in
- The HTML is located in
- The CSS is located in
Any trouble? Go to the discord server: