2011-10-18 35 views
1

像CryEngine3這樣的Seriouse圖形引擎,虛幻引擎3都有自己定製的着色器語言和效果系統。在嘗試爲我的小圖形框架找到一些效果系統時,它看起來像nvidia CgFx是唯一的選擇(似乎Khronos有一個名爲glFx的項目,但項目頁面現在是404)。如何創建一個類似CgFx的效果系統?

我有幾個原因使我自己的影響系統:

  1. 我需要了解如何以及何時通過着色器參數的更多控制。
  2. 爲了重用shader片段,我想創建一些類似於C++的宏機制。使用宏進行一些條件編譯也很有用,並且CryEngine用於產生各種效果的方式也很有用。
  3. 貌似GLSL不具有這樣的效果系統

所以我想知道如何創建一個影響系統?我是否需要從頭開始編寫語法分析器,或者有一些代碼/工具能夠做到這一點?

PS:我使用OpenGL既GLSL和CG。

回答

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++編寫所有參數邏輯,它是硬編碼的。如果不是,那麼我必須實施某種配置系統,並且這應該是效果系統的一部分。 2.和3. GLSL和CG着色器可以包含外部文件,但不支持條件編譯。 – Raymond

+0

這兩個答案可能有所幫助:「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

相關問題