glTFをGLBに変換する方法(単一ファイルの3Dモデル)
glTF vs. GLB:この2つのフォーマットの本当の違いとは
核心部分では、glTFとGLBは同じものです。どちらも同じKhronos Groupの仕様で定義されており、同一のデータ構造を共有し、同じPBRマテリアル、アニメーション、シーン階層をサポートしています。唯一の本当の違いは、パッケージングの方法です。 標準的なglTFアセットは、常に一緒にしておく必要があるファイルの集合体です。まず、シーン、マテリアル、メッシュのトポロジーを記述した、人間が読める.gltf JSONファイルがあります。その隣には、頂点位置、法線、UVなどの生のジオメトリデータを保持する1つ以上の.binファイルがあります。さらに、通常はPNGやJPEG形式のテクスチャ画像が入ったフォルダも存在します。中程度に複雑なキャラクターモデルは、character.gltf、character0.bin、そして10枚の画像が入ったtextures/フォルダとして提供されるかもしれません。これらのファイルの1つでも失うと、モデルは単純に読み込めなくなります。 一方、GLBはバイナリコンテナ版です。JSON、バイナリデータ、そしてすべてのテクスチャを1つの.glbファイルにきれいにパックします。これは、マジックナンバー(0x46546C67、ASCIIで'glTF')、バージョンフィールド(現在は2)、そして総ファイル長を含む、わずか12バイトの小さなヘッダーによってまとめられています。ファイルの残りの部分は、データチャンクの連続にすぎません。 これにより、GLBファイルは完全に自己完結型になります。パスの破損やテクスチャの欠落を心配することなく、メールで送信したり、ウェブベースのプロダクトコンフィギュレータにドロップしたり、クライアントに渡したりできます。ファイルサイズは、元のバンドルと比べてほとんどの場合1〜3%の差しかなく、この絶大な利便性のためにストレージのペナルティを支払うことは実質的にありません。
glTFをGLBに変換すべき時(と、すべきでない時)
最終的な納品やデプロイメントには、私はいつもGLBをデフォルトにしています。単一の自己完結型ファイルというシンプルさは、見過ごすにはあまりにも魅力的です。しかし、活発な開発中は、複数ファイルのglTF形式を使い続ける方が、実は賢い選択だったりします。 GLBへの変換が最も効果的なのは、model-viewer、Babylon.js、Three.jsのようなウェブビューワーにモデルをデプロイする場合です。1回のフェッチリクエストは、各バイナリファイルやテクスチャに対する滝のようなネットワーク呼び出しよりも常に優れています。4MBのGLBは、モバイル接続において、120KBの.gltf、2.1MBの.bin、そして合計1.8MBの6つのテクスチャに分割された同じモデルよりも著しく速く読み込まれます。なぜなら、個別のファイルはそれぞれ独自のHTTPラウンドトリップを必要とするからです。また、クライアントやマーケットプレイスに配布する際もGLBに変換すべきです。Unity Asset Store、Sketchfab、AppleのAR Quick Lookパイプラインのようなプラットフォームはすべて、GLBとシームレスに連携します。 では、複数ファイルのglTFはどこで輝くのでしょうか?それはコンテンツ制作中です。テクスチャアーティストが2Kのラフネスマップを繰り返し修正している場合、新しいPNGをtexturesフォルダにドロップしてリフレッシュするだけです。これは、毎回アセット全体を再パックするよりもずっと高速です。同じロジックは、自動化されたビルドシステムにも当てはまります。パイプラインがKTX2やBasis Universalのバリアントを生成するためにテクスチャ圧縮を実行する場合、ビルドごとにGLBをアンパックしてリパックするよりも、個々のバラバラのファイルを操作する方がはるかに簡単です。 そして、覚えておくべき重要な制約があります。設計上、GLBは外部テクスチャを参照できません。もし元のglTFがCDN上のテクスチャにリンクするように巧妙に設定されていた場合(複数のモデル間でテクスチャアトラスを共有するためのパターン)、GLBに変換するとローカルコピーが埋め込まれ、その共有リソースのパターンが壊れてしまいます。
CocoConvertを使ってglTFをGLBに変換する方法
CocoConvertのブラウザベースのツールを使うのが、ソフトウェアのインストールが不要なので、GLBを手に入れる最も簡単な方法です。100MB未満のファイルであれば、プロセス全体がクライアントサイドで動作するため、あなたの貴重なジオメトリやテクスチャデータがマシンから外に出ることはありません。 ステップ1 — ファイルを準備する。glTFアセットはパッケージのようなものなので、すべてを一緒にアップロードする必要があります。これを行う唯一の方法は、.gltfファイル、関連するすべての.binファイル、そしてtexturesフォルダ全体を1つのアーカイブにzipすることです。内部のフォルダ構造をそのまま維持することが非常に重要です。.gltfファイルは`./textures/baseColor.png`のような相対パスに依存しており、コンバーターがzip内でこれらのパスを正しく認識する必要があります。 ステップ2 — コンバーターを開く。/convert/gltf-to-glbにアクセスして、アップロードエリアをクリックするか、.zipファイルをページにドラッグ&ドロップするだけです。このツールは賢いので、自動的にglTFのエントリポイントを見つけ出します。何らかの理由でzipに複数の.gltfファイル(LODバリアントなど)が含まれている場合は、ドロップダウンが表示され、ルートとして使用する正しいファイルを選択できます。 ステップ3 — 変換オプションを確認する。CocoConvertにはいくつかの設定があります。「テクスチャを埋め込む」はデフォルトでオンになっており、これは真の単一ファイルGLBにまさに求めているものです。もしこれをオフにすると、出力は外部のテクスチャURIを参照することになり、変換の目的そのものを台無しにしてしまいます。もう一つのオプションは「バッファをフラット化」です。私からのアドバイス?これは有効のままにしておきましょう。これにより、複数の.binファイルが単一のバイナリチャンクにマージされ、これは標準的なGLBの動作です。 ステップ4 — ダウンロードする。以上です。変換は通常、テクスチャの数や総ファイルサイズに応じて5秒から20秒ほどかかります。デプロイ準備が整った単一の.glbファイルが手に入ります。
コマンドラインの代替手段:gltf-pipelineを使った自動化ワークフロー
ビルドパイプラインの一部として何十ものモデルを変換する場合、Web UIを一つ一つ使うのは現実的ではありません。あらゆる種類の自動化ワークフローには、Cesiumチームが提供するNode.jsツール、gltf-pipelineが最も信頼できるオープンソースの選択肢です。 まず、npmでグローバルにインストールします:`npm install -g gltf-pipeline`。単一のアセットの変換は簡単です:`gltf-pipeline -i scene.gltf -o scene.glb`。-iフラグは入力の.gltfファイルを指します。Webツールとは異なり、gltf-pipelineは同じディレクトリ内にある関連する.binファイルやテクスチャを自動的に見つけるため、何もzipする必要はありません。出力ファイル名が.glbで終わる場合、-bフラグ(--binary用)は暗黙的に指定されるので、これは便利な点です。 ディレクトリ全体をバッチ処理するには、簡単なシェルループが役立ちます:`for f in models/*.gltf; do gltf-pipeline -i "$f" -o "${f%.gltf}.glb"; done`。Windows PowerShellでの同等のコマンドは`Get-ChildItem -Filter *.gltf | ForEach-Object { gltf-pipeline -i $_.FullName -o ($_.FullName -replace '.gltf','.glb') }`です。 gltf-pipelineは、--draco.compressionLevelフラグ(値は0〜10、デフォルトは7)でDracoメッシュ圧縮もサポートしています。メッシュが密なモデルには、絶対にこれを有効にすべきです。ジオメトリのサイズを60〜80%も削減できます。非圧縮で18MBの50万ポリゴンのスキャンデータが、Dracoレベル7で約4MBにまで縮小できます。ブラウザでのデコード時間がわずかに長くなりますが、ほとんどの場合、それに見合う価値があります。 このツールの唯一の大きな制限は、テクスチャ圧縮(KTX2/Basis)を扱えないことです。そのためには、GLBをパッケージ化する前か後に、toktxやbasisuのようなツールを使ってパイプラインに別のステップを追加する必要があります。
デプロイ前にGLB出力を検証する
このステップをスキップしないでください。あるビューワーでは完璧に開けるGLBが、別のビューワーでは非準拠のデータが含まれているために静かに失敗することがあります。変換したアセットを出荷する前に、検証をプロセスの一部として標準化しましょう。 KhronosのglTF Validatorが唯一の信頼できる情報源です。validator.khronos.orgでオンラインで利用できます。.glbをページにドラッグするだけです。エラー、警告、その他の情報が詳述された構造化JSONレポートが出力されます。エラーは致命的な問題です。アクセサのcomponentTypeの不一致や、宣言されたバッファ長を超えるバッファビューのような問題は、ほとんどのローダーがファイルを即座に拒否する原因となります。警告はそれほど深刻ではありませんが、それでも読む価値はあります。よくある「MESH_PRIMITIVE_UNUSED_TEXCOORD」のような警告は、単にどのマテリアルも使用していないUVセットがあることを意味します。 自動化パイプラインの場合、バリデーターをNodeパッケージとしてインストールできます:`npm install -g gltf-validator`。その後、`gltf-validator scene.glb --stdout > report.json`を実行し、そのレポートをCIチェックにパイプします。エラー数がゼロより大きい場合、ビルドは絶対に失敗させるべきです。 厳密な仕様準拠だけでなく、少なくとも2つの異なるレンダラーで必ずビジュアルチェックを行いましょう。私のおすすめは、model-viewer(modelviewer.dev)とBabylon.js Sandbox(sandbox.babylonjs.com)です。これらは異なるWebGL実装を使用しており、微妙なマテリアルの問題をあぶり出すのに優れています。DCCツールでは問題なく見えた法線マップが、ウェブ上では不思議なことに反転してしまうという問題に苦労したことがある人なら、この痛みがわかるでしょう。glTF仕様ではOpenGLスタイルの法線(Y-up)が必要ですが、多くのツールはデフォルトでDirectXスタイル(Y-down)をエクスポートします。ライティングが反転した凹凸のように見える場合は、法線マップのグリーンチャンネルを反転させて再変換してください。
よくある変換エラーとその修正方法
glTFからGLBへの変換エラーのほとんどはイライラさせられますが、ありがたいことに、修正方法は単純です。ここでは、何度も繰り返し発生する問題を紹介します。 出力にテクスチャがない:これが最大の問題です。原因はほとんどの場合、変換中に.gltfファイルのテクスチャURIパスが解決されなかったことです。これをデバッグするには、.gltfをテキストエディタで開き、images配列を見つけます。`"uri": "textures/Material_baseColor.png"`のようなエントリがあるはずです。zipアーカイブ内または作業ディレクトリ内で、それらのファイルがまったく同じ相対パスに存在することを確認する必要があります。サーバー上ではパスの区切り文字や大文字と小文字の区別が重要であることを覚えておいてください:`Textures/BaseColor.png`は`textures/baseColor.png`と同じではありません。 出力ファイルが大きすぎる:GLBが予期せず大きい場合、原因はほぼ間違いなくテクスチャです。1つの4096×4096 RGBA PNGは、メモリ内で非圧縮だと64MBにもなり得ます。PNG自体は可逆圧縮を使用していますが、GLBは生のPNGファイルのバイトをそのまま埋め込むだけです。つまり、12MBのPNGテクスチャはGLBに12MBを追加します。Web用途では、テクスチャを2048×2048にダウンサンプリングするか(視覚的な違いはしばしば無視できる程度です)、GLBをパックする前にKTX2圧縮を適用することを真剣に検討すべきです。 アニメーションが再生されない:ソースのglTFにスケルタルアニメーションがあったのに、GLBでそれがなくなってしまった場合、アニメーションデータが含まれていなかった可能性が高いです。一部の3Dエクスポーターは、アニメーションデータを別の.binファイルに書き込みます。そのファイルが変換の入力に含まれていなかった場合、アニメーションデータは単純に失われます。修正方法は、3Dツールから再エクスポートし、すべてのバイナリデータが単一の.binファイルに書き込まれるようにしてから、再度変換を実行することです。 CocoConvertは、アーカイブ内で見つけられなかった参照ファイルが検出された場合、ログに警告を報告します。ダウンロードする前に必ずログを確認してください。
ファイルサイズ、パフォーマンス、そして実際のプロジェクトで期待できること
理論はさておき。漠然とした約束よりも、具体的な期待値の方が良いでしょう。そこで、典型的なアセットで変換プロセスが実際にどのように見えるかをご紹介します。 シンプルな家具モデル(メッシュ1つ、マテリアル2つ、1Kテクスチャ4枚)は、3.2MBの複数ファイルglTFバンドルから始まるかもしれません。変換後は、3.1MBのGLBになります。このわずかなサイズ削減は、JSONの空白をなくし、バッファヘッダーを統合することによるものです。高速な接続のデスクトップでは、読み込み時間の違いに気づかないでしょう。しかし、4Gのモバイル接続では、その単一ファイルのGLBは、複数のHTTPリクエストのオーバーヘッドを避けることで、300〜500ミリ秒早くレンダリングを開始します。 次に、スケルタルアニメーション、12個のマテリアル、2Kテクスチャを持つ複雑なキャラクターを考えてみましょう。これは28MBのglTFバンドルになる可能性があります。プレーンなGLBでは約27.4MBです。ジオメトリにDraco圧縮を追加すると、約22MBまで落ちるかもしれません。しかし、最初にKTX2 Basis Universalテクスチャ圧縮を適用すれば、最終的なGLBは9〜11MBという小ささになる可能性があります。CocoConvertは基本的なglTFからGLBへのパッケージングを完璧に処理しますが、現在DracoやKTX2は適用しません。これらの高度な最適化のためには、別のステップでgltf-pipelineやtoktxのようなツールを使用する必要があります。 ARプロジェクトでは、ファイルサイズが非常に重要です。AppleのAR Quick LookとGoogleのScene Viewerはどちらも文書化された制限があります。Appleは、モバイルネットワーク上で確実に読み込むためにGLBを20MB未満に保つことを推奨しています。Googleのハードリミットは200MBですが、良好なパフォーマンスのためには15MB未満を推奨しています。変換したGLBがこれらの制限を超えている場合、すぐにジオメトリ単純化ツールに手を伸ばさないでください。最初に行うべきで、最もインパクトの大きい手段は、ほとんどの場合、テクスチャ圧縮です。 /convert/gltf-to-glbでの変換自体は、3Dデータ(ジオメトリ、マテリアル、アニメーション、シーン階層)に関してはロスレスです。入力したものがそのまま出力されます。ただ、最大限の移植性のために再パッケージ化されるだけです。