本文 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 的特性

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

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

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);

重點MeshBasicMaterialcolor 接受十六進位、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 必須與 alphaMapopacity < 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 使用 alphaMapopacity 時,物件仍呈不透明。 必須同時把 transparent 設為 true,才能讓透明度生效。
貼圖未正確載入 TextureLoader.load 的回呼未處理錯誤,導致材質呈純白或黑。 使用 loader.load(url, onLoad, onProgress, onError),在 onError 中顯示警告。
線框與實體同時渲染 想要同時看到實體與線框,但直接 wireframe:true 會隱藏實體。 建議建立兩個 Mesh:一個 MeshBasicMaterial(實體),另一個 MeshBasicMaterial({wireframe:true}),並共用同一 geometry。
過多獨立 Mesh 每個小部件都建一個 Mesh,會造成渲染批次過多。 盡量 合併 geometryBufferGeometryUtils.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 搭配 BoxGeometrySphereGeometry 完全足夠。
Debug/除錯 透過 wireframe:true 或多材質的顏色區分,可快速定位模型錯誤或看清拓撲結構。

總結

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

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