How to Use Metalness Maps in Three.js PBR Materials

In modern 3D web development, achieving realistic surfaces requires Physically Based Rendering (PBR). This article explains how to use a metalness map within a Three.js MeshStandardMaterial to define which areas of a 3D model’s texture are conductive (metallic) and which are dielectric (insulators). You will learn how a metalness map works, how to load it using the TextureLoader, and how to properly configure your material properties to achieve accurate visual results.

Understanding the Metalness Map

A metalness map is a grayscale texture where pixel values determine the metallic properties of a surface: * White (1.0) represents fully conductive, metallic surfaces (such as steel, gold, or copper). * Black (0.0) represents non-conductive, dielectric surfaces (such as wood, plastic, or stone). * Gray values represent transitional states, often used for dirt, dust, or rust covering a metal surface.

In Three.js, these values are multiplied by the material’s overall metalness property.

Step-by-Step Implementation

To apply a metalness map in Three.js, you must load the texture, configure its color space, and assign it to a compatible PBR material like MeshStandardMaterial or MeshPhysicalMaterial.

1. Load the Texture

Use the THREE.TextureLoader to load your grayscale metalness map. Because a metalness map contains mathematical data rather than color information, you must set its color space to THREE.NoColorSpace (or linear filtering) to prevent Three.js from applying gamma correction.

import * as THREE from 'three';

// Initialize the texture loader
const textureLoader = new THREE.TextureLoader();

// Load the metalness map texture
const metalnessMap = textureLoader.load('textures/metalness.jpg');

// Set the correct color space for data textures
metalnessMap.colorSpace = THREE.NoColorSpace;

2. Configure the PBR Material

Create a MeshStandardMaterial and pass the loaded texture to the metalnessMap property. To ensure the map displays correctly, you must set the scalar metalness property to 1.0.

const material = new THREE.MeshStandardMaterial({
    color: 0xaaaaaa,                 // Base color of the material
    metalnessMap: metalnessMap,      // The loaded grayscale map
    metalness: 1.0,                  // Multiplier (must be 1.0 to use the map's full range)
    roughness: 0.2                   // Standard roughness value
});

If the metalness property is set to 0.5, the maximum metalness on the white parts of the map will only reach 50% conductivity. Keeping it at 1.0 ensures the map dictates the exact metallic values of the surface.

3. Pair with Roughness for Realism

Metalness maps work best when paired with a roughnessMap. Metals reflect light differently based on how polished they are. Providing both maps allows you to define shiny metal parts alongside dull, rough non-metal parts on the same 3D mesh.

const roughnessMap = textureLoader.load('textures/roughness.jpg');
roughnessMap.colorSpace = THREE.NoColorSpace;

const pbrMaterial = new THREE.MeshStandardMaterial({
    map: colorTexture,               // Base color texture
    metalnessMap: metalnessMap,
    metalness: 1.0,
    roughnessMap: roughnessMap,
    roughness: 1.0                   // Multiplier for the roughness map
});

By combining these properties, Three.js processes the metalness map to determine the reflectivity and color preservation of light bounces, producing realistic, physically-accurate renders on the web.