SKILL.md
唯讀
名稱
threejs-materials
描述
Three.js 材質 - PBR、基本、Phong、著色器材質、材質屬性。用於設定網格樣式、處理紋理、建立自訂著色器或最佳化材質效能。
Three.js 材質
快速開始
import * as THREE from "three";
// PBR 材質(建議用於擬真渲染)
const material = new THREE.MeshStandardMaterial({
color: 0x00ff00,
roughness: 0.5,
metalness: 0.5,
});
const mesh = new THREE.Mesh(geometry, material);
材質類型概覽
| 材質 | 使用情境 | 光照 |
|---|---|---|
| MeshBasicMaterial | 無光照、純色、線框 | 否 |
| MeshLambertMaterial | 霧面表面、效能優先 | 是(僅漫射) |
| MeshPhongMaterial | 光亮表面、鏡面高光 | 是 |
| MeshStandardMaterial | PBR、擬真材質 | 是(PBR) |
| MeshPhysicalMaterial | 進階 PBR、清漆、透射 | 是(PBR+) |
| MeshToonMaterial | 卡通著色、漫畫風格 | 是(卡通) |
| MeshNormalMaterial | 除錯法線 | 否 |
| MeshDepthMaterial | 深度視覺化 | 否 |
| ShaderMaterial | 自訂 GLSL 著色器 | 自訂 |
| RawShaderMaterial | 完全著色器控制 | 自訂 |
MeshBasicMaterial
無光照計算。快速,永遠可見。
const material = new THREE.MeshBasicMaterial({
color: 0xff0000,
transparent: true,
opacity: 0.5,
side: THREE.DoubleSide, // FrontSide, BackSide, DoubleSide
wireframe: false,
map: texture, // 顏色/漫射紋理
alphaMap: alphaTexture, // 透明度紋理
envMap: envTexture, // 反射紋理
reflectivity: 1, // 環境貼圖強度
fog: true, // 受場景霧影響
});
MeshLambertMaterial
僅漫射光照。快速,無鏡面高光。
const material = new THREE.MeshLambertMaterial({
color: 0x00ff00,
emissive: 0x111111, // 自發光顏色
emissiveIntensity: 1,
map: texture,
emissiveMap: emissiveTexture,
envMap: envTexture,
reflectivity: 0.5,
});
MeshPhongMaterial
鏡面高光。適用於光亮、塑膠般的表面。
const material = new THREE.MeshPhongMaterial({
color: 0x0000ff,
specular: 0xffffff, // 高光顏色
shininess: 100, // 高光銳利度(0-1000)
emissive: 0x000000,
flatShading: false, // 平面 vs 平滑著色
map: texture,
specularMap: specTexture, // 逐像素光澤度
normalMap: normalTexture,
normalScale: new THREE.Vector2(1, 1),
bumpMap: bumpTexture,
bumpScale: 1,
displacementMap: dispTexture,
displacementScale: 1,
});
MeshStandardMaterial (PBR)
基於物理的渲染。建議用於擬真效果。
const material = new THREE.MeshStandardMaterial({
color: 0xffffff,
roughness: 0.5, // 0 = 鏡面,1 = 漫射
metalness: 0.0, // 0 = 非金屬,1 = 金屬
// 紋理
map: colorTexture, // 反照率/基底顏色
roughnessMap: roughTexture, // 逐像素粗糙度
metalnessMap: metalTexture, // 逐像素金屬度
normalMap: normalTexture, // 表面細節
normalScale: new THREE.Vector2(1, 1),
aoMap: aoTexture, // 環境光遮蔽(需使用 uv2!)
aoMapIntensity: 1,
displacementMap: dispTexture, // 頂點位移
displacementScale: 0.1,
displacementBias: 0,
// 自發光
emissive: 0x000000,
emissiveIntensity: 1,
emissiveMap: emissiveTexture,
// 環境
envMap: envTexture,
envMapIntensity: 1,
// 其他
flatShading: false,
wireframe: false,
fog: true,
});
// 注意:aoMap 需要第二個 UV 通道
geometry.setAttribute("uv2", geometry.attributes.uv);
MeshPhysicalMaterial (進階 PBR)
擴充 MeshStandardMaterial,加入進階功能。
const material = new THREE.MeshPhysicalMaterial({
// 所有 MeshStandardMaterial 屬性加上:
// 清漆(車漆、亮光漆)
clearcoat: 1.0, // 0-1 清漆層強度
clearcoatRoughness: 0.1,
clearcoatMap: ccTexture,
clearcoatRoughnessMap: ccrTexture,
clearcoatNormalMap: ccnTexture,
clearcoatNormalScale: new THREE.Vector2(1, 1),
// 透射(玻璃、水)
transmission: 1.0, // 0 = 不透明,1 = 完全透明
transmissionMap: transTexture,
thickness: 0.5, // 折射體積厚度
thicknessMap: thickTexture,
attenuationDistance: 1, // 吸收距離
attenuationColor: new THREE.Color(0xffffff),
// 折射
ior: 1.5, // 折射率(1-2.333)
// 光澤(布料、天鵝絨)
sheen: 1.0,
sheenRoughness: 0.5,
sheenColor: new THREE.Color(0xffffff),
sheenColorMap: sheenTexture,
sheenRoughnessMap: sheenRoughTexture,
// 虹彩(肥皂泡、油膜)
iridescence: 1.0,
iridescenceIOR: 1.3,
iridescenceThicknessRange: [100, 400],
iridescenceMap: iridTexture,
iridescenceThicknessMap: iridThickTexture,
// 各向異性(拉絲金屬)
anisotropy: 1.0,
anisotropyRotation: 0,
anisotropyMap: anisoTexture,
// 鏡面
specularIntensity: 1,
specularColor: new THREE.Color(0xffffff),
specularIntensityMap: specIntTexture,
specularColorMap: specColorTexture,
});
玻璃材質範例
const glass = new THREE.MeshPhysicalMaterial({
color: 0xffffff,
metalness: 0,
roughness: 0,
transmission: 1,
thickness: 0.5,
ior: 1.5,
envMapIntensity: 1,
});
車漆範例
const carPaint = new THREE.MeshPhysicalMaterial({
color: 0xff0000,
metalness: 0.9,
roughness: 0.5,
clearcoat: 1,
clearcoatRoughness: 0.1,
});
MeshToonMaterial
卡通著色風格。
const material = new THREE.MeshToonMaterial({
color: 0x00ff00,
gradientMap: gradientTexture, // 可選:自訂著色漸層
});
// 建立階梯漸層紋理
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
視覺化表面法線。用於除錯。
const material = new THREE.MeshNormalMaterial({
flatShading: false,
wireframe: false,
});
MeshDepthMaterial
渲染深度值。用於陰影貼圖、景深效果。
const material = new THREE.MeshDepthMaterial({
depthPacking: THREE.RGBADepthPacking,
});
PointsMaterial
用於點雲。
const material = new THREE.PointsMaterial({
color: 0xffffff,
size: 0.1,
sizeAttenuation: true, // 隨距離縮放
map: pointTexture,
alphaMap: alphaTexture,
transparent: true,
alphaTest: 0.5, // 丟棄低於閾值的像素
vertexColors: true, // 使用逐頂點顏色
});
const points = new THREE.Points(geometry, material);
LineBasicMaterial 與 LineDashedMaterial
// 實線
const lineMaterial = new THREE.LineBasicMaterial({
color: 0xffffff,
linewidth: 1, // 注意:>1 僅部分系統支援
linecap: "round",
linejoin: "round",
});
// 虛線
const dashedMaterial = new THREE.LineDashedMaterial({
color: 0xffffff,
dashSize: 0.5,
gapSize: 0.25,
scale: 1,
});
// 虛線需要
const line = new THREE.Line(geometry, dashedMaterial);
line.computeLineDistances();
ShaderMaterial
自訂 GLSL 著色器,使用 Three.js 內建 uniform。
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() {
// GLSL 1.0 使用 texture2D(),GLSL 3.0 使用 texture()(glslVersion: THREE.GLSL3)
vec4 texColor = texture2D(texture1, vUv);
gl_FragColor = vec4(color * texColor.rgb, 1.0);
}
`,
transparent: true,
side: THREE.DoubleSide,
});
// 在動畫迴圈中更新 uniform
material.uniforms.time.value = clock.getElapsedTime();
內建 Uniform(自動提供)
// 頂點著色器
uniform mat4 modelMatrix; // 物件到世界
uniform mat4 modelViewMatrix; // 物件到相機
uniform mat4 projectionMatrix; // 相機投影
uniform mat4 viewMatrix; // 世界到相機
uniform mat3 normalMatrix; // 用於轉換法線
uniform vec3 cameraPosition; // 相機世界位置
// 屬性
attribute vec3 position;
attribute vec3 normal;
attribute vec2 uv;
RawShaderMaterial
完全控制 - 無內建 uniform/屬性。
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);
}
`,
});
常見材質屬性
所有材質共享以下基礎屬性:
// 可見性
material.visible = true;
material.transparent = false;
material.opacity = 1.0;
material.alphaTest = 0; // 丟棄 alpha < 值的像素
// 渲染
material.side = THREE.FrontSide; // FrontSide, BackSide, DoubleSide
material.depthTest = true;
material.depthWrite = true;
material.colorWrite = true;
// 混合
material.blending = THREE.NormalBlending;
// NormalBlending, AdditiveBlending, SubtractiveBlending, MultiplyBlending, CustomBlending
// 模板
material.stencilWrite = false;
material.stencilFunc = THREE.AlwaysStencilFunc;
material.stencilRef = 0;
material.stencilMask = 0xff;
// 多邊形偏移(Z 衝突修正)
material.polygonOffset = false;
material.polygonOffsetFactor = 0;
material.polygonOffsetUnits = 0;
// 其他
material.dithering = false;
material.toneMapped = true;
多重材質
// 為幾何群組指定不同材質
const geometry = new THREE.BoxGeometry(1, 1, 1);
const materials = [
new THREE.MeshBasicMaterial({ color: 0xff0000 }), // 右
new THREE.MeshBasicMaterial({ color: 0x00ff00 }), // 左
new THREE.MeshBasicMaterial({ color: 0x0000ff }), // 上
new THREE.MeshBasicMaterial({ color: 0xffff00 }), // 下
new THREE.MeshBasicMaterial({ color: 0xff00ff }), // 前
new THREE.MeshBasicMaterial({ color: 0x00ffff }), // 後
];
const mesh = new THREE.Mesh(geometry, materials);
// 自訂群組
geometry.clearGroups();
geometry.addGroup(0, 6, 0); // 起始索引, 數量, 材質索引
geometry.addGroup(6, 6, 1);
環境貼圖
// 載入立方體紋理
const cubeLoader = new THREE.CubeTextureLoader();
const envMap = cubeLoader.load([
"px.jpg",
"nx.jpg", // 正/負 X
"py.jpg",
"ny.jpg", // 正/負 Y
"pz.jpg",
"nz.jpg", // 正/負 Z
]);
// 套用至材質
material.envMap = envMap;
material.envMapIntensity = 1;
// 或設定為場景環境(影響所有 PBR 材質)
scene.environment = envMap;
// HDR 環境(建議使用)
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;
});
材質複製與修改
// 複製材質
const clone = material.clone();
clone.color.set(0x00ff00);
// 執行時期修改
material.color.set(0xff0000);
material.needsUpdate = true; // 僅部分變更需要
// 需要 needsUpdate 的情況:
// - 變更 flatShading
// - 變更紋理
// - 變更 transparent
// - 自訂著色器程式碼變更
效能提示
- 重複使用材質:相同材質 = 批次繪製呼叫
- 盡量避免透明:透明材質需要排序
- 使用 alphaTest 取代透明度:適用時更快
- 選擇較簡單的材質:Basic > Lambert > Phong > Standard > Physical
- 限制啟用的光源數量:每個光源增加著色器複雜度
// 材質池
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);
}
// 使用完畢後釋放
material.dispose();
另請參閱
threejs-textures- 紋理載入與設定threejs-shaders- 自訂著色器開發threejs-lighting- 光照與材質互動






