4

私が理解している限りでは、VAO は特定の状態を表します。VAO をバインドする場合、いくつかの VBO と要素バッファーを追加して、インデックスなどを描画し、アクティブ化したいオブジェクトの特定の状態を保存し、後でレンダリングしたいときに簡単に描画できます。右?

VBOは実際のデータを保持しますが、VAOは定義したすべてのバッファへのポインタを保持する単なる「ラッパーオブジェクト」ですか?

VAO の変更にはコストがかかります (VBO の変更と同様に?!)。現在、メッシュをロードしてモデルに結合しています。各モデルは独自の VAO を使用し、VBO (頂点を含む) と要素バッファーとそのインデックスを持ちます。

私がこれを理解しているように、これはでたらめです。私の世界の各オブジェクト (モデルを持つ) は独自の VAO を使用します。私の世界の約 30 個のオブジェクトでは問題ありませんが、これを正しく行いたいと思っています。将来、数百または数千のオブジェクトが存在する可能性があり、パフォーマンスが大幅に低下する可能性があります。

そのため、多くのオブジェクトはモデルに関して「同じ」です。たとえば、世界に特定のツリータイプがある場合、同じモデルを異なる場所で複数回使用する可能性があります。

さて、これについてどうすればよいでしょうか?VAO を次のように手動で追跡する必要があります: (疑似コードに続く!)

treesVAOId = 1;
rabbitsVAOId = 2;

次に、モデルをロードする場合は、ID が既にバインドされているかどうかを確認し (どのように?)、そこに別の VBO のセットを追加します (または、正しい VBO に追加しますか? その場合、どのように?)

ここで大きなゲームを考えています。ゲームには何千ものキャラクターがいるとしましょう。これらすべてが同時にレンダリングされるわけではありませんが、それぞれに VAO と VBO を作成することはできません。

大部分が欠けているように感じます...インスタンス化して、(多かれ少なかれ)同じデータを別の目的で効率的に使用するなどです。

それは私が見逃している 1 つのステップであり、現実の世界で VAO と VBO の使用を実際に最適化する方法です。

4

2 に答える 2

7

ここで説明したことは、リソース マネージャーまたは少なくともリソース マネージャーの一部と呼ばれます。外部ファイルにリソースを記述することは良い方法であるため、すべてのメッシュが何らかの方法で記述されているリソース ファイルが必要です (XML または JSON の使用を検討してください)。

クラス階層

クラス階層への可能なアプローチは次のとおりです。

各 VAO はメッシュを表し、頂点座標、テクスチャ座標、法線、頂点カラーなどを定義します。視覚化の非常に特殊なケースが発生するまで、複数の VAO で同じ VBO を使用する理由はないと思います。つまり、VAO を使用するクラスは、基礎となる VBO について何も認識してはならず、VBO のクラス ラッパーを記述する必要はありません。

メッシュのセット (おそらく 1 つのメッシュのみを含む) は、モデルを表します。最小限のモデル クラスには、VAO へのハンドルとジオメトリ変換情報 (回転、変換など、必要なもの) を含める必要があります。モデルごとに厳密に 1 つのメッシュにしないのはなぜですか? 場合によっては、1 つの変換をメッシュのグループに適用する必要がある場合があります。これらのメッシュには、独自のモデル ローカル変換があります。たとえば、このような構成は、一種の骨格アニメーションに使用したり、可能な武器のライブラリから取得した任意の武器でキャラクターをレンダリングしたりするために使用できます。さらに、そのようなモデルをグループ化して、同じインターフェイスを持つより複雑なモデルを作成することができるため、シーン グラフに似たものになります。とにかく、モデル クラスに複合パターンを使用することをお勧めします。

シーンには、モデル、光源、力場などのコレクションが含まれている必要があります。

リソースマネージャー

しかし、シーン (または同様のゲーム オブジェクト) はどこからモデルを取得するのでしょうか? リソース マネージャーは、この質問に答える必要があります。ある種の一意の識別子で定義された各モデルを作成します。最も単純なケースでは、実際のファイルシステムまたは仮想ファイルシステムのパスを識別子と見なすことができますが、あまり柔軟ではありません。私の考えでは、人間が読める表現力のある名前を使用してリソース ファイル内のすべてのメッシュを定義し、各名前を一連のデータ (すべてのタイプの座標、色など) と属性にバインドする方がよいでしょう。すべてのコードでモデルを直接使用するべきではありませんが、リソース マネージャーから提供されたハンドルを使用する必要があります。明らかに、リソース マネージャーは、プログラムの実行中およびさまざまな場所からの呼び出しの間で状態を保持する必要があります。どのメッシュが既にメモリに保存されているかを追跡し、保存されているすべてのメッシュの VAO 識別子を保持することを目的としています。使用を検討してくださいリソース マネージャーのシングルトンパターン。

例:

ModelHandle footman = resMan->getModel("footman.model");
//.....
footman->setLocation(x,y,z);
footman->draw();

ここで getModel("footman.model") の呼び出しにより、モデルの構築が開始され、次のような呼び出しが発生します。

MeshHandle resMan->getMesh("footman1.mesh");

すべてのメッシュを取得します。そしてgetMesh、仕事はこのすべての説明を引き起こしましたか. そのようなメッシュが以前にロードされたかどうかを確認し、ロードされている場合は、このメッシュを含む VAO にハンドルを返します。それ以外の場合は、新しい VAO オブジェクトを作成し、要求されたデータをロードして、新しく作成されたオブジェクトへのハンドルを返します。このオブジェクトの後続のすべての要求は、新しい VAO 割り当てを引き起こしません。

確かに、説明されているシーン グラフの構成は、それがどのように見えるべきかについての大まかな概算にすぎません。たとえば、モデル ノードと抽象シーン グラフ ノードは区別されませんが、エンジン用にそのような階層を開発および微調整するのはユーザー次第です。

リソース マネージャー クラスへの最終的なインターフェイスは、議論および設計すべきもう 1 つのトピックです。いくつかの質問とアイデア:

  • シングルトンを使用しますか、それとも何らかの理由でグローバル変数を使用することにしますか?
  • シングルトンを使用することに決めた場合、リソースの限られたセットに対して、シングルトン以外のプライベート リソース マネージャーをいくつか用意したいと思うかもしれません。次に、そのようなコードを可能にするために、シングルトンをラッピング テンプレート クラスとして設計することを検討してください。
    ResourceHandle h1 = Singleton<ResourceMan>::instance->getResource("foo");
    ResourceMan myPrivateManager;
    ResourceHandle h2 = myPrivateManager.getResource("bar");
  • 1 つの包括的なマネージャーですべての種類のリソースを管理しますか?それともリソースの種類ごとに特別なマネージャー クラスを使用しますか? 2番目のアプローチの方が優れています。2番目のアプローチのアイデアを開発し、コンパイラにコードを書いてもらいます! 特殊なメソッドの小さなサブセットでテンプレート リソース マネージャー クラスを使用します。リソースの種類ごとに 1 つのリソース作成メソッドを特殊化するだけで、他のすべてのリソース管理コードは変更されません!
  • リソースの有効期間を考えてください。特定の VAO をいつ破棄する必要がありますか? 参照カウンターや借用参照の実装を検討してください。
  • キャッシング?デバイス (ビデオ カード) にロードした直後にホスト メモリからデータを削除しますか、それともしばらく保持しますか? どれだけの時間?
  • ストリーミングはどうですか?リソース マネージャーのドメインであってはなりませんが、ストリーミング サポートによって影響を受ける可能性があります。
  • glIsVertexArray関数とその類似物が役立つ場合があります。

並べ替え

シーンのレンダリング中に変更する必要があるリソースは、VAO だけではありません。テクスチャ、シェーダー、さらにはフレームバッファーも変更する必要があります。状態変更の回数を減らす一般的な方法は、表示可能なオブジェクトを何らかのプロパティで並べ替えることです。

たとえば、特定のメッシュを 1 つのシェーダーだけでレンダリングする可能性が非常に高くなります。そのため、最初にすべてのメッシュをシェーダーごとに並べ替えて、シェーダーの変更の数を最小限に抑えます。次に、シェーダーごとに (つまり、特定のシェーダーのメッシュのリスト内で)、VAO ごとにメッシュを並べ替えて、VAO の変更の数を実行可能な数に減らすことができます。最小。テクスチャで並べ替えますか?オブジェクトをテクスチャで並べ替える必要があるかどうか、およびそれをどこで行うかは、アプリケーションによって異なります。

結論

要約すると、ゲーム エンジンを作成する場合は、とにかくリソース マネージャーが必要になります。VAO の簡単な部分的な解決策を作成すると、テクスチャ、追加のフレームバッファ、およびその他の多くのオブジェクトを処理する際に、まったく同じ質問と問題に直面することになるため、優れたリソース マネージャーを一度実装することをお勧めします。

最初に役立つ記事:

http://www.gamedev.net/page/resources/_/technical/game-programming/a-resource-manager-for-game-assets-r3807

http://www.gamedev.net/page/resources/_/technical/game-programming/a-simple-fast-resource-manager-using-c-and-stl-r2503

非常に役立つ本:

http://www.gameenginebook.com/

于 2015-04-08T17:52:58.913 に答える