threejs-materials
cloudai-x/threejs-skills
PBR, Phong, and custom shader materials for Three.js meshes and textures.
What is threejs-materials?
Comprehensive guide to Three.js material types including physically-based rendering (MeshStandardMaterial), traditional lighting models (Phong, Lambert), and advanced effects (clearcoat, transmission, iridescence). Use when styling 3D meshes, applying textures, creating custom shaders, or optimizing material performance.
- Apply 10+ material types: Basic, Lambert, Phong, Standard (PBR), Physical, Toon, Normal, Depth, Points, and Lines
- Configure physically-based rendering with roughness, metalness, and environment maps
- Create advanced effects: clearcoat, glass transmission, iridescence, anisotropy, and sheen
- Use texture maps: color, normal, roughness, metalness, displacement, ambient occlusion, and emissive
- Write custom GLSL shaders with ShaderMaterial and RawShaderMaterial
- Optimize material properties: wireframe, flat shading, fog, and transparency
How to install threejs-materials
npx skills add https://github.com/cloudai-x/threejs-skills --skill threejs-materialsHow to use threejs-materials
- 1.Choose a material type based on your use case (Basic for unlit, Standard for realistic, Physical for advanced effects)
- 2.Create the material with appropriate properties (color, roughness, metalness, etc.)
- 3.Attach textures if needed (map, normalMap, roughnessMap, etc.)
- 4.For aoMap, ensure geometry has a second UV channel via geometry.setAttribute('uv2', geometry.attributes.uv)
- 5.Create a mesh with THREE.Mesh(geometry, material) and add to scene
- 6.Update uniforms in animation loop if using ShaderMaterial or time-dependent properties
Use cases
- Render realistic car paint with clearcoat and metallic properties
- Create glass or water materials with transmission and refraction
- Build cel-shaded cartoon scenes with MeshToonMaterial
- Visualize point clouds with PointsMaterial and per-vertex colors
- Debug surface normals and depth values during development
- 3D graphics developers
- Game developers using Three.js
- WebGL/web3D engineers
- Visual effects and shader programmers
- 3D visualization specialists
threejs-materials FAQ
Use MeshStandardMaterial for most realistic PBR needs. Use MeshPhysicalMaterial only if you need advanced features like clearcoat, transmission (glass), iridescence, or anisotropy.
Ambient occlusion maps require a second UV channel. Add it with: geometry.setAttribute('uv2', geometry.attributes.uv)
Use MeshPhysicalMaterial with transmission: 1, thickness: 0.5, ior: 1.5, and roughness: 0 for clear glass.
normalMap directly encodes surface normals (more accurate), while bumpMap uses grayscale height to simulate normals (less accurate but cheaper).
Yes, use ShaderMaterial for custom GLSL with Three.js uniforms, or RawShaderMaterial for full shader control without Three.js helpers.
Full instructions (SKILL.md)
Source of truth, from cloudai-x/threejs-skills.
name: threejs-materials description: Three.js materials - PBR, basic, phong, shader materials, material properties. Use when styling meshes, working with textures, creating custom shaders, or optimizing material performance.
Three.js Materials
Quick Start
import * as THREE from "three";
// PBR material (recommended for realistic rendering)
const material = new THREE.MeshStandardMaterial({
color: 0x00ff00,
roughness: 0.5,
metalness: 0.5,
});
const mesh = new THREE.Mesh(geometry, material);
Material Types Overview
| Material | Use Case | Lighting |
|---|---|---|
| MeshBasicMaterial | Unlit, flat colors, wireframes | No |
| MeshLambertMaterial | Matte surfaces, performance | Yes (diffuse only) |
| MeshPhongMaterial | Shiny surfaces, specular highlights | Yes |
| MeshStandardMaterial | PBR, realistic materials | Yes (PBR) |
| MeshPhysicalMaterial | Advanced PBR, clearcoat, transmission | Yes (PBR+) |
| MeshToonMaterial | Cel-shaded, cartoon look | Yes (toon) |
| MeshNormalMaterial | Debug normals | No |
| MeshDepthMaterial | Depth visualization | No |
| ShaderMaterial | Custom GLSL shaders | Custom |
| RawShaderMaterial | Full shader control | Custom |
MeshBasicMaterial
No lighting calculations. Fast, always visible.
const material = new THREE.MeshBasicMaterial({
color: 0xff0000,
transparent: true,
opacity: 0.5,
side: THREE.DoubleSide, // FrontSide, BackSide, DoubleSide
wireframe: false,
map: texture, // Color/diffuse texture
alphaMap: alphaTexture, // Transparency texture
envMap: envTexture, // Reflection texture
reflectivity: 1, // Env map intensity
fog: true, // Affected by scene fog
});
MeshLambertMaterial
Diffuse-only lighting. Fast, no specular highlights.
const material = new THREE.MeshLambertMaterial({
color: 0x00ff00,
emissive: 0x111111, // Self-illumination color
emissiveIntensity: 1,
map: texture,
emissiveMap: emissiveTexture,
envMap: envTexture,
reflectivity: 0.5,
});
MeshPhongMaterial
Specular highlights. Good for shiny, plastic-like surfaces.
const material = new THREE.MeshPhongMaterial({
color: 0x0000ff,
specular: 0xffffff, // Highlight color
shininess: 100, // Highlight sharpness (0-1000)
emissive: 0x000000,
flatShading: false, // Flat vs smooth shading
map: texture,
specularMap: specTexture, // Per-pixel shininess
normalMap: normalTexture,
normalScale: new THREE.Vector2(1, 1),
bumpMap: bumpTexture,
bumpScale: 1,
displacementMap: dispTexture,
displacementScale: 1,
});
MeshStandardMaterial (PBR)
Physically-based rendering. Recommended for realistic results.
const material = new THREE.MeshStandardMaterial({
color: 0xffffff,
roughness: 0.5, // 0 = mirror, 1 = diffuse
metalness: 0.0, // 0 = dielectric, 1 = metal
// Textures
map: colorTexture, // Albedo/base color
roughnessMap: roughTexture, // Per-pixel roughness
metalnessMap: metalTexture, // Per-pixel metalness
normalMap: normalTexture, // Surface detail
normalScale: new THREE.Vector2(1, 1),
aoMap: aoTexture, // Ambient occlusion (uses uv2!)
aoMapIntensity: 1,
displacementMap: dispTexture, // Vertex displacement
displacementScale: 0.1,
displacementBias: 0,
// Emissive
emissive: 0x000000,
emissiveIntensity: 1,
emissiveMap: emissiveTexture,
// Environment
envMap: envTexture,
envMapIntensity: 1,
// Other
flatShading: false,
wireframe: false,
fog: true,
});
// Note: aoMap requires second UV channel
geometry.setAttribute("uv2", geometry.attributes.uv);
MeshPhysicalMaterial (Advanced PBR)
Extends MeshStandardMaterial with advanced features.
const material = new THREE.MeshPhysicalMaterial({
// All MeshStandardMaterial properties plus:
// Clearcoat (car paint, lacquer)
clearcoat: 1.0, // 0-1 clearcoat layer strength
clearcoatRoughness: 0.1,
clearcoatMap: ccTexture,
clearcoatRoughnessMap: ccrTexture,
clearcoatNormalMap: ccnTexture,
clearcoatNormalScale: new THREE.Vector2(1, 1),
// Transmission (glass, water)
transmission: 1.0, // 0 = opaque, 1 = fully transparent
transmissionMap: transTexture,
thickness: 0.5, // Volume thickness for refraction
thicknessMap: thickTexture,
attenuationDistance: 1, // Absorption distance
attenuationColor: new THREE.Color(0xffffff),
// Refraction
ior: 1.5, // Index of refraction (1-2.333)
// Sheen (fabric, velvet)
sheen: 1.0,
sheenRoughness: 0.5,
sheenColor: new THREE.Color(0xffffff),
sheenColorMap: sheenTexture,
sheenRoughnessMap: sheenRoughTexture,
// Iridescence (soap bubbles, oil slicks)
iridescence: 1.0,
iridescenceIOR: 1.3,
iridescenceThicknessRange: [100, 400],
iridescenceMap: iridTexture,
iridescenceThicknessMap: iridThickTexture,
// Anisotropy (brushed metal)
anisotropy: 1.0,
anisotropyRotation: 0,
anisotropyMap: anisoTexture,
// Specular
specularIntensity: 1,
specularColor: new THREE.Color(0xffffff),
specularIntensityMap: specIntTexture,
specularColorMap: specColorTexture,
});
Glass Material Example
const glass = new THREE.MeshPhysicalMaterial({
color: 0xffffff,
metalness: 0,
roughness: 0,
transmission: 1,
thickness: 0.5,
ior: 1.5,
envMapIntensity: 1,
});
Car Paint Example
const carPaint = new THREE.MeshPhysicalMaterial({
color: 0xff0000,
metalness: 0.9,
roughness: 0.5,
clearcoat: 1,
clearcoatRoughness: 0.1,
});
MeshToonMaterial
Cel-shaded cartoon look.
const material = new THREE.MeshToonMaterial({
color: 0x00ff00,
gradientMap: gradientTexture, // Optional: custom shading gradient
});
// Create step gradient texture
const colors = new Uint8Array([0, 128, 255]);
const gradientMap = new THREE.DataTexture(colors, 3, 1, THREE.RedFormat);
gradientMap.minFilter = THREE.NearestFilter;
gradientMap.magFilter = THREE.NearestFilter;
gradientMap.needsUpdate = true;
MeshNormalMaterial
Visualize surface normals. Useful for debugging.
const material = new THREE.MeshNormalMaterial({
flatShading: false,
wireframe: false,
});
MeshDepthMaterial
Render depth values. Used for shadow maps, DOF effects.
const material = new THREE.MeshDepthMaterial({
depthPacking: THREE.RGBADepthPacking,
});
PointsMaterial
For point clouds.
const material = new THREE.PointsMaterial({
color: 0xffffff,
size: 0.1,
sizeAttenuation: true, // Scale with distance
map: pointTexture,
alphaMap: alphaTexture,
transparent: true,
alphaTest: 0.5, // Discard pixels below threshold
vertexColors: true, // Use per-vertex colors
});
const points = new THREE.Points(geometry, material);
LineBasicMaterial & LineDashedMaterial
// Solid lines
const lineMaterial = new THREE.LineBasicMaterial({
color: 0xffffff,
linewidth: 1, // Note: >1 only works on some systems
linecap: "round",
linejoin: "round",
});
// Dashed lines
const dashedMaterial = new THREE.LineDashedMaterial({
color: 0xffffff,
dashSize: 0.5,
gapSize: 0.25,
scale: 1,
});
// Required for dashed lines
const line = new THREE.Line(geometry, dashedMaterial);
line.computeLineDistances();
ShaderMaterial
Custom GLSL shaders with Three.js uniforms.
const material = new THREE.ShaderMaterial({
uniforms: {
time: { value: 0 },
color: { value: new THREE.Color(0xff0000) },
texture1: { value: texture },
},
vertexShader: `
varying vec2 vUv;
uniform float time;
void main() {
vUv = uv;
vec3 pos = position;
pos.z += sin(pos.x * 10.0 + time) * 0.1;
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}
`,
fragmentShader: `
varying vec2 vUv;
uniform vec3 color;
uniform sampler2D texture1;
void main() {
// Use texture2D() for GLSL 1.0, texture() for GLSL 3.0 (glslVersion: THREE.GLSL3)
vec4 texColor = texture2D(texture1, vUv);
gl_FragColor = vec4(color * texColor.rgb, 1.0);
}
`,
transparent: true,
side: THREE.DoubleSide,
});
// Update uniform in animation loop
material.uniforms.time.value = clock.getElapsedTime();
Built-in Uniforms (auto-provided)
// Vertex shader
uniform mat4 modelMatrix; // Object to world
uniform mat4 modelViewMatrix; // Object to camera
uniform mat4 projectionMatrix; // Camera projection
uniform mat4 viewMatrix; // World to camera
uniform mat3 normalMatrix; // For transforming normals
uniform vec3 cameraPosition; // Camera world position
// Attributes
attribute vec3 position;
attribute vec3 normal;
attribute vec2 uv;
RawShaderMaterial
Full control - no built-in uniforms/attributes.
const material = new THREE.RawShaderMaterial({
uniforms: {
projectionMatrix: { value: camera.projectionMatrix },
modelViewMatrix: { value: new THREE.Matrix4() },
},
vertexShader: `
precision highp float;
attribute vec3 position;
uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
precision highp float;
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`,
});
Common Material Properties
All materials share these base properties:
// Visibility
material.visible = true;
material.transparent = false;
material.opacity = 1.0;
material.alphaTest = 0; // Discard pixels with alpha < value
// Rendering
material.side = THREE.FrontSide; // FrontSide, BackSide, DoubleSide
material.depthTest = true;
material.depthWrite = true;
material.colorWrite = true;
// Blending
material.blending = THREE.NormalBlending;
// NormalBlending, AdditiveBlending, SubtractiveBlending, MultiplyBlending, CustomBlending
// Stencil
material.stencilWrite = false;
material.stencilFunc = THREE.AlwaysStencilFunc;
material.stencilRef = 0;
material.stencilMask = 0xff;
// Polygon offset (z-fighting fix)
material.polygonOffset = false;
material.polygonOffsetFactor = 0;
material.polygonOffsetUnits = 0;
// Misc
material.dithering = false;
material.toneMapped = true;
Multiple Materials
// Assign different materials to geometry groups
const geometry = new THREE.BoxGeometry(1, 1, 1);
const materials = [
new THREE.MeshBasicMaterial({ color: 0xff0000 }), // right
new THREE.MeshBasicMaterial({ color: 0x00ff00 }), // left
new THREE.MeshBasicMaterial({ color: 0x0000ff }), // top
new THREE.MeshBasicMaterial({ color: 0xffff00 }), // bottom
new THREE.MeshBasicMaterial({ color: 0xff00ff }), // front
new THREE.MeshBasicMaterial({ color: 0x00ffff }), // back
];
const mesh = new THREE.Mesh(geometry, materials);
// Custom groups
geometry.clearGroups();
geometry.addGroup(0, 6, 0); // start, count, materialIndex
geometry.addGroup(6, 6, 1);
Environment Maps
// Load cube texture
const cubeLoader = new THREE.CubeTextureLoader();
const envMap = cubeLoader.load([
"px.jpg",
"nx.jpg", // positive/negative X
"py.jpg",
"ny.jpg", // positive/negative Y
"pz.jpg",
"nz.jpg", // positive/negative Z
]);
// Apply to material
material.envMap = envMap;
material.envMapIntensity = 1;
// Or set as scene environment (affects all PBR materials)
scene.environment = envMap;
// HDR environment (recommended)
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader.js";
const rgbeLoader = new RGBELoader();
rgbeLoader.load("environment.hdr", (texture) => {
texture.mapping = THREE.EquirectangularReflectionMapping;
scene.environment = texture;
scene.background = texture;
});
Material Cloning and Modification
// Clone material
const clone = material.clone();
clone.color.set(0x00ff00);
// Modify at runtime
material.color.set(0xff0000);
material.needsUpdate = true; // Only needed for some changes
// When needsUpdate is required:
// - Changing flat shading
// - Changing texture
// - Changing transparent
// - Custom shader code changes
Performance Tips
- Reuse materials: Same material = batched draw calls
- Avoid transparent when possible: Transparent materials require sorting
- Use alphaTest instead of transparency: When applicable, faster
- Choose simpler materials: Basic > Lambert > Phong > Standard > Physical
- Limit active lights: Each light adds shader complexity
// Material pooling
const materialCache = new Map();
function getMaterial(color) {
const key = color.toString(16);
if (!materialCache.has(key)) {
materialCache.set(key, new THREE.MeshStandardMaterial({ color }));
}
return materialCache.get(key);
}
// Dispose when done
material.dispose();
See Also
threejs-textures- Texture loading and configurationthreejs-shaders- Custom shader developmentthreejs-lighting- Light interaction with materials
Related skills
More from cloudai-x/threejs-skills and the wider catalog.

threejs-postprocessing
Add bloom, DOF, color grading, and screen-space effects to Three.js scenes via EffectComposer.

threejs-shaders
Write custom GLSL shaders with Three.js ShaderMaterial, uniforms, varyings, and built-in effects.

threejs-textures
Load, configure, and apply textures in Three.js—colors, normals, HDR environments, and render targets.

threejs-animation
Keyframe, skeletal, and morph target animation for Three.js objects and GLTF models.

security-audit
Security guidance and vulnerability review for codebases, APIs, services, and daemons.

agents-sdk
Build and debug Cloudflare Agents SDK applications with persistent state, RPC, scheduling, and MCP integration.