Three.js 與工具整合 ── 匯入 Blender 產生的模型
簡介
在 3D 網頁開發的領域,Three.js 已成為最主流的 JavaScript 圖形函式庫。它提供了完整的渲染管線、相機、光源與材質系統,讓開發者可以在瀏覽器內即時呈現高品質的 3D 內容。而 Blender 作為免費且功能強大的 3D 建模工具,常被用來製作角色、場景、動畫等資產。把在 Blender 中完成的模型帶入 Three.js,能大幅縮短開發週期、提升視覺表現,尤其適合遊戲、產品展示與互動藝術等專案。
本篇文章將一步步說明 如何將 Blender 匯出的模型正確載入 Three.js,包含常見的檔案格式、匯出設定、載入程式碼與最佳化技巧。即使您是剛接觸 Three.js 的新手,或是已有一定經驗的前端開發者,都能從中獲得實務上可直接套用的範例與概念。
核心概念
1. 何謂「可匯入」的檔案格式?
Three.js 原生支援多種 3D 檔案格式,最常用的兩種是:
| 格式 | 副檔名 | 特點 |
|---|---|---|
| glTF | .gltf / .glb |
現代標準、支援 PBR 材質、檔案體積小、載入速度快 |
| OBJ | .obj + .mtl |
老牌格式、僅支援基本材質、檔案較大、無法直接包含貼圖 |
建議:在大多數情況下,優先選擇 glTF(尤其是二進位
.glb),因為它保留了 Blender 中的節點層級、動畫與高階材質資訊,且與 WebGL 的相容性最佳。
2. 從 Blender 匯出 glTF
檢查模型
- 確認法線方向正確(
Shift+N重新計算) - 移除未使用的頂點與重複的材質
- 以 單位公尺 為基礎(
Scene > Units > Metric),避免比例錯誤
- 確認法線方向正確(
匯出流程
File > Export > glTF 2.0 (.glb/.gltf)- Export Settings(常用選項)
- Format:選擇
glb(單一二進位檔)或gltf + bin + textures - Include:
Selected Objects(只匯出選取的)或Scene(全部) - Geometry:
UVs、Normals、Tangents必勾選,確保貼圖與法線正確 - Materials:
Export Materials→PBR Metallic Roughness(預設) - Animation:若有動畫,勾選
Animation,否則可關閉
- Format:選擇
測試匯出結果
- 使用官方的 glTF Viewer 或
three.js的GLTFViewer範例快速驗證模型是否正確載入。
- 使用官方的 glTF Viewer 或
3. Three.js 中載入 glTF
Three.js 提供了 GLTFLoader 來讀取 glTF/GLB 檔案。以下是一個最簡單的載入範例:
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
// 建立基本場景
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 1.6, 3);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 加入簡單光源
const hemiLight = new THREE.HemisphereLight(0xffffff, 0x444444, 1.5);
scene.add(hemiLight);
// 載入 glTF
const loader = new GLTFLoader();
loader.load(
'models/house.glb', // ← 你的模型路徑
(gltf) => {
const model = gltf.scene;
model.scale.set(1, 1, 1); // 依需求調整比例
scene.add(model);
console.log('模型載入完成', gltf);
},
(xhr) => {
console.log(`模型載入進度: ${(xhr.loaded / xhr.total * 100).toFixed(2)}%`);
},
(error) => {
console.error('模型載入失敗', error);
}
);
// 渲染迴圈
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
重點:
loader.load的第三個參數是 進度回呼,對於大型模型特別有用;第四個參數則是 錯誤處理,務必保留以便除錯。
4. 使用材質與貼圖的進階範例
如果模型本身沒有完整的 PBR 材質,或想在程式中覆寫貼圖,可參考以下範例:
loader.load('models/car.glb', (gltf) => {
const car = gltf.scene;
// 假設模型內有名為 "Body" 的 Mesh
const bodyMesh = car.getObjectByName('Body');
if (bodyMesh) {
// 建立自訂的 MeshStandardMaterial
const texture = new THREE.TextureLoader().load('textures/car-paint.jpg');
bodyMesh.material = new THREE.MeshStandardMaterial({
map: texture,
metalness: 0.8,
roughness: 0.2,
});
}
scene.add(car);
});
5. 載入含動畫的模型
Blender 可以匯出骨架動畫(skinning)或物件動畫(keyframe)。Three.js 會把這些資訊放在 gltf.animations 陣列中,使用 AnimationMixer 播放:
loader.load('models/character.glb', (gltf) => {
const model = gltf.scene;
scene.add(model);
// 建立 Mixer
const mixer = new THREE.AnimationMixer(model);
// 假設只有一段動畫
const action = mixer.clipAction(gltf.animations[0]);
action.play();
// 在渲染迴圈中更新 Mixer
const clock = new THREE.Clock();
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
mixer.update(delta);
renderer.render(scene, camera);
}
animate();
});
技巧:若模型包含多段動畫,可使用
mixer.clipAction(name)針對特定片段控制播放、暫停與混合。
常見陷阱與最佳實踐
| 陷阱 | 說明 | 解決方案 |
|---|---|---|
| 模型比例不正確 | Blender 預設使用公尺,Web 頁面常用的是「單位」為 1。 | 匯出前確認 Scene > Units 為 Metric,載入後使用 model.scale.set(...) 調整。 |
| 法線翻轉 | 法線方向錯誤會導致光照異常,特別是雙面材質。 | 在 Blender 中 Shift+N 重新計算法線,或於 Three.js 使用 material.side = THREE.DoubleSide(僅作臨時測試)。 |
| 貼圖路徑錯誤 | glTF 內的貼圖路徑若是相對路徑,必須確保檔案位置一致。 | 使用 GLTFLoader.setPath('models/') 統一設定基礎路徑,或在匯出時選擇 Embed Textures(將貼圖寫入 .glb)。 |
| 過大的檔案 | 未壓縮的模型或高解析度貼圖會拖慢載入速度。 | 於 Blender 使用 Decimate Modifier 簡化多邊形,貼圖使用 JPEG/WEBP 壓縮,或在匯出時勾選 Compress(.glb 支援) |
| 動畫不播放 | 常見原因是忘記在渲染迴圈更新 AnimationMixer。 |
確保 mixer.update(delta) 於 animate 內部呼叫,並使用 THREE.Clock 取得正確的時間差。 |
最佳實踐
- 使用
.glb二進位檔:單檔案、壓縮率高、載入速度快。 - 分離貼圖與模型:大型貼圖可使用 CDN 或
Cache-Control進行快取。 - 利用 DRACO 壓縮:Three.js 支援
DRACOLoader,可將幾千個三角形壓縮至數百 KB。 - Lazy Load:使用
IntersectionObserver或three/examples/jsm/loaders/GLTFLoader的setDRACOLoader只在需要時才載入模型。 - 測試不同平台:手機 GPU 記憶體有限,務必在低階裝置上測試 FPS 與記憶體佔用。
實際應用場景
| 場景 | 為何需要匯入 Blender 模型 | 典型實作方式 |
|---|---|---|
| 產品 3D 展示 | 客製化的商品外觀與材質(如手機、家具) | 使用 GLTFLoader 載入高品質貼圖,搭配 OrbitControls 讓使用者旋轉檢視。 |
| 線上互動教學 | 需要精細的解剖模型或機械結構 | 匯入含骨架動畫的模型,利用 AnimationMixer 播放分解動畫。 |
| Web AR/VR | 需要輕量且支援 PBR 的模型以符合實境光照 | 使用 .glb + DRACO 壓縮,結合 WebXRManager 建立沉浸式體驗。 |
| 即時多人遊戲 | 多樣化角色與場景資產 | 透過 GLTFLoader 動態載入角色外觀,結合 SkeletonHelper 進行骨架調整。 |
| 藝術裝置 | 複雜的程式產生幾何與手工雕刻模型混合 | 在 Blender 中完成基礎造型、貼圖,匯出後在 Three.js 中加入自訂 Shader 效果。 |
總結
將 Blender 與 Three.js 結合,是當今前端 3D 開發最常見且高效的工作流程。透過 glTF/GLB 作為橋樑,我們能保留模型的幾何、材質、貼圖與動畫,同時在瀏覽器中以 WebGL 即時渲染。本文重點回顧如下:
- 選擇適當的檔案格式:優先使用
.glb,必要時搭配 DRACO 壓縮。 - 匯出前的模型清理:法線、UV、單位與多餘材質必須檢查。
- Three.js 載入流程:
GLTFLoader+AnimationMixer+ 進度/錯誤回呼是基本骨架。 - 常見陷阱:比例、法線、貼圖路徑與檔案大小,皆可透過上述最佳實踐避免。
- 實務應用:從產品展示到 AR/VR,模型的即時載入與渲染已成為提升使用者體驗的關鍵。
掌握以上技巧後,您就能在 Three.js 專案中自如地使用 Blender 製作的資產,快速打造出視覺豐富、互動性高的 Web 3D 體驗。祝開發順利,玩得開心!