エンティティ/コンポーネントシステムでマテリアルを処理する方法


13

私のE / C実装は、エンティティが単なるIDであり、コンポーネントがデータであり、システムがデータに基づいて動作する基本的な実装です。現在、私はオブジェクトのマテリアルとレンダリング全般に問題を抱えています。単純なオブジェクトの場合、ModelComponentに関連付けられているRenderSystemModelComponentは、レンダリングシステムが使用する頂点バッファーIDがあります。シンプルMaterialComponentはおそらく色や鏡面強度などを持っているでしょうが、複数のレンダーパスとの単純な変数ほど簡単ではない一般的な「効果」を可能にするのに十分な柔軟性が必要でしたMaterialComponent

これらの問題を解決しようとして、2つの解決策を思いつきました。

1-超汎用材料コンポーネント

このようなもの:

struct Material : public Component
{
    ShaderData* shader;
    std::vector<std::pair<std::string, boost::any>> uniforms;
    [...]
};

レンダリングシステムでは、ユニフォームをループしてシェーダーに渡します。これは遅いと思いますが、私の目的には十分な速さです。

2-別の抽象化レイヤー、MaterialData

特定のマテリアルをラップするクラスを持ち、それは特殊なマテリアルに継承できますが、基本クラスは次のようなものになりますvoid set_shader_constants(ShaderData* d)が、実装は各クラスにMaterialComponent依存し、MaterialDataオブジェクトへのポインターを持ちます。

私がどちらのアプローチを好むかはわかりませんが、これらはどちらも複数のパスや他の複雑なレンダリング技術の主題には触れません。

これを達成する方法についてのアイデアはありますか?

回答:


26

マテリアルはグラフィックの概念であり、レンダラーに属します。レンダラーは、エンティティシステムの上に構築するには低レベルのアーキテクチャです。エンティティシステムは、高レベルのゲームオブジェクト用である必要があります。すべてがコンポーネントである必要はありません。実際、すべてをそのような単一のパラダイムに強制しようとすることは一般に悪い考えです。最小公分母のソリューションを作成します。

したがって、別のアプローチを取ることをお勧めします。

  • マテリアルはレンダラーの別のタイプにすぎません。
  • レンダラーには、「画面に描画されるもの」を表すタイプがあります。多くの場合、これらは「レンダリングインスタンス」、「レンダリング可能」、または「モデル」と呼ばれます。この型は、描画時に使用するマテリアルへの参照を持ち、パブリックAPIを提供して、レンダラーのコンシューマがそのマテリアルを必要なものに設定できるようにします。

これは本質的にあなたを取るためにあなたを求めているModelComponentし、それを名前を変更しますModelし、エンティティ/コンポーネントレイヤーへの依存関係を削除し、レンダラーの残りと一緒に抽象化の下位レイヤーに移動するように求めています。

次に、これを行います:

  • 他のコンポーネントと同じ抽象化層に、エンティティの視覚的表現を表すある種の「アスペクトコンポーネント」があります。このコンポーネントには、(上記のように)レンダリング可能なものへの参照が含まれているだけです。これには、マテリアルへの参照が含まれています。コンポーネントは、レンダリング可能なオブジェクトを公開するためのAPIを提供する場合があり(したがって、クライアントがそれを操作できるようにする)、レンダリング可能なオブジェクトのAPIをラップして公開を制御する場合があります。それはあなた次第です。

これは、モデルとマテリアルの両方をコンポーネントにすることで、実行中のコンポーネントの相互依存の問題に対処します。エンティティにはアスペクトがあるかどうかがあり、そのアスペクトは、素材を含むエンティティの表示に関するすべてをエンコードできる必要があります。

また、これにより、レンダリングシステムの抽象化の残りの部分とのパリティが不足しているため、コンポーネントとしてそのオブジェクトを使用するのが困難になるマテリアルオブジェクトで他のアプローチを取る柔軟性が得られます。

より複雑なエフェクトと複数のパスを可能にするという問題は、マテリアルのシェーダーファイルによって公開される名前付きシェーダー定数をクエリおよび設定する関数を公開することにより、主にマテリアルで解決できる問題です。これは、複数のパスなどをサポートするエフェクトファイル(D3D)を使用する場合に特に当てはまります。エフェクトファイルを使用していない場合でも、それぞれ異なるシェーダーを使用して、マテリアルからの複数のパスのアイデアを公開し、マテリアルAPIがそのためのマニピュレーターを提供できるようにすることができます。マテリアルは現在、同じレベルの抽象化になっているため、レンダリングAPIに統合する方が簡単でクリーンです。


1
あなたの答えをありがとう、この問題はかなり長い間私を悩ませていましたが、E / Cの制約なしでレンダラーを作成することははるかに簡単です。
ルークB.
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.