threejs-materials

threejs-materials

熱門

Three.js 材質 - PBR、基本、Phong、著色器材質、材質屬性。用於設定網格樣式、處理紋理、建立自訂著色器或最佳化材質效能。

2609星標
299分支
更新於 2026/7/9
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
// - 自訂著色器程式碼變更

效能提示

  1. 重複使用材質:相同材質 = 批次繪製呼叫
  2. 盡量避免透明:透明材質需要排序
  3. 使用 alphaTest 取代透明度:適用時更快
  4. 選擇較簡單的材質:Basic > Lambert > Phong > Standard > Physical
  5. 限制啟用的光源數量:每個光源增加著色器複雜度
// 材質池
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 - 光照與材質互動