5.9 KiB
5.9 KiB
Three.js - Advanced Materials
PBR materials and custom shaders.
MeshStandardMaterial (PBR)
Physically-based rendering with metallic/roughness workflow:
const material = new THREE.MeshStandardMaterial({
color: 0xffffff,
metalness: 0.5, // 0 = dielectric, 1 = metal
roughness: 0.5, // 0 = smooth/shiny, 1 = rough/matte
map: colorTexture, // base color
normalMap: normalTexture, // surface detail
roughnessMap: roughnessTexture,
metalnessMap: metalnessTexture,
aoMap: aoTexture, // ambient occlusion
emissive: 0xff0000, // glow color
emissiveMap: emissiveTexture,
emissiveIntensity: 1.0,
envMap: environmentMap, // reflections
envMapIntensity: 1.0,
alphaMap: alphaTexture, // transparency control
transparent: true,
opacity: 1.0,
side: THREE.DoubleSide, // render both sides
flatShading: false // smooth normals
});
MeshPhysicalMaterial (Enhanced PBR)
Extended PBR with clearcoat, transmission, sheen:
const material = new THREE.MeshPhysicalMaterial({
// All MeshStandardMaterial properties plus:
// Clearcoat (protective layer)
clearcoat: 1.0,
clearcoatRoughness: 0.1,
clearcoatMap: clearcoatTexture,
clearcoatRoughnessMap: clearcoatRoughTexture,
clearcoatNormalMap: clearcoatNormalTexture,
// Transmission (transparency with refraction)
transmission: 1.0, // 0-1, glass-like
thickness: 0.5, // volumetric thickness
ior: 1.5, // index of refraction (glass = 1.5)
// Sheen (fabric-like edge glow)
sheen: 1.0,
sheenRoughness: 0.5,
sheenColor: new THREE.Color(0xffffff),
// Iridescence (rainbow effect)
iridescence: 1.0,
iridescenceIOR: 1.3,
iridescenceThicknessRange: [100, 400],
// Anisotropy (directional reflections)
anisotropy: 1.0,
anisotropyRotation: 0
});
ShaderMaterial (Custom Shaders)
Full control over vertex and fragment shaders:
const material = new THREE.ShaderMaterial({
uniforms: {
time: { value: 0.0 },
color: { value: new THREE.Color(0xff0000) },
texture1: { value: texture }
},
vertexShader: `
varying vec2 vUv;
varying vec3 vNormal;
void main() {
vUv = uv;
vNormal = normalize(normalMatrix * normal);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
uniform float time;
uniform vec3 color;
uniform sampler2D texture1;
varying vec2 vUv;
varying vec3 vNormal;
void main() {
vec4 texColor = texture2D(texture1, vUv);
vec3 light = vec3(0.5, 0.2, 1.0);
float dProd = max(0.0, dot(vNormal, light));
gl_FragColor = vec4(color * dProd * texColor.rgb, 1.0);
}
`,
transparent: true,
side: THREE.DoubleSide
});
// Update uniform in animation loop
material.uniforms.time.value += 0.01;
RawShaderMaterial
Like ShaderMaterial but without Three.js shader injection:
const material = new THREE.RawShaderMaterial({
uniforms: {
// ...
},
vertexShader: `
precision mediump float;
precision mediump int;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
attribute vec3 position;
attribute vec2 uv;
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
precision mediump float;
varying vec2 vUv;
void main() {
gl_FragColor = vec4(vUv, 0.0, 1.0);
}
`
});
Common Shader Patterns
Fresnel Effect
// In fragment shader
float fresnel = pow(1.0 - dot(vNormal, vViewDirection), 3.0);
gl_FragColor = vec4(mix(baseColor, edgeColor, fresnel), 1.0);
Noise/Distortion
// Simple noise function
float noise(vec2 p) {
return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453);
}
// UV distortion
vec2 distortedUV = vUv + vec2(
noise(vUv + time) * 0.1,
noise(vUv.yx + time) * 0.1
);
Scrolling Texture
uniform float time;
varying vec2 vUv;
vec2 scrollUV = vUv + vec2(time * 0.1, 0.0);
vec4 color = texture2D(map, scrollUV);
Material Blending
material.blending = THREE.AdditiveBlending;
// Options:
// THREE.NoBlending
// THREE.NormalBlending (default)
// THREE.AdditiveBlending (glow/light effects)
// THREE.SubtractiveBlending
// THREE.MultiplyBlending
// Custom blending
material.blending = THREE.CustomBlending;
material.blendEquation = THREE.AddEquation;
material.blendSrc = THREE.SrcAlphaFactor;
material.blendDst = THREE.OneMinusSrcAlphaFactor;
Depth & Stencil
// Depth testing
material.depthTest = true;
material.depthWrite = true;
material.depthFunc = THREE.LessEqualDepth;
// Alpha testing (discard transparent pixels)
material.alphaTest = 0.5;
// Render order
mesh.renderOrder = 1; // higher renders later
// Polygonoffset (prevent z-fighting)
material.polygonOffset = true;
material.polygonOffsetFactor = 1;
material.polygonOffsetUnits = 1;
Material Cloning & Disposal
// Clone material
const material2 = material.clone();
// Dispose when done (free GPU memory)
material.dispose();
texture.dispose();
geometry.dispose();
Common Built-in Uniforms
Available in ShaderMaterial (automatic):
// Matrices
uniform mat4 modelMatrix;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat3 normalMatrix;
// Camera
uniform vec3 cameraPosition;
// Attributes (vertex shader)
attribute vec3 position;
attribute vec3 normal;
attribute vec2 uv;
attribute vec2 uv2;
Performance Tips
- Use MeshStandardMaterial for most cases (good balance)
- MeshPhysicalMaterial is expensive (use sparingly)
- ShaderMaterial requires GPU knowledge
- Avoid transparent materials when possible
- Use alphaTest instead of transparency for cutouts
- Minimize uniform updates
- Share materials between meshes