はじめに
Three.jsで3Dモデルを読み込むとき、FBXとglTF(GLB)のどちらを使うべきか迷ったので調べてまとめました。
結論から言うと、Three.jsではglTF(GLB)を使うのがおすすめです。
FBXでマテリアルがうまく表示されない問題にハマったので、その経験も含めて書いていきます。
各形式の概要
FBX
Autodesk社が開発したプロプライエタリ形式。3DCGソフト間のデータ交換でよく使われます。
glTF / GLB
Khronos Groupが策定したオープンな3D形式。「3DのJPEG」とも呼ばれていて、Web向けに最適化されています。
| 形式 | 説明 |
|---|---|
| glTF | JSON + 外部バイナリ + テクスチャ画像(複数ファイル) |
| GLB | glTFをバイナリにまとめた単一ファイル |
GLBはglTFのバイナリ版で、中身は同じです。配布や読み込みが楽なのでGLBを使うことが多いです。
Three.jsでの比較
読み込み方法
import { FBXLoader } from 'three/addons/loaders/FBXLoader.js'
const loader = new FBXLoader()
loader.load('/model.fbx', (fbx) => {
scene.add(fbx)
})
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'
const loader = new GLTFLoader()
loader.load('/model.glb', (gltf) => {
scene.add(gltf.scene)
})
どちらも簡単に読み込めますが、問題はその後です。
FBXで起きた問題:マテリアルが正しく表示されない
FBXを使っていたとき、Blenderでは綺麗に見えていたモデルがThree.jsだと全然違う見た目になる問題が発生しました。
具体的な症状
- テクスチャが真っ黒になる
- 金属感や光沢が再現されない
- 透明度がおかしい
- ノーマルマップが効いていない
原因
FBXはマテリアル情報の互換性が低いです。
FBXのマテリアルはDCCツール(Blender等)固有の設定に依存していて、Three.jsのマテリアルシステムと1対1で対応していないので
以下のように手動で設定する必要があるみたいです。
// FBXLoaderはPhongMaterialとして読み込むことが多い
// PBRマテリアルとして使いたい場合は手動変換が必要
fbx.traverse((child) => {
if (child.isMesh) {
const oldMaterial = child.material
child.material = new THREE.MeshStandardMaterial({
map: oldMaterial.map,
// 他のプロパティを手動で設定...
})
}
})
glTF(GLB)に変えたら解決した
glTFに変換したら、Blenderで見たままの見た目がThree.jsでも再現されました。
なぜglTFだとうまくいくのか
glTFはPBR(Physically Based Rendering)マテリアルを標準サポートしています。
Three.jsのMeshStandardMaterialとglTFのマテリアル仕様が対応しているので、変換ロスがほぼありません。
FBX vs glTF(GLB) 比較表
| 項目 | FBX | glTF / GLB |
|---|---|---|
| 形式 | プロプライエタリ | オープン標準 |
| ファイルサイズ | 大きめ | 小さい(最適化済み) |
| Web向け最適化 | ❌ | ✅ |
| PBRマテリアル | △(変換が必要) | ✅(標準サポート) |
| アニメーション | ✅ | ✅ |
| Three.jsサポート | △ | ✅(推奨形式) |
| Draco圧縮 | ❌ | ✅ |
glTFのメリット
1. マテリアルの互換性が高い
PBRマテリアルが標準なので、DCCツール(Blenderなど)とThree.jsで見た目が一致します。
2. ファイルサイズが小さい
バイナリ形式 + Draco圧縮でかなり軽量化できます。
import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js'
const dracoLoader = new DRACOLoader()
dracoLoader.setDecoderPath('/draco/')
const loader = new GLTFLoader()
loader.setDRACOLoader(dracoLoader)
3. Web標準として広くサポート
Three.js公式が推奨している形式です。
FBXを使うべきケース
とはいえ、FBXが必要な場面もあります。
- 既存のパイプラインがFBX前提
- 他のチームからFBXでしかもらえない
- 特定のDCCツール間のデータ交換
その場合でも、最終的にThree.jsで使うならglTFに変換することをおすすめします。
まとめ
Three.jsで3Dモデルを使うなら、glTF(GLB)一択です。
FBXでマテリアルが正しく表示されない問題に何時間も悩んだんですが、GLBに変えたら一瞬で解決しました。
最初からGLBを使っていれば...という気持ちになったので、これから始める人はglTF(GLB)を選んでおくのが無難です。