重い3Dモデルを弱いGPUでもスムーズに動かす方法
想像してみてください:Sketchfabからクールなモデルをダウンロードしてエンジンにドロップすると、GPU悲鳴を上げながらもFPSが единицы桁まで落ちてしまう。ジオメトリはそんなに複雑に見えないのに、GPUが「窒息」している。問題はポリゴン数本身ではなく、メモリ上でのデータのレイアウトとレンダリングパイプラインへのデータの供給順序であることがよくある。
私はこれらの問題に体系的に取り組むmeshoptimizerリポジトリに出会いました。これは単なる「別のメッシュ簡略化ツール」ではなく、実際のレンダリング用にジオメトリを準備するための低レベルツールのセットです。プロジェクトの作者であるArseny Kaplutkin(zeux)は、グラフィックエンジン開発サークルでよく知られており、この专业知识がコードの每一行に表れています。
問題の核心とは
сучасний GPUは常にデータを供給し続ける必要がある野兽です。データを場当たり的に与えると、メモリの待機や同じ顶点の再計算に時間を浪費します。
一般的に、メッシュデータはいくつかのステージを通過します:
- メモリからのインデックスと顶点のフェッチ。
- 頂点シェーダー。
- ラスタライゼーション。
- ピクセルシェーダー。
三角形がバッファ内で無造作に配置されていると、顶点キャッシュが効率的に動作しません。GPUは数ミリ秒前に処理した顶点を再変換する必要があります。meshoptimizerはデータを再順序化してキャッシュ効率を最大化し、冗長な作業を最小限抑えます。
このライブラリできること
このプロジェクトは任意のプロジェクトに簡単に統合できるC++ファイルのセットです。重い依存関係はなく、純粋な数学とアルゴリズムだけです。
頂点キャッシュの最適化
これが基盤です。このアルゴリズムは、頻繁に使用される顶点がGPUキャッシュにより長く留まるように、三角形の順序を再構築します。コードでは可能な限りシンプルに次のように見えます:
この呼び出しの後、ACMR(平均キャッシュミス率)は通常劇的に低下します。これはモデル自体を変更せずに、文字通り免费のパフォーマンス向上です。
メッシュ簡略化
LOD(Level of Detail)を作成する必要がある場合、このツールは命綱です。シルエットと重要なディテールを維持しようとしめながらポリゴンをコラプスできます。トポロジーを気にしないが、非常に高速に動作し、非常に遠いオブジェクトに適した「ダーティ」モード(simplifySloppy)さえあります。
興味深い機能:簡略化子は属性と一緒に動作できます。テクスチャ座標や法線が「壊れる」ことになるなら、顶点を単に移動できないことを理解しています。
データの圧縮
あなたのゲームが100GBで、その半分がジオメトリなら、組み込みコーデックが好きになるはずです。顶点とインデックスをコンパクトなフォーマットにパックします。これはzstdやlz4の代替ではなく、それら補うものです。まずデータをmeshopt_encodeVertexBufferで処理し、その後通常の アーカイバで圧縮します。結果は印象的です:データは2〜4倍少ないスペースを占めることができます。
Mesh Shadersのサポート
新しいNVIDIAやAMDカードでMesh Shadersを使用している先进的な人にとっては、ライブラリはメッシュをmeshletに分割できます。これらは新しいプログラム可能なパイプラインモデルに 완벽하게適合する小さなジオメトリのピースです。
実践的なメリット
これは実際の生活でどのように使えますか?
- アセットパイプラインの最適化。パッケージに含まれる
gltfpackに基づいた小さなユーティリティを作成して、ビルド前にすべての.gltfモデルをオプティマイザ経由で自動的に処理できます。 - ジオメトリストリーミング。高度な圧縮のおかげで、モデルの読み込みが速くなり、オープンンワールドゲームにとって重要です。
- シャドウレンダリング。ライブラリを使用すると、位置専用の別個のインデックスバッファ(Shadow Indexing)を作成できます。これにより深度のみが必要な場所でGPUが重たいテクスチャ座標や法線データをドラッグする必要がないため、シャドウの描画が高速化されます。
技術的な実装
このライブラリはC++で書かれていますが、C互換インターフェースがあります。Rust(meshopt crate)とJavaScript(WebAssembly経由)用のラッパーがあります。
特に気に入った点:
- 隠れたアロケーションはありません。自分でメモリをアロケーションし、ライブラリは単にそこに書き込みます。
- 非常に高速です。頂点とインデックスのデコードは毎秒数ギガバイトで動作します。
- 最小限のマジック。すべてのアルゴリズムは文書化されており、分析関数を使用すると、メッシュがどれだけ改善されたかをすぐに確認できます(関数
meshopt_analyze*)。
誰が試すべきか
独自のエンジンを書いている場合、重いブラウザビジュアライザーで作業している場合、またはIntel統合グラフィックスでアプリケーションがLAGしないようにしたい場合、meshoptimizerは必須です。
始める 가장簡単な方法はコンソールユーティリティgltfpackを使用することです。重いモデルをそれに掛けて、任意のビューワーで結果を確認してみてください。品質損失なしにファイルサイズとレンダリングの滑らかさの差に気づくでしょう。
このプロジェクトは活発にメンテナンスされており、主要な商用エンジンで使用されています。これは1つの小さなライブラリがグラフィックパフォーマンスの問題の巨大なレイヤーをカバーする珍しいケースです。
関連プロジェクト