本文 AI 產出,尚未審核

Three.js 教學 – 基本材質 MeshBasicMaterial


簡介

在 3D 網頁開發中,材質 (Material) 扮演了「外觀」的角色,決定了模型在螢幕上如何呈現光影、顏色與紋理。MeshBasicMaterial 是 Three.js 最簡單、最常使用的材質之一,它不受任何光照影響,僅以固定的顏色或貼圖直接渲染網格。

對於需要 快速原型UI 介面、或 不需要光照計算的物件(例如天空盒、2D 精靈、debug 圖形),MeshBasicMaterial 是最佳選擇。掌握它的使用方式,能讓你在開發初期就快速看到成果,並為後續進階材質(如 MeshStandardMaterial)奠定基礎。


核心概念

1. MeshBasicMaterial 是什麼?

MeshBasicMaterial 繼承自 Material,其特點如下:

  • 不受光照影響:渲染時只依賴顏色 (color) 或貼圖 (map)。
  • 渲染速度快:省略光照計算,適合大量低多邊形物件或 UI 元素。
  • 適用於 2D 風格或背景圖:如 HUD、精靈、天空盒等。
const material = new THREE.MeshBasicMaterial({ color: 0xff0000 });

2. 常用屬性概覽

屬性 型別 說明
color THREE.Color 基本顏色,可使用十六進位、CSS 字串或 THREE.Color 物件
map THREE.Texture 貼圖,支援 PNG、JPG、WebP 等格式
opacity Number (0~1) 透明度,需同時設定 transparent:true 才會生效
transparent Boolean 是否啟用透明度混合
side THREE.Side 渲染哪一面:FrontSideBackSideDoubleSide
wireframe Boolean 是否以線框模式渲染
alphaTest Number Alpha 測試門檻,常用於裁切半透明貼圖的邊緣
depthWrite Boolean 是否寫入深度緩衝區,調整渲染順序時會用到

小技巧:如果只需要 純色,可以省略 map,直接使用 color;若同時使用貼圖與顏色,貼圖會 乘上 color

3. 建立 MeshBasicMaterial 的基本流程

  1. 載入貼圖(若需要)
    使用 THREE.TextureLoader,確保貼圖已完成載入再套用。
  2. 建立材質實例,設定所需屬性。
  3. 建立幾何體 (Geometry),如 BoxGeometrySphereGeometry
  4. 組合成 Mesh,加入場景。
// 1. 載入貼圖
const loader = new THREE.TextureLoader();
const texture = loader.load('textures/brick_diffuse.jpg');

// 2. 建立材質
const material = new THREE.MeshBasicMaterial({
  map: texture,
  color: 0xffffff,   // 乘上白色不會改變貼圖顏色
  side: THREE.DoubleSide
});

// 3. 建立幾何體
const geometry = new THREE.BoxGeometry(2, 2, 2);

// 4. 合成 Mesh 並加入場景
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

程式碼範例

以下提供 5 個實用範例,示範 MeshBasicMaterial 在不同情境下的用法。每段程式碼均附上說明註解,方便直接複製測試。

範例 1️⃣ 基本純色立方體

// 建立一個純紅色的立方體
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({
  color: 0xff0000   // 十六進位紅色
});
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

說明:此材質完全不受光照影響,無論場景中有多少光源,立方體都會保持純紅色。


範例 2️⃣ 使用貼圖作為材質

const loader = new THREE.TextureLoader();
loader.load('textures/earth.jpg', (texture) => {
  const geometry = new THREE.SphereGeometry(1, 32, 32);
  const material = new THREE.MeshBasicMaterial({
    map: texture,
    // 若想讓貼圖顏色稍微暗一些,可加上 color
    // color: new THREE.Color(0.9, 0.9, 0.9)
  });
  const earth = new THREE.Mesh(geometry, material);
  scene.add(earth);
});

說明MeshBasicMaterial 直接把貼圖貼在球體上,不會因光源而產生陰影或高光,適合作為 地球示意圖背景圖


範例 3️⃣ 半透明與混合模式

const geometry = new THREE.PlaneGeometry(3, 3);
const material = new THREE.MeshBasicMaterial({
  color: 0x00ff00,
  opacity: 0.5,          // 50% 透明度
  transparent: true,    // 必須啟用才能生效
  side: THREE.DoubleSide // 雙面可見
});
const plane = new THREE.Mesh(geometry, material);
plane.position.set(0, 1, -2);
scene.add(plane);

重點:若忘記把 transparent 設為 trueopacity 會被忽略,物件仍會完整不透明。


範例 4️⃣ 雙面渲染與線框模式

// 雙面渲染 + 線框
const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);
const material = new THREE.MeshBasicMaterial({
  color: 0x0000ff,
  side: THREE.DoubleSide, // 兩面都渲染,避免背面消失
  wireframe: true        // 只顯示線框
});
const knot = new THREE.Mesh(geometry, material);
scene.add(knot);

應用:在開發階段想快速檢視模型拓撲或作為 技術指示器(如軌道、路徑)時非常有用。


範例 5️⃣ 結合 alphaTest 裁切半透明貼圖

loader.load('textures/leaf.png', (texture) => {
  const geometry = new THREE.PlaneGeometry(2, 2);
  const material = new THREE.MeshBasicMaterial({
    map: texture,
    transparent: true,
    alphaTest: 0.5          // 只保留 alpha > 0.5 的像素,避免半透明邊緣的混合
  });
  const leaf = new THREE.Mesh(geometry, material);
  leaf.position.set(-2, 0, 0);
  scene.add(leaf);
});

說明alphaTest 可以在渲染前直接剔除低透明度的像素,提升效能,同時避免在多層半透明物件上出現 Z‑fight


常見陷阱與最佳實踐

陷阱 可能的結果 解決方式
忘記設定 transparent:true opacity 無效,物件仍全不透明 設定 transparent:true,或直接使用 alphaTest
貼圖未完成載入就使用 會得到 黑色或錯誤的紋理 使用 TextureLoader.load 的回呼或 Promise,確保貼圖載入完成
使用非 2 的次方尺寸貼圖 部分舊版瀏覽器會自動縮放,導致模糊或失真 盡量使用 256、512、1024、2048… 的尺寸;若無法避免,設定 texture.minFilter = THREE.LinearFilter
大量重複建立相同材質 記憶體浪費、渲染效能下降 重用 Material 實例,或使用 material.clone() 只在需要微調時才複製
未呼叫 material.dispose() 釋放不到 GPU 記憶體,長時間運行會記憶體泄漏 在物件不再需要時,手動呼叫 material.dispose()texture.dispose()
忘記設定 side: THREE.DoubleSide 背面不渲染,導致模型在特定角度變透明 若模型會被從背面觀看,記得設定 DoubleSide,但注意渲染成本會稍增

最佳實踐小結

  1. 先載入貼圖再建立材質:使用 Promiseasync/await 確保貼圖已完成。
  2. 統一管理材質:建立一個 materials 物件或 Map,集中儲存與重用。
  3. 設定正確的色彩空間:在渲染器開啟 outputEncoding = THREE.sRGBEncoding,貼圖若為 sRGB,記得 texture.encoding = THREE.sRGBEncoding
  4. 適度使用 alphaTest:在大量半透明葉子、旗幟等貼圖時,使用 alphaTest 可大幅提升效能。
  5. 釋放資源:在場景切換或物件刪除時,務必呼叫 dispose(),保持記憶體乾淨。

實際應用場景

場景 為什麼選擇 MeshBasicMaterial
2D UI/HUD(如血條、按鈕) 不需要光照,渲染成本低,顏色與貼圖直接呈現
天空盒或背景平面 只需貼圖,不受光照影響,避免背景被光源改變顏色
Debug 形狀(座標軸、邊框) 直接使用純色或線框,快速辨識模型位置
簡易貼圖示意(例如地圖、概念圖) 只要貼圖本身的色彩,無需光照計算
粒子系統的基礎點 使用 SpriteMaterial(基於 MeshBasicMaterial)渲染 2D 圖案,保持透明度與混合模式

總結

MeshBasicMaterialThree.js 中最直接、最輕量的材質類別。它的 不受光照特性 讓開發者能在最短時間內得到可視化結果,特別適合:

  • 快速原型UI 元件
  • 背景圖、天空盒 以及 純色示意
  • Debug教學範例

掌握其屬性(colormapopacitytransparentsidewireframe 等)以及常見陷阱(透明度設定、貼圖載入、資源釋放),即可在日常開發中靈活運用,並為之後的 PBRShader 材質奠定堅實基礎。

實務建議:在專案中先建立一套 材質管理器(Material Registry),把所有 MeshBasicMaterial 放入共用池子。這樣不僅能減少記憶體開銷,還能在需要調整全局顏色或亮度時,只需要改動一次即可。

祝你在 Three.js 的旅程中玩得開心,創造出豐富多彩的 3D 網頁體驗! 🚀