早在我使用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專家^^),但希望它給你幾條線索:)
感謝您的建議。您的實現(XML方式)看起來非常像CryEngine人員構建其材料系統的方式。 – Raymond