本文 AI 產出,尚未審核

Three.js 教學:Mesh 與 MeshBasicMaterial


簡介

在 Three.js 的整個渲染管線中,Mesh 是最常見、也是最基礎的可視化單位。它把幾何體(Geometry)與材質(Material)結合起來,讓 3D 物件能被投射到螢幕上。即使是最簡單的立方體、球體或自訂模型,都必須先以 Mesh 的形式呈現。

而 MeshBasicMaterial 則是三大內建材質之一,特點是不受光照影響、渲染速度快,非常適合用於 UI、背景、debug、或是需要純色/純貼圖顯示的情境。掌握 Mesh 與 MeshBasicMaterial 的用法,能讓你在開發階段快速驗證模型、建立原型,甚至在正式作品中也能運用得當。

本篇文章將從概念說明、實作範例、常見陷阱與最佳實踐,直到實務應用,完整帶領你建立對 Mesh 與 MeshBasicMaterial 的深刻認識。


核心概念

1. Mesh 的結構

在 Three.js 中,THREE.Mesh 是一個 Object3D 的子類別,具備以下兩個核心屬性:

屬性 型別 說明
geometry THREE.BufferGeometry(或舊版 Geometry) 定義頂點、索引、法線、UV 等資訊的幾何體。
material THREE.Material(或陣列) 定義表面外觀、顏色、貼圖、透明度等的材質。

Mesh 會把 geometry 與 material 直接「綁」在一起,渲染器在渲染每一幀時會根據這兩者的資訊產生最終像素。

小技巧:若需要同一個 geometry 共享多個材質(例如同一個模型的不同部位使用不同貼圖),可以在 Mesh 建構子裡傳入 材質陣列,或使用 THREE.Group 來管理多個子 Mesh。

2. MeshBasicMaterial 的特性

特性 說明
不受光照影響 只依賴 color、map、wireframe 等屬性,適合做 UI、2.5D 背景或測試模型。
渲染效能高 省去光照計算,對於大量簡單物件(如粒子、點陣圖)非常友好。
支援透明度 透過 transparent、opacity 或 alphaMap 控制透明效果。
支援貼圖 可直接掛載 map(顏色貼圖)、alphaMap(透明貼圖)等。
支援線框模式 wireframe: true 可快速切換成線框顯示,方便除錯。

提醒:如果場景需要光照、陰影或更真實的材質效果,請改用 MeshStandardMaterial、MeshPhongMaterial 等會參與光照計算的材質。

3. 建立 Mesh 的基本流程

// 1. 建立渲染器、相機、場景(此處省略設定細節)
// 2. 建立幾何體
const geometry = new THREE.BoxGeometry(1, 1, 1);   // 立方體

// 3. 建立材質
const material = new THREE.MeshBasicMaterial({
  color: 0x156289,          // 基礎顏色(十六進位)
  wireframe: false,        // 是否以線框方式渲染
});

// 4. 組合成 Mesh
const mesh = new THREE.Mesh(geometry, material);

// 5. 加入場景
scene.add(mesh);

上述流程是最常見的「幾何 + 材質 = Mesh」模式,接下來會展示更實務的變化。


程式碼範例

以下示範 5 個常見且實用的 Mesh + MeshBasicMaterial 實例,從最簡單的顏色方塊到貼圖、透明、線框、以及多材質組合。每段程式碼皆附上說明,方便直接貼到自己的專案中測試。

範例 1:單純顏色方塊

// 建立一個 2x2x2 的立方體,使用純色材質
const geometry = new THREE.BoxGeometry(2, 2, 2);
const material = new THREE.MeshBasicMaterial({ color: 0xff0000 }); // 紅色
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

重點:MeshBasicMaterial 的 color 接受十六進位、CSS 色碼或 THREE.Color 物件。

範例 2:貼圖立方體

// 載入貼圖(使用 TextureLoader)
const loader = new THREE.TextureLoader();
const texture = loader.load('textures/crate.jpg'); // 替換成你的貼圖路徑

const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({
  map: texture,               // 指定貼圖
  side: THREE.DoubleSide,     // 雙面渲染,避免背面消失
});
const texturedCube = new THREE.Mesh(geometry, material);
scene.add(texturedCube);

技巧:若貼圖尺寸不是 2 的次方,Three.js 仍會自動調整,但建議使用 2ⁿ(如 256、512、1024)以獲得最佳效能。

範例 3:透明材質與 Alpha 貼圖

// 透明 PNG 作為 alphaMap
const loader = new THREE.TextureLoader();
const colorMap = loader.load('textures/leaf_diffuse.png');
const alphaMap = loader.load('textures/leaf_alpha.png');

const geometry = new THREE.PlaneGeometry(2, 2);
const material = new THREE.MeshBasicMaterial({
  map: colorMap,
  alphaMap: alphaMap,          // 透明度貼圖
  transparent: true,          // 必須開啟透明度
  side: THREE.DoubleSide,
});

const leaf = new THREE.Mesh(geometry, material);
leaf.position.set(0, 1, -2);
scene.add(leaf);

注意:transparent: true 必須與 alphaMap 或 opacity < 1 同時使用,否則透明度不會生效。

範例 4:線框模式(Wireframe)

const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);
const material = new THREE.MeshBasicMaterial({
  color: 0x00ff00,
  wireframe: true,            // 啟用線框渲染
});

const knot = new THREE.Mesh(geometry, material);
scene.add(knot);

應用:線框模式常用於 除錯(檢查模型拓撲)或 藝術化(如網格風格的 UI)。

範例 5:多材質組合(同一幾何體不同面使用不同材質)

// 立方體的六個面分別使用不同顏色
const geometry = new THREE.BoxGeometry(1, 1, 1);
const materials = [
  new THREE.MeshBasicMaterial({ color: 0xff0000 }), // +X
  new THREE.MeshBasicMaterial({ color: 0x00ff00 }), // -X
  new THREE.MeshBasicMaterial({ color: 0x0000ff }), // +Y
  new THREE.MeshBasicMaterial({ color: 0xffff00 }), // -Y
  new THREE.MeshBasicMaterial({ color: 0xff00ff }), // +Z
  new THREE.MeshBasicMaterial({ color: 0x00ffff }), // -Z
];

// 傳入材質陣列,Three.js 會自動對應每個面
const multiMaterialCube = new THREE.Mesh(geometry, materials);
scene.add(multiMaterialCube);

說明:若 geometry 使用 BufferGeometry,需要確保每個面都有對應的 group(Three.js 會自動在 BoxGeometry 中建立),才能正確套用陣列材質。


常見陷阱與最佳實踐

陷阱 描述 解決方案 / 最佳實踐
忘記設定 transparent:true 使用 alphaMap 或 opacity 時,物件仍呈不透明。 必須同時把 transparent 設為 true,才能讓透明度生效。
貼圖未正確載入 TextureLoader.load 的回呼未處理錯誤,導致材質呈純白或黑。 使用 loader.load(url, onLoad, onProgress, onError),在 onError 中顯示警告。
線框與實體同時渲染 想要同時看到實體與線框,但直接 wireframe:true 會隱藏實體。 建議建立兩個 Mesh:一個 MeshBasicMaterial(實體),另一個 MeshBasicMaterial({wireframe:true}),並共用同一 geometry。
過多獨立 Mesh 每個小部件都建一個 Mesh,會造成渲染批次過多。 盡量 合併 geometry(BufferGeometryUtils.mergeBufferGeometries)或使用 InstancedMesh。
材質共享導致意外變更 多個 Mesh 共用同一個 material,改變其中一個會影響全部。 若需要獨立控制,使用 material.clone() 為每個 Mesh 建立副本。

最佳實踐

  1. 預先載入貼圖:使用 THREE.LoadingManager 統一管理資源,確保所有貼圖在場景建立前已載入完成。
  2. 使用 DoubleSide 時謹慎:雙面渲染會增加渲染成本,僅在需要看到背面時才開啟。
  3. 適時切換材質:在需要光照的階段,可將 MeshBasicMaterial 換成 MeshStandardMaterial,不必重新建立 Mesh,只要 mesh.material = newMaterial 即可。
  4. 保持 geometry 與 material 分離:保持程式碼結構清晰,讓幾何體與材質可以獨立重用或替換。

實際應用場景

場景 為什麼選擇 Mesh + MeshBasicMaterial
遊戲 UI 元素(如按鈕、圖示) 不需要光照,渲染效能高,且可以直接使用貼圖或顏色。
資料視覺化(柱狀圖、熱圖) 大量簡單立方體或平面,使用 MeshBasicMaterial 渲染速度快。
快速原型測試 開發階段只想驗證模型尺寸、位置,使用純色材質即可省去光照設定。
2.5D 背景或天空盒 只需要貼圖顯示環境,沒有光照需求,MeshBasicMaterial 搭配 BoxGeometry 或 SphereGeometry 完全足夠。
Debug/除錯 透過 wireframe:true 或多材質的顏色區分,可快速定位模型錯誤或看清拓撲結構。

總結

  • Mesh 是將幾何體與材質結合的核心物件,三維場景的所有可見元素基本上都以 Mesh 形式存在。
  • MeshBasicMaterial 以「不受光照」為最大特點,適合 UI、背景、測試與大量簡單物件的渲染。
  • 透過 顏色、貼圖、透明度、線框 等屬性,你可以在短時間內完成多樣化的視覺效果。
  • 注意 transparent、alphaMap、side、wireframe 等屬性的相互關係,避免常見的渲染錯誤。
  • 最佳實踐包括 預載貼圖、資源管理、適度合併 Mesh、避免不必要的雙面渲染,以提升效能與維護性。

掌握以上概念與技巧,你就能在 Three.js 中自如地建立各式 3D 物件,從快速原型到正式作品,都能以 Mesh + MeshBasicMaterial 為基礎,打造流暢且易於維護的渲染流程。祝你玩得開心,創作出精彩的 3D 世界!