国際規格 VRM も採用した、"世界統一" 3D シーン保存規格 glTF とは

OpenGL や Vulkan など、特定の企業やプラットフォームに依存しない国際規格を定義・管理する [Khronos Group](https://www.khronos.org/) という所があります。

そこが提唱し、今世界中で注目されているのが **glTF** という新しいフォーマット(規格)です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332028/71b6d959-53e3-52d9-d4d7-f4b5546cd496.png)
(from: [KhronosGroup/glTF: glTF – Runtime 3D Asset Delivery](https://github.com/KhronosGroup/glTF))

これは一体どのようなフォーマットなのでしょうか。

## "世界統一" 3D シーン保存規格 glTF

> GL トランスミッションフォーマット(glTF) は API 中立な **ランタイムアセットのデリバリフォーマット** です。 glTF は 3D 作成ツールとモダンな 3D アプリケーションを、効率的で拡張可能な相互運用可能フォーマットを通して 3D コンテンツを伝送しロードすることでそれらを橋渡しします。
> (from: [glTF Overview - The Khronos Group Inc](https://www.khronos.org/gltf/))

昨今、 3D モデルは、各企業や団体が開発した 3D モデリングツール(Maya や Blender など)でモデルを制作し、それをランタイムであるゲームや映画のレンダリングなどで利用します。

例えば Unity であれば [Unity - マニュアル: 3D アプリケーションからモデルをどのようにインポートしますか?](https://docs.unity3d.com/jp/460/Manual/HOWTO-importObject.html) にも書かれている通り、 `obj` や `fbx` などを主体に、様々なフォーマットを読み込むことが出来るようになっています。

しかし、それらのフォーマットは **ランタイムよりも制作時の使いやすさ** をベースとして作られていることが多く、実際に動かすときには無駄なデータが入ったり、変換が必要だったりします。

ゲームなどのリアルタイムレンダリングを求められる場所では、 **「よりランタイムに優しいフォーマット」** が求められます。

そこで登場したのがこの **glTF** フォーマットです。

モチベーションの欄にはこう書かれています(一部を要約)。

> これまでの伝統的な 3D モデルフォーマットはオフラインでの利用が想定されていて、ダウンロード速度やランタイムの読み込み速度に最適化されていませんでした。今後は WebGL や OpenGL ES などで手軽にモデルを共有していくことが予想されるため、様々なユーザ・アプリケーション・端末で効率的にダウンロードし展開出来る共通フォーマットが必要になってきました。
> glTF では、 JSON によるシーンの説明と、ジオメトリやアニメーションをそのまま GPU バッファに乗せれる形のバイナリで提供し、ベンダーやランタイムに依存せず、シーンをノード、メッシュ、カメラ、マテリアル、アニメーションなどを階層構造で保持しデリバリし素早く読み込めます。
> (from [glTF/README.md at master · KhronosGroup/glTF](https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#motivation))

頂点座標やアニメーションデータなどのバッファ(同じデータの配列)は GPU が読み込む時と同様のバイナリ形式を利用し、シーン全体の構成や要素の関連、マテリアルの材質設定などは一般的な `json` フォーマットで記述することで、わかりやすく高速という二つのメリットを持ったフォーマットになりました。


## 3D モデル界 の JPEG を目指す

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332028/de4b36be-414b-50c5-75b9-c6ed6a6819ca.png)
(from: [glTF Overview - The Khronos Group Inc](https://www.khronos.org/gltf/))

画像に `jpeg`, 映像に `H.264`, 音声に `mp3` を使っているように、 3D モデルはその多くを `glTF` で表現していきたいというのが Khronos Group の考えです。

既に多くのアプリケーションやサービスがこのフォーマットに対応し、既に **世界で共通のフォーマット** と呼んでも良いかもしれません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332028/51ee0a1a-23d1-aca2-ac4b-ebfcb4debcd0.png)
(from: [glTF Overview - The Khronos Group Inc](https://www.khronos.org/gltf/))

Windows 10 では、デフォルトで glTF ビューアが内蔵されているため、手軽に glTF モデルに触れることができます。

## glTF 仕様

少し仕様を確認してみます。

デザインゴールとして下記が挙げられています。

- コンパクトなファイルサイズ
- 素早い読み込み: glTF データ構造は GPU API データと出来るだけ同一になるようになっているため、パースなどの追加作業を必要としないので素早い読み込みが可能
- ランタイム独立: 3D エンジンに依存しない
- 3D シーン全ての表現: 1 つのオブジェクトをエクスポートするのはアプリケーション的にふさわしくない。複数のシーンを一気に読みたい
- 拡張性: 今後の成長や改善に耐えうる拡張の仕組み

これを実現するため、シーンをutf8文字列で表現する `json` 部分と、 GPU API と同一のデータ構造を持つバイナリ部分、そして `png` または `jpg` のテクスチャの三種類に分けられました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332028/f55b5d84-f497-ea58-395c-e2b6b1a5bbbf.png)
(from: [glTF/README.md at master · KhronosGroup/glTF](https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#motivation))

また、シーンはノードベースの階層構造で表現されるため、人型モデル一つ、や、建物一つ、だけでなく、それらの複合体も 1 つの glTF で定義することが可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332028/39685173-f6d4-656c-4d8b-0608add2e6d8.png)
(from: [glTF/README.md at master · KhronosGroup/glTF](https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#motivation))

細かい要素については省きますが、バイナリの位置を参照するための `bufferView` や `accessor` 、マテリアルの定義やスキンメッシュ(ボーン構造)など、 3D モデルを表現するのには十分な仕組みになっています。 json で構成されているためパーサの作成も簡単です。

また、仕様内で _Physically-Based Rendering_ (物理ベースレンダリング)をサポートしていることも特徴に挙げられます。

## Web ブラウザでの表現

このフォーマットは、ブラウザ上で 3D を表現する WebGL でも活躍出来るように作られています。

[glTF Sample Viewer](http://github.khronos.org/glTF-Sample-Viewer/): これは[公式のサンプルビューア](https://github.com/KhronosGroup/glTF-Sample-Viewer)ですが、ブラウザ上でも快適にモデルを読み込むことが出来るのを体感してもらえると思います(GPU を積んでない PC だとさすがに重いですが...)。

現在各種 WebGL フレームワークが glTF 対応を行っており、 [three.js](https://threejs.org/examples/webgl_loader_gltf.html), [babylon.js](https://www.babylonjs.com/demos/gltf/) など、「とりあえず `glTF` で出力しておけば WebGL で出せる」というレベルまで来ています。


## 拡張性

デザインゴールの一つとして挙げられていた **拡張性** も十分にあります。

既に Khronos Group やそのほかベンダーが提供している拡張が[たくさんあります](https://github.com/KhronosGroup/glTF/tree/master/extensions)。

DDS テクスチャ対応や、 Google が提唱するジオメトリ・ポイントクラウドの新しい圧縮フォーマットである [google/draco](https://github.com/google/draco) 対応など、基礎的な部分を拡張するものが多いです。

しかし、定義は `json` なのですから、別にそこに何を入れても構いません。

## VR 空間向け人型アバターフォーマット "VRM"

3D モデルでも、特に **「VR 空間での人型アバター」** を制作する際、便利になる定義を独自の拡張として実装したのが **[VRM](https://vrm.dev/)** です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332028/2616444e-39ae-9c80-c24a-f14c81ad6242.png)
(from: [VRM](https://vrm.dev/))

これは 2019 年 4 月 24 日に設立された [VRMコンソーシアム](https://vrm-consortium.org/) と呼ばれる団体が提唱している規格で、現在公式で [Unity 対応の UniVRM](https://github.com/vrm-c/UniVRM) が実装されています。

VRM のデザインゴールとしては下記が挙げられています。

> 「人型のキャラクターやアバター」において、細かいモデルデータの差違を吸収・統一し、アプリケーション側の取り扱いを簡単にする
> from: [「VRM」って何？どんなことができる？ - VRM](https://vrm.dev/vrm_about/)

例えば、 glTF では定義されていない「T-Pose 固定」であるとか、「ボーンに回転やスケールを入れない」という制約を入れるなどして、手軽に **「自分のアバター」** を動かせるようになっています。

VR アプリで一人称視点の時に頭を描画しないようにする定義や、このモデルに対してのライセンス表記、「あいうえお」の口の動きを事前に登録しておくなど、実際にアプリで利用される際に **「あると便利だなー」** という仕様が含まれています。詳しくは [VRM仕様 - VRM](https://vrm.dev/vrm_spec/) をご確認ください。

VRM コンソーシアムの会員一覧を見てわかる通り、既にアジア圏で主要な IT 企業が並んでいます。このフォーマットは去年生まれたばかりなので、今後世界的にも有名になり一般化されるかもしれません。

現在この VRM フォーマットを利用出来るアプリケーションは [ここに乗っていますが](https://vrm.dev/vrm_applications/)、これを書いている 2019/04/25 現在で 41 個です。今後数えきれないくらいたくさんのアプリケーションが対応してくれるのを楽しみにしています。