glTF 対応 WebGL ライブラリを比較してみる

この記事は[WebGL Advent Calender 2016](http://qiita.com/advent-calendar/2016/webgl)の４日目の記事です。

## はじめに
皆さんは、[glTF](https://github.com/KhronosGroup/glTF) というファイルフォーマットをご存じでしょうか？

glTF  は GL Transmission Format の略で、3D アセットの標準仕様を狙った、比較的新しいフォーマットです。

音楽なら「MP3」、画像なら「JPEG」という感じで、3Dなら「glTF」を目指しているようです。

![image](https://qiita-image-store.s3.amazonaws.com/0/26094/9ce11bb5-a45f-7d1a-bf45-b05f5a23d682.png)
（出典：https://www.khronos.org/gltf）

最近マイクロソフトも [Khronos の 3D Format Working group に加わった](https://blogs.windows.com/buildingapps/2016/10/28/bringing-3d-to-everyone-through-open-standards/#kqkeTE7YaKIcOvcM.97)ようですし、今後の普及が期待されるフォーマットとなっています。

## glTF ファイルの特徴

- ファイルは JSON ベース
- データ構造は OpenGL ベース
- GLSL シェーダを採用

と、なっており、JavaScript と WebGL と親和性の高いファイルになっています。

フォーマットの詳細は、後日、純国産 WebGL ライブラリ「GLBoost」の作者、emadurandal さんから解説があると思われますので、興味があるかたは[そちら](http://qiita.com/emadurandal/items/1a034c4addd7ff8b5184)を参照ください。

## glTF 対応ライブラリについて

glTF 対応ライブラリも様々あるわけですが、ここでは WebGL 版の glTF 対応ライブラリを紹介したいと思います。WebGL Advent Calender ですしね。

現在、Khronos の [glTF 公式ページ](https://github.com/KhronosGroup/glTF#webgl-engines)には、以下の８つのライブラリが紹介されています。特徴は自分の主観です。

|ライブラリ名                                      |作者                   |WebGL ライブラリの特徴                 |
|:-------------------------------------------------|:----------------------|:--------------------------------------|
|[Three.js](https://threejs.org/)                  |mrdoob                 |一番人気の WebGL ライブラリ            |
|[BabylonJS](http://babylonjs.com/)                |deltakosh              |MS の中の人が中心になって開発中        |
|[Cesium](http://cesiumjs.org/)                    |AnalyticalGraphicsInc  |3D 地球儀のライブラリ                  |
|[PEX](http://vorg.github.io/pex/)                 |vorg                   |node.js と親和性の高い WebGL ライブラリ|
|[xeogl](http://xeogl.org/)                        |xeolabs                |データ駆動型の WebGL ライブラリ        |
|[A-Frame](https://github.com/aframevr/aframe)     |ngokevin               |VR を構築する為の Web フレームワーク   |
|[GLBoost](https://github.com/emadurandal/GLBoost) |emadurandal            |純国産の WebGL ライブラリ              |
|[xml3d.js](http://xml3d.org/)                     |csvurt                 |XML ベースの 3D ライブラリ             |

## glTF 対応ライブラリ別ステータス比較

本当は上記8つのライブラリすべて試したかったのですが、準備不足の為、PEX / A-Frame / xml3d.js は、未実施です。
また、公式ページには未記載ですが、国産 WebGL ライブラリの「Grimoire.js」が、glTF 対応に取り組み始めたようですので、一覧に追加しました。

| Model                                                                                           | Screenshot                                                                                                |[Three.js r82dev](https://github.com/mrdoob/three.js/tree/dev/examples/js/loaders/GLTFLoader.js)                           |[Babylon.js 2.5-beta](https://github.com/BabylonJS/Babylon.js/tree/master/loaders/glTF)                                                           |[Cesium.js 1.26](https://github.com/AnalyticalGraphicsInc/cesium/)                                               |[xeogl 2016.11.11](https://github.com/xeolabs/xeogl/tree/master/src/models/gltf)                                               |[GLBoost 2016.11.30](https://github.com/emadurandal/GLBoost/blob/master/src/js/middle_level/loader/GLTFLoader.js)                  |[Grimoire.js 2016.12.04](https://github.com/GrimoireGL/grimoirejs-gltf)                                                               |
|-------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------|
|[Box](https://github.com/cx20/gltf-test/raw/master/sampleModels/Box)                             |![](https://github.com/cx20/gltf-test/raw/master/sampleModels/Box/screenshot/screenshot.png)               |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/threejs/index.html?model=Box&scale=1)                |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/babylonjs/index.html?model=Box&scale=1)                                     |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/cesium/index.html?model=Box)               |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/xeogl/index.html?model=Box&scale=1)                      |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/glboost/index.html?model=Box&scale=1)                        |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/grimoiregl/index.html?model=Box&scale=1)                        |
|[BoxWithoutIndices](https://github.com/cx20/gltf-test/raw/master/sampleModels/BoxWithoutIndices) |![](https://github.com/cx20/gltf-test/raw/master/sampleModels/BoxWithoutIndices/screenshot/screenshot.png) |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/threejs/index.html?model=BoxWithoutIndices&scale=1)  |:x: [Sample](https://cx20.github.io/gltf-test/examples/babylonjs/index.html?model=BoxWithoutIndices&scale=1) glTF-Embedded not work               |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/cesium/index.html?model=BoxWithoutIndices) |:x: [Sample](https://cx20.github.io/gltf-test/examples/xeogl/index.html?model=BoxWithoutIndices&scale=1) glTF-Embedded not work|:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/glboost/index.html?model=BoxWithoutIndices&scale=1)          |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/grimoiregl/index.html?model=BoxWithoutIndices&scale=1)          |
|[Box Textured](https://github.com/cx20/gltf-test/raw/master/sampleModels/BoxTextured)            |![](https://github.com/cx20/gltf-test/raw/master/sampleModels/BoxTextured/screenshot/screenshot.png)       |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/threejs/index.html?model=BoxTextured&scale=1)        |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/babylonjs/index.html?model=BoxTextured&scale=1)                             |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/cesium/index.html?model=BoxTextured)       |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/xeogl/index.html?model=BoxTextured&scale=1)              |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/glboost/index.html?model=BoxTextured&scale=1)                |:x: [Sample](https://cx20.github.io/gltf-test/examples/grimoiregl/index.html?model=BoxTextured&scale=1) glTF-Embedded not textured    |
|[Box Semantics](https://github.com/cx20/gltf-test/raw/master/sampleModels/BoxSemantics)          |![](https://github.com/cx20/gltf-test/raw/master/sampleModels/BoxSemantics/screenshot/screenshot.png)      |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/threejs/index.html?model=BoxSemantics&scale=1)       |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/babylonjs/index.html?model=BoxSemantics&scale=1)                            |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/cesium/index.html?model=BoxSemantics)      |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/xeogl/index.html?model=BoxSemantics&scale=1)             |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/glboost/index.html?model=BoxSemantics&scale=1)               |:x: [Sample](https://cx20.github.io/gltf-test/examples/grimoiregl/index.html?model=BoxSemantics&scale=1) glTF-Embedded not textured   |
|[Duck](https://github.com/cx20/gltf-test/raw/master/sampleModels/Duck)                           |![](https://github.com/cx20/gltf-test/raw/master/sampleModels/Duck/screenshot/screenshot.png)              |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/threejs/index.html?model=Duck&scale=1)               |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/babylonjs/index.html?model=Duck&scale=1)                                    |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/cesium/index.html?model=Duck)              |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/xeogl/index.html?model=Duck&scale=1)                     |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/glboost/index.html?model=Duck&scale=1)                       |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/grimoiregl/index.html?model=Duck&scale=1)                       |
|[2 Cylinder Engine](https://github.com/cx20/gltf-test/raw/master/sampleModels/2CylinderEngine)   |![](https://github.com/cx20/gltf-test/raw/master/sampleModels/2CylinderEngine/screenshot/screenshot.png)   |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/threejs/index.html?model=2CylinderEngine&scale=0.005)|:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/babylonjs/index.html?model=2CylinderEngine&scale=0.005)                     |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/cesium/index.html?model=2CylinderEngine)   |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/xeogl/index.html?model=2CylinderEngine&scale=0.005)      |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/glboost/index.html?model=2CylinderEngine&scale=0.005)        |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/grimoiregl/index.html?model=2CylinderEngine&scale=0.005)        |
|[Reciprocating Saw](https://github.com/cx20/gltf-test/raw/master/sampleModels/ReciprocatingSaw)  |![](https://github.com/cx20/gltf-test/raw/master/sampleModels/ReciprocatingSaw/screenshot/screenshot.png)  |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/threejs/index.html?model=ReciprocatingSaw&scale=0.01)|:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/babylonjs/index.html?model=ReciprocatingSaw&scale=0.01)                     |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/cesium/index.html?model=ReciprocatingSaw)  |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/xeogl/index.html?model=ReciprocatingSaw&scale=0.01)      |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/glboost/index.html?model=ReciprocatingSaw&scale=0.01)        |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/grimoiregl/index.html?model=ReciprocatingSaw&scale=0.01)        |
|[Gearbox Assy](https://github.com/cx20/gltf-test/raw/master/sampleModels/GearboxAssy)            |![](https://github.com/cx20/gltf-test/raw/master/sampleModels/GearboxAssy/screenshot/screenshot.png)       |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/threejs/index.html?model=GearboxAssy&scale=1)        |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/babylonjs/index.html?model=GearboxAssy&scale=1)                             |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/cesium/index.html?model=GearboxAssy)       |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/xeogl/index.html?model=GearboxAssy&scale=1)              |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/glboost/index.html?model=GearboxAssy&scale=1)                |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/grimoiregl/index.html?model=GearboxAssy&scale=1)                |
|[Buggy](https://github.com/cx20/gltf-test/raw/master/sampleModels/Buggy)                         |![](https://github.com/cx20/gltf-test/raw/master/sampleModels/Buggy/screenshot/screenshot.png)             |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/threejs/index.html?model=Buggy&scale=0.02)           |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/babylonjs/index.html?model=Buggy&scale=0.02)                                |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/cesium/index.html?model=Buggy)             |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/xeogl/index.html?model=Buggy&scale=0.02)                 |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/glboost/index.html?model=Buggy&scale=0.02)                   |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/grimoiregl/index.html?model=Buggy&scale=0.02)                   |
|[Box Animated](https://github.com/cx20/gltf-test/raw/master/sampleModels/BoxAnimated)            |![](https://github.com/cx20/gltf-test/raw/master/sampleModels/BoxAnimated/screenshot/screenshot.gif)       |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/threejs/index.html?model=BoxAnimated&scale=1)        |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/babylonjs/index.html?model=BoxAnimated&scale=1)                             |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/cesium/index.html?model=BoxAnimated)       |:x: [Sample](https://cx20.github.io/gltf-test/examples/xeogl/index.html?model=BoxAnimated&scale=1) animation not support       |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/glboost/index.html?model=BoxAnimated&scale=1)                |:x: [Sample](https://cx20.github.io/gltf-test/examples/grimoiregl/index.html?model=BoxAnimated&scale=1) animation not support         |
|[Cesium Milk Truck](https://github.com/cx20/gltf-test/raw/master/sampleModels/CesiumMilkTruck)   |![](https://github.com/cx20/gltf-test/raw/master/sampleModels/CesiumMilkTruck/screenshot/screenshot.gif)   |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/threejs/index.html?model=CesiumMilkTruck&scale=0.5)  |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/babylonjs/index.html?model=CesiumMilkTruck&scale=0.5)                       |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/cesium/index.html?model=CesiumMilkTruck)   |:x: [Sample](https://cx20.github.io/gltf-test/examples/xeogl/index.html?model=CesiumMilkTruck&scale=0.5) animation not support |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/glboost/index.html?model=CesiumMilkTruck&scale=0.5)          |:x: [Sample](https://cx20.github.io/gltf-test/examples/grimoiregl/index.html?model=CesiumMilkTruck&scale=0.5) animation not support   |
|[Rigged Simple](https://github.com/cx20/gltf-test/raw/master/sampleModels/RiggedSimple)          |![](https://github.com/cx20/gltf-test/raw/master/sampleModels/RiggedSimple/screenshot/screenshot.gif)      |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/threejs/index.html?model=RiggedSimple&scale=0.2)     |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/babylonjs/index.html?model=RiggedSimple&scale=1) animation not smooth       |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/cesium/index.html?model=RiggedSimple)      |:x: [Sample](https://cx20.github.io/gltf-test/examples/xeogl/index.html?model=RiggedSimple&scale=0.2) animation not support    |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/glboost/index.html?model=RiggedSimple&scale=0.2)             |:x: [Sample](https://cx20.github.io/gltf-test/examples/grimoiregl/index.html?model=RiggedSimple&scale=0.2) animation not support      |
|[Rigged Figure](https://github.com/cx20/gltf-test/raw/master/sampleModels/RiggedFigure)          |![](https://github.com/cx20/gltf-test/raw/master/sampleModels/RiggedFigure/screenshot/screenshot.gif)      |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/threejs/index.html?model=RiggedFigure&scale=1)       |:x: [Sample](https://cx20.github.io/gltf-test/examples/babylonjs/index.html?model=RiggedFigure&scale=1) animation not work                        |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/cesium/index.html?model=RiggedFigure)      |:x: [Sample](https://cx20.github.io/gltf-test/examples/xeogl/index.html?model=RiggedFigure&scale=1) animation not support      |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/glboost/index.html?model=RiggedFigure&scale=1)               |:x: [Sample](https://cx20.github.io/gltf-test/examples/grimoiregl/index.html?model=RiggedFigure&scale=1) animation not support        |
|[Cesium Man](https://github.com/cx20/gltf-test/raw/master/sampleModels/CesiumMan)                |![](https://github.com/cx20/gltf-test/raw/master/sampleModels/CesiumMan/screenshot/screenshot.gif)         |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/threejs/index.html?model=CesiumMan&scale=1)          |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/babylonjs/index.html?model=CesiumMan&scale=1)                               |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/cesium/index.html?model=CesiumMan)         |:x: [Sample](https://cx20.github.io/gltf-test/examples/xeogl/index.html?model=CesiumMan&scale=1) animation not support         |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/glboost/index.html?model=CesiumMan&scale=1)                  |:x: [Sample](https://cx20.github.io/gltf-test/examples/grimoiregl/index.html?model=CesiumMan&scale=1) animation not support           |
|[Monster](https://github.com/cx20/gltf-test/raw/master/sampleModels/Monster)                     |![](https://github.com/cx20/gltf-test/raw/master/sampleModels/Monster/screenshot/screenshot.gif)           |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/threejs/index.html?model=Monster&scale=0.05)         |:x: [Sample](https://cx20.github.io/gltf-test/examples/babylonjs/index.html?model=Monster&scale=1) has nightmare dragon problem                   |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/cesium/index.html?model=Monster)           |:x: [Sample](https://cx20.github.io/gltf-test/examples/xeogl/index.html?model=Monster&scale=0.05) animation not support        |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/glboost/index.html?model=Monster&scale=0.05)                 |:x: [Sample](https://cx20.github.io/gltf-test/examples/grimoiregl/index.html?model=Monster&scale=0.05) animation not support          |
|[BrainStem](https://github.com/cx20/gltf-test/raw/master/sampleModels/BrainStem)                 |![](https://github.com/cx20/gltf-test/raw/master/sampleModels/BrainStem/screenshot/screenshot.gif)         |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/threejs/index.html?model=BrainStem&scale=1)          |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/babylonjs/index.html?model=BrainStem&scale=1)                               |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/cesium/index.html?model=BrainStem)         |:x: [Sample](https://cx20.github.io/gltf-test/examples/xeogl/index.html?model=BrainStem&scale=1) only partial                  |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/glboost/index.html?model=BrainStem&scale=1)                  |:x: [Sample](https://cx20.github.io/gltf-test/examples/grimoiregl/index.html?model=BrainStem&scale=1) animation not support           |
|[Virtual City](https://github.com/cx20/gltf-test/raw/master/sampleModels/VC)                     |![](https://github.com/cx20/gltf-test/raw/master/sampleModels/VC/screenshot/screenshot.gif)                |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/threejs/index.html?model=VC&scale=0.2)               |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/babylonjs/index.html?model=VC&scale=0.2)                                    |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/cesium/index.html?model=VC)                |:x: [Sample](https://cx20.github.io/gltf-test/examples/xeogl/index.html?model=VC&scale=0.2) animation not support              |:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/glboost/index.html?model=VC&scale=0.2)                       |:x: [Sample](https://cx20.github.io/gltf-test/examples/grimoiregl/index.html?model=VC&scale=0.2) glTF-Embedded not textured           |
|[WalkingLady](https://github.com/cx20/gltf-test/raw/master/sampleModels/WalkingLady)             |![](https://github.com/cx20/gltf-test/raw/master/sampleModels/WalkingLady/screenshot/screenshot.gif)       |:x: [Sample](https://cx20.github.io/gltf-test/examples/threejs/index.html?model=WalkingLady&scale=0.2) not work            |:x: [Sample](https://cx20.github.io/gltf-test/examples/babylonjs/index.html?model=WalkingLady&scale=1) not work                                   |:x: [Sample](https://cx20.github.io/gltf-test/examples/cesium/index.html?model=WalkingLady) has nightmare dragon problem |:x: [Sample](https://cx20.github.io/gltf-test/examples/xeogl/index.html?model=WalkingLady&scale=1) animation not support|:white_check_mark: [Sample](https://cx20.github.io/gltf-test/examples/glboost/index.html?model=WalkingLady&scale=1)               |:x: [Sample](https://cx20.github.io/gltf-test/examples/grimoiregl/index.html?model=WalkingLady&scale=1) animation not support         |

いかがでしょうか。静的な3Dデータは、概ねどのライブラリも表示できるようですが、スキニングアニメーションが、なかなかハードルが高いようです。

なお、最新のステータス比較およびglTFライブラリのサンプルは、以下で更新予定です。もしよろしければチェックしてみてください。

- glTF 対応ライブラリ別ステータス比較
  https://github.com/cx20/gltf-test
- glTF 対応ライブラリ別サンプル一覧（glTFファイル17モデル×3形式×7ライブラリ）
  https://cx20.github.io/gltf-test/

## 最後に

glTF 対応は、まだまだ実装半ばなライブラリが多い印象です。

もし使ってみて、挙動がおかしい事象を見つけたら、是非、サンプルと合わせて、各サポート掲示板に連絡してみてください。

きっと親切な方々が相談に載ってくれるでしょう。海外のライブラリが多いですが、機械翻訳でも、割と通じると思われます（たぶん）

それでは、皆様、よい WebGL ライフを♪

## 追記(2016.2.06)

サンプルに WalkingLady を追加しました。