2011-10-18 4 views
1

CryEngine3のようなSeriouseグラフィックスエンジン、Unreal Engine 3はカスタマイズされたシェーダ言語とエフェクトシステムを持っています。私の小さなグラフィックスフレームワークのためのエフェクトシステムを探しているうちに、nvidia CgFxが唯一の選択です(KhronosはglFxというプロジェクトを持っていたようですが、プロジェクトページは現在404です)。CgFxのようなエフェクトシステムを作成するには?

  1. 私はシェーダのパラメータを渡す方法と時期についての詳細な制御を必要とする:

    は、私は自分の効果のシステムを作るためにいくつかの理由があります。

  2. シェーダスニペットを再利用するために、メカニズムのようないくつかのC++マクロを作成したいと思います。マクロを使用して条件付きコンパイルを行うことや、CryEngineがさまざまなエフェクトを生成するために使用した方法も便利です。
  3. GLSLは、そのような効果システムに

を持っていないようなので、私は効果のシステムを作成する方法を疑問に思って見えますか?文法パーサーを一から作成する必要があるのですか、それともすでにこのようなことができるコードやツールがありますか?

PS:GLSLとCGの両方でOpenGLを使用しています。

答えて

4

私はHLSLを使用していた頃に少しのシェーダシステムを開発しました。データを使ってすべてのパラメータを指定できるので、パラメータリストとシェーダを含むXMLファイルを編集できますコードを保存した後、エンジンは自動的に再読み込みし、すべてのパラメータを再バインドします。

これはUDKのものと何も比較できませんが、かなり便利です。

私はそれは、ここにいくつかのものがあります。まず、あなたはこれらの線に沿って何かを抽象シェーダパラメータの取り扱い(結合、設定、など)にクラスを作成する必要があります。

class IShaderParameter 
{ 
protected: 
    IShaderParameter(const std::string & name) 
     : m_Uniform(-1) 
     , m_Name(name) 
    {} 
    GLuint m_Uniform; 
    std::string m_Name; 
public: 
    virtual void Set(GLuint program) = 0; 
}; 

次に、静的パラメータのために、あなたは、単にこのような過負荷を作成することができます。

template < typename Type > 
class StaticParameter 
    : public IShaderParameter 
{ 
public: 
    StaticParameter(const std::string & name, const Type & value) 
     : IShaderParameter(name) 
     , m_Value(value) 
    {} 
    virtual void Set(GLuint program) 
    { 
     if (m_Uniform == -1) 
      m_Uniform = glGetUniformLocation(program, m_Name.c_str()); 
     this->SetUniform(m_Value); 
    } 
protected: 
    Type m_Value; 
    void SetUniform(float value) { glUniform1f(m_Uniform, value); } 
    // write all SetUniform specializations that you need here 
    // ... 
}; 

同じ考え方で、「ダイナミックシェーダパラメータ」タイプを作成できます。たとえば、ライトのパラメータをシェーダにバインドできるようにするには、特殊なパラメータのタイプを作成します。そのコンストラクターで、ライトのIDを渡して、Setメソッドでライトを取得する方法を知るようにします。少しの作業では、あなたはその後、自動的にエンジンの実体に結合することができ、パラメータの全体の束(など材料パラメータ、ライトパラメータ、)

行うには最後のものは少しカスタムファイルを作成しているを持つことができますさまざまなパラメータを定義するための形式(xmlを使用)、およびローダーです。例えば、私の場合、それはこのように見えた:

<shader> 
    <param type="vec3" name="lightPos">light_0_position</param> 
    <param type="vec4" name="diffuse">material_10_diffuse</param> 
    <vertexShader> 
     ... a CDATA containing your shader code 
    </vertexShader> 
</shader> 

を私のエンジンでは、「light_0_positionは、」光のパラメータを意味し、0は光のIDであり、位置が取得するためのパラメータです。パラメータと実際の値との間のバインディングはローディング時に行われ、オーバーヘッドはあまりありませんでした。

とにかく質問に答えても、これらのサンプルコードをあまり重視しないでください(HLSLとOpenGLシェーダは全く違った働きをしていますが、OpenGLの専門家はいません^^)が、うまくいけばあなたにいくつかのリードを与える:

+0

ありがとうございました。あなたの実装(XMLの方法)は、CryEngineの人がマテリアルシステムを構築する方法と非常によく似ています。 – Raymond

0
  1. これについて詳しく説明できますか? OpenGLを直接操作すると、GPUに渡されるパラメータを完全に制御できます。あなたは何が欠けているのですか?

  2. (および3.)GLSL は、コードの再利用をサポートしています。さまざまな機能を提供するシェーダのライブラリを持つことができます。任意の関数を使用するには、クライアントシェーダ(vec4 get_diffuse();)で事前宣言し、リンクする前に関数を実装するシェーダオブジェクトをシェーダプログラムにアタッチするだけで済みます。

+0

1.すべてのパラメータロジックをC++で記述すると、ハードコーディングされます。そうでなければ、何らかの設定システムを実装しなければならず、それはエフェクトシステムの一部でなければなりません。 GLSLとCGシェーダは外部ファイルを含むことができますが、条件付きコンパイルはサポートしていません。 – Raymond

+0

これらの2つの答えは、 "http://stackoverflow.com/questions/6166202/how-to-design-a-simple-glsl-wrapper-for-shader-use/6169023#6169023"と "http:// stackoverflow.com/questions/4873631/vertex-shader-attribute-mapping-in-glsl/4927116#4927116 " – kvark

関連する問題