00:00/00:00TIME LEFT
Choosing the a bcd
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

Want to learn more?

That's the end of the free part 😔

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

12.

Materials

Difficulty Hard

Downloads

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:34

The starter doesn't contain any object. This is an excellent occasion to revise the basics of creating Meshes.

Prepare our scene 02:03

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 support adding multiple objects at once:

/**
 * Objects
 */
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 on 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.

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 on 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')

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 a texture on 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.

MeshBasicMaterial 15:40

MeshBasicMaterial is probably the most "basic" material... But there are multiple properties that we haven't cover yet.

You can set most of those properties while instancing the material in the object we send as a parameter, but you can also change those properties on the instance directly:

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

// Equals
const material = new THREE.MeshBasicMaterial()
material.map = doorColorTexture

We will use the second method, but feel free to do as you like.

Map

The map property will apply a texture on the surface of the geometry:

material.map = doorColorTexture

Color

The color property will apply a uniform color on the surface of the geometry. When you are changing the color property directly, you must instantiate a Color class. You can use many different formats:

material.color = new THREE.Color('#ff0000')
material.color = new THREE.Color('#f00')
material.color = new THREE.Color('red')
material.color = new THREE.Color('rgb(255, 0, 0)')
material.color = new THREE.Color(0xff0000)

Combining color and map will tint the texture with the color:

material.map = doorColorTexture
material.color = new THREE.Color('#ff0000')

Wireframe

The wireframe property will show the triangles that compose your geometry with a thin line of 1px regardless of the distance of the camera:

material.wireframe = true

Opacity

The opacity property controls the transparency but, to work, you should set the transparent property to true to inform Three.js that this material now supports transparency:

material.transparent = true
material.opacity = 0.5

AlphaMap

Now that the transparency is working, we can use the alphaMap property to control the transparency with a texture:

material.transparent = true
material.alphaMap = doorAlphaTexture

Side

The side property lets you decide which side of a face is visible. By default, the front side is visible (THREE.FrontSide), but you can show the backside instead (THREE.BackSide) or both (THREE.DoubleSide):

material.side = THREE.DoubleSide

You should see both the front and the back of the plane.

Try to avoid using THREE.DoubleSide because rendering both sides means having twice more triangles to render.

Some of these properties like wireframe or opacity can be used with other types of materials. We won't repeat those every time.

Want to learn more?

That's the end of the free part 😔

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

How to use it

  • Download the Starter pack or Final project
    (if your browser detects a menace, do not worry, it is not)
  • Unzip it
  • Open your terminal and go to the unzip folder
  • Run npm install command to install dependencies
  • Run npm run dev to launch the local server
    (your browser should start automatically)

You can now 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

Any trouble? Go to the discord server: