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 建立副本。 |
最佳實踐
- 預先載入貼圖:使用
THREE.LoadingManager統一管理資源,確保所有貼圖在場景建立前已載入完成。 - 使用
DoubleSide時謹慎:雙面渲染會增加渲染成本,僅在需要看到背面時才開啟。 - 適時切換材質:在需要光照的階段,可將
MeshBasicMaterial換成MeshStandardMaterial,不必重新建立 Mesh,只要mesh.material = newMaterial即可。 - 保持 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 世界!