バックグラウンド:
私は、C ++とOpenGLを使用して、エンティティコンポーネントシステムタイプアーキテクチャ用のシンプルな3Dレンダリングシステムを設計しています。システムは、レンダラーとシーングラフで構成されています。レンダラーの最初の反復を終えたら、シーングラフをECSアーキテクチャーに配布します。今のところ、それは何らかの方法でプレースホルダーです。可能であれば、レンダラーの目標は次のとおりです。
- シンプルさ。これは研究プロジェクト用であり、システムを簡単に変更および拡張できるようにしたい(したがって、ECSアプローチ)。
- パフォーマンス。私のシーンには、多くの小さなモデルと、多くのジオメトリを持つ大きなボリュームがあるかもしれません。OGLコンテキストからオブジェクトを取得し、レンダリングフレームごとにジオメトリをバッファリングすることはできません。キャッシュミスを回避するために、データの局所性を目指しています。
- 柔軟性。スプライト、モデル、ボリューム(ボクセル)をレンダリングできる必要があります。
- 分離。レンダラーを作成した後、シーングラフがコアECSアーキテクチャにリファクタリングされる場合があります。
- モジュラー。シーングラフを変更せずに、さまざまなレンダラーを入れ替えることができると便利です。
- 参照透明度、つまり、いつでも有効なシーンを指定できるため、そのシーンでは常に同じ画像がレンダリングされます。特にこの目標は必ずしも必要ではありません。シーンのシリアル化を簡略化し(シーンの保存と読み込みができるようにする必要があります)、テスト/実験の目的で実行時に異なるシーンを入れ替える柔軟性が得られると思いました。
問題とアイデア:
私はいくつかの異なるアプローチを考え出しましたが、各レンダリングノードのOGLリソース(VAO、VBO、シェーダーなど)をキャッシュする方法に苦労しています。以下は、これまでに考えてきたさまざまなキャッシングの概念です。
- 一元化されたキャッシュ。各シーンノードにはIDがあり、レンダラーにはIDをレンダリングノードにマップするキャッシュがあります。各レンダーノードには、ジオメトリに関連付けられたVAOとVBOが含まれています。キャッシュミスはリソースを取得し、ジオメトリをキャッシュ内のレンダーノードにマップします。ジオメトリが変更されると、ダーティフラグが設定されます。レンダラーがシーンノードを反復処理しているときにダーティジオメトリフラグを確認すると、レンダラーを使用してデータを再バッファーします。シーンノードが削除されると、イベントがブロードキャストされ、レンダラーは関連するレンダーノードをキャッシュから削除し、リソースを解放します。または、ノードに削除のマークが付けられており、レンダラーがノードを削除する責任があります。このアプローチは、4と5も考慮しながら、最も厳密に目標6を達成すると思います。2は、配列アクセスの代わりにマップルックアップを使用すると、複雑さが増し、データの局所性が失われます。
- 分散キャッシュ。上記と同様ですが、各シーンノードにはレンダーノードがあります。これにより、マップルックアップがバイパスされます。データの局所性に対処するために、レンダーノードをレンダラーに保存できます。その場合、シーンノードは代わりにレンダリングノードへのポインターを持つことができ、レンダラーはポインターをキャッシュミスに設定します。この種のエンティティコンポーネントアプローチを模倣しているので、アーキテクチャの他の部分と一貫性があると思います。ここでの問題は、シーンノードがレンダラー実装固有のデータを保持することです。レンダラでのレンダリング方法を変更する場合(スプライトとボリュームのレンダリングなど)、レンダーノードを変更するか、シーンノードに「コンポーネント」を追加する必要があります(つまり、シーングラフも変更します)。プラス面では、これは、最初の反復レンダラーを起動して実行する最も簡単な方法のようです。
- 分散メタデータ。レンダラーキャッシュメタデータコンポーネントは、各シーンノードに格納されます。このデータは実装固有ではなく、ID、タイプ、およびキャッシュに必要なその他の関連データを保持しています。次に、IDを使用して配列内で直接キャッシュルックアップを実行できます。タイプは、使用するレンダリングアプローチのタイプ(スプライトとボリュームなど)を示します。
- 訪問者+分散マッピング。レンダラーはビジターであり、シーンノードはビジターパターンの要素です。各シーンノードは、レンダラーのみが操作するキャッシュキー(メタデータのようにIDのみ)を保持します。IDは、一般化されたマップ検索の代わりに配列に使用できます。レンダラーを使用すると、シーンノードのタイプに基づいてシーンノードが異なるレンダリング関数をディスパッチでき、IDは任意のキャッシュで使用できます。デフォルトまたは範囲外のIDは、キャッシュミスを示します。
この問題をどのように解決しますか?それとも何か提案はありますか?私のテキストの壁を読んでくれてありがとう!