00:00/00:00
3:22
00:03:22

Shortcuts ⌨️

  • SPACE to play / pause
  • ARROW RIGHT or L to go forward
  • ARROW LEFT or J to go backward
  • ARROW UP to increase volume
  • ARROW DOWN to decrease volume
  • F to toggle fullscreen
  • M to toggle mute
  • 0 to 9 to go to the corresponding part of the video
  • SHIFT + , to decrease playback speed
  • SHIFT + . or ; to increase playback speed

Unlock content 🔓

To get access to 72 hours of video, a members-only Discord server, subtitles, lesson resources, future updates and much more join us for only $95!

Want to learn more? 🖖

13%

That's the end of the free part 😔

To get access to 72 hours of video, a members-only Discord server and future updates, join us for only $95!

Next lesson
11.

Materials

Difficulty Hard

Introduction 00:00

Materials are used to put a color on each visible pixel of the geometries.

The algorithms that decide on the color of each pixel are written in programs called shaders. Writing shaders is one of the most challenging parts of WebGL and Three.js, but don't worry; Three.js has many built-in materials with pre-made shaders.

We will discover how to create our own shaders in a future lesson. For now, let's use Three.js materials.

Setup 01:25

The starter doesn't contain any object and you should get a black render. This is an excellent occasion to revise the basics of creating Meshes.

Prepare our scene 01:45

To test the materials, we should prepare a lovely scene and load some textures.

Create 3 Meshes composed of 3 different geometries (a sphere, a plane, and a torus) and use the same MeshBasicMaterial on all of the 3. Yes, you can use one material on multiple meshes. Move the sphere on the left and the torus on the right to separate them.

The add(...) method supports adding multiple objects at once:

/**
 * Objects
 */
// MeshBasicMaterial
const material = new THREE.MeshBasicMaterial()

const sphere = new THREE.Mesh(
    new THREE.SphereGeometry(0.5, 16, 16),
    material
)
sphere.position.x = - 1.5

const plane = new THREE.Mesh(
    new THREE.PlaneGeometry(1, 1),
    material
)

const torus = new THREE.Mesh(
    new THREE.TorusGeometry(0.3, 0.2, 16, 32),
    material
)
torus.position.x = 1.5

scene.add(sphere, plane, torus)

We can now rotate our objects on our tick function, as we did in the Animation lesson:

/**
 * Animate
 */
const clock = new THREE.Clock()

const tick = () =>
{
    const elapsedTime = clock.getElapsedTime()

    // Update objects
    sphere.rotation.y = 0.1 * elapsedTime
    plane.rotation.y = 0.1 * elapsedTime
    torus.rotation.y = 0.1 * elapsedTime

    sphere.rotation.x = 0.15 * elapsedTime
    plane.rotation.x = 0.15 * elapsedTime
    torus.rotation.x = 0.15 * elapsedTime

    // ...
}

tick()

You should see your 3 objects spinning slowly.

Let’s use - 0.15 * elapsedTime for the rotation.x to ensure that they rotate the other way and we appreciate the plane for longer before it disappears:

sphere.rotation.x = - 0.15 * elapsedTime
plane.rotation.x = - 0.15 * elapsedTime
torus.rotation.x = - 0.15 * elapsedTime

The materials we are going to discover are using textures in many different ways. Let's load some textures using the TextureLoader as we did in the Textures lesson.

All the texture images are located in the static/textures/ folder. For now, we will load all the door textures located in the static/textures/door/ folder, the first matcap texture located in the static/textures/matcaps/ folder, and the first gradient texture located in the static/textures/gradients/ folder.

Make sure to do that before instantiating the material:

/**
 * Textures
 */
const textureLoader = new THREE.TextureLoader()

const doorColorTexture = textureLoader.load('./textures/door/color.jpg')
const doorAlphaTexture = textureLoader.load('./textures/door/alpha.jpg')
const doorAmbientOcclusionTexture = textureLoader.load('./textures/door/ambientOcclusion.jpg')
const doorHeightTexture = textureLoader.load('./textures/door/height.jpg')
const doorNormalTexture = textureLoader.load('./textures/door/normal.jpg')
const doorMetalnessTexture = textureLoader.load('./textures/door/metalness.jpg')
const doorRoughnessTexture = textureLoader.load('./textures/door/roughness.jpg')
const matcapTexture = textureLoader.load('./textures/matcaps/1.png')
const gradientTexture = textureLoader.load('./textures/gradients/3.jpg')

As we’ve seen previously, textures used as map and matcap are supposed to be encoded in sRGB and we need to inform Three.js of this by setting their colorSpace to THREE.SRGBColorSpace:

doorColorTexture.colorSpace = THREE.SRGBColorSpace
matcapTexture.colorSpace = THREE.SRGBColorSpace

To ensure that all the textures are well loaded, you can use them on your material with the map property, as we saw in the Textures lesson.

const material = new THREE.MeshBasicMaterial({ map: doorColorTexture })

Until now, we only used the MeshBasicMaterial, which applies a uniform color or texture to our geometry.

If you search for "material" on the Three.js documentation, you'll see that there are many classes we can use. Let's try them.

Want to learn more?

That's the end of the free part 😔

To get access to 72 hours of video, a members-only Discord server and future updates, join us for only $95!

How to use it 🤔

  • Download the Starter pack or Final project
  • Unzip it
  • Open your terminal and go to the unzip folder
  • Run npm install to install dependencies
    (if your terminal warns you about vulnerabilities, ignore it)
  • Run npm run dev to launch the local server
    (project should open on your default browser automatically)
  • Start coding
  • The JS is located in src/script.js
  • The HTML is located in src/index.html
  • The CSS is located in src/style.css

If you get stuck and need help, join the members-only Discord server:

Discord