Command Palette

Search for a command to run...

Hectal
Course outline
Topic 5.3Intermediate ~18 min · step 3 of 7

PBR: Metalness and Roughness

In one line

Physically based rendering describes a surface with two numbers, metalness and roughness, and lights it with rules from real optics. You learn what each number does, why metal needs something to reflect, and what clearcoat adds for car-style paint.

0/7 · 0%

Think of it like this

A mirror, a painted wall and a steel spoon sit in the same kitchen light but look different for two reasons. Is the surface a metal? Is it polished (sharp reflections) or rough (blurred ones)? Those are the two PBR questions.

Words you'll meet

New words in this topic, in plain English. Come back here whenever one feels fuzzy.

PBR
Physically based rendering: describing a surface with real-world quantities, such as roughness and metalness, and lighting it with rules from optics.
roughness
How blurred a surface's reflections are, from 0 (polished) to 1 (very rough).
metalness
Whether a surface is a metal (1) or not (0). Metals have no diffuse colour, only tinted reflections.
environment
An image of the surroundings. Surfaces reflect it and are lit by it. In three.js: scene.environment.

Step by step

01Meet the grid

The widget shows 25 balls of the same colour. Metalness grows from 0 on the left to 1 on the right and roughness from 0 at the top to 1 at the bottom. Switch scene.environment off: the metal column goes almost black (only a small highlight of the one directional light is left).

02Three balls, one light

The first example has only an AmbientLight. It prints the middle pixel of three balls (metalness 0, 0.5, 1), first with no environment and then with one built from three.js's RoomEnvironment.

03Read the numbers

Without an environment the metal ball is 0,0,0. With it, all three balls are bright orange (255,169,99, 255,200,115, 255,192,85) because the image gives them something to reflect.

04A real environment

The second example loads the course's studio image /data/3d/hdr/studio_small_08_1k.hdr with HDRLoader, turns it into a PMREM texture and sets scene.environment. A wrong file name is a rejected promise: it is caught and printed first.

Try it yourself

  1. 1

    Brighten the ambient light

    In the first example change the ambient intensity from 1.5 to 5. The no environment row becomes 255,130,55, 227,94,38, 0,0,0: the paint ball gets brighter, the metal ball stays 0,0,0. Light with no direction cannot be reflected.

  2. 2

    Change the paint's roughness

    In the second example change the first ball's roughness: 0.8 to 0.1: the matt ball with no visible highlight gets two small, sharp bright windows (the studio's lamps).

Code & diagrams

Try it: interactive

PBR material grid

Switch the environment off to see why metal goes black, then switch clearcoat on and compare the top-left ball.

Metal with and without an environment New tab

Only an AmbientLight lights this scene. The environment comes from RoomEnvironment, built into three.js, so nothing is downloaded.

idle

Console

Run the scene to see its console.

Expected console output

no environment   metalness 0: 180,73,28   metalness 0.5: 132,52,17   metalness 1: 0,0,0
with environment metalness 0: 255,169,99   metalness 0.5: 255,200,115   metalness 1: 255,192,85
The studio image, clearcoat, and a wrong file name New tab

The first load asks for a file that does not exist and prints the 404. Then the real image loads. Left to right: rough paint, glossy paint, car paint (clearcoat), brushed metal. There are no lights: the environment is the only light.

idle

Console

Run the scene to see its console.

Expected console output

wrong path: fetch for "/data/3d/hdr/missing.hdr" responded with 404: Not Found
HDR image: 1024 x 512 pixels, type half float
environment set: true

Break it on purpose

Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.

Break #1

Forget the environment on a metal

In the second example, delete the scene.environment = ... line.

terminal
$ Run
── what you'll see ──
environment set: false
All four balls are black. In a measured run the middle of the paint ball and of the metal ball were both `0,0,0`.

Myth vs fact

Myth

A metal ball is shiny because of its colour.

Fact

It is shiny because of what it reflects. Put a metal ball in an empty scene and it is black, whatever its colour.

Pro corner

Extra depth for experienced readers. New to this? Skip it for now and come back later.

  • ▸

    The specular part of a three.js PBR material uses a GGX distribution (how bumps are spread), a Smith visibility term (bumps shading each other) and Fresnel (surfaces reflect more at grazing angles).

  • ▸

    PMREMGenerator.fromEquirectangular renders a cube map and blurs it on the GPU. Do it once, then dispose() the generator (the example does) and the source image. The resulting texture is what you keep, and it lives in GPU memory (Phase 6 counts texture memory).

Remember this

  1. 1

    The problem this solves: older materials had arbitrary numbers (shininess 30, specular colour) that looked right in one scene and wrong in another. PBR (physically based rendering) uses numbers that mean something, so a material built once looks believable in any light.

  2. 2

    Roughness (0 to 1). 0 is a polished surface: a small, sharp reflection. 1 is a very rough one: the reflection spreads out and dims. Think of it as how many tiny bumps the surface has, too small to see. Most paint is 0.3 to 0.6.

  3. 3

    Metalness (0 to 1). In practice it is 0 or 1. A non-metal (plastic, paint, wood) shows its colour as diffuse light and adds a faint white reflection. A metal has no diffuse light at all: it only reflects, and the reflection is tinted by the metal's colour. In-between values are for edges of rust or dirt on a texture, not for a material.

  4. 4

    Energy conservation. A PBR surface can never send out more light than it receives. When the reflection gets stronger, the diffuse part gets weaker. This is why changing roughness changes the look without making the surface suddenly too bright.

  5. 5

    Metal needs something to reflect. A metal's reflection of a plain AmbientLight is black: ambient light has no direction to reflect. The first example prints it: with metalness 1 and only an ambient light, the pixel is 0,0,0, and raising the ambient light to 5 does not change that. The fix is an environment: an image of a room that every surface reflects (scene.environment).

  6. 6

    **MeshPhysicalMaterial adds layers.** clearcoat puts a thin glossy lacquer over the paint (car paint), with its own clearcoatRoughness. sheen is the soft edge glow of cloth. transmission lets light pass through glass. Each layer adds shader work, so use them only where they show.

Explain it without notes

01

Why is a metal ball black under an AmbientLight, and what are two ways to fix it?

02

What do metalness and roughness each control, and why does roughness not make a surface darker overall?

Practice

01

Build a chrome bell: a sphere that looks like polished metal using the course's studio image. Write the setup.

02

Make the paint ball look like car paint with a lacquer that is sharper than the paint under it.

Done when you can

  • Say what roughness and metalness each mean

  • Say why a metal is black without an environment

  • Set up an environment with HDRLoader and PMREMGenerator

  • Say what clearcoat adds and what it costs