支援材質Shader的Shader管理器完成,發圖紀念
終於完成了結構最複雜的Shader管理器,特性如下:
GlobalShader管理:
也就是傳統的手寫Shader,完成特殊的任務,例如線條繪製,2D繪製等等
class ElementPixelShader : public ShaderBinder
{
DECLARE_RTTIOBJECT( ElementPixelShader )
DECLARE_RTTISERIAL( ElementPixelShader )
DECLARE_SHADER_METAINFO(ST_PixelShader, L"Shader\\SimpleElementPixelShader.usf",L"Main")
public:
virtual void BindShaderParameter( eShaderType ShaderType, const ShaderParameterMap& ParameterMap )
{
mTexture.Bind( ParameterMap, "Texture" );
}
void SetTexture( RenderTexture* NewTexture )
{
mShaderRHI->SetTextureParameter( mTexture, NewTexture );
}
virtual void Serialize( BinarySerializer& Ser )
{
__super::Serialize( Ser );
Ser << mTexture;
}
private:
ShaderParameter mTexture;
};
IMPLEMENT_GLOBAL_SHADER( ElementPixelShader, 1);
管理器中,是一種類似單件儲存,通過型別可以直接取到例項
MaterialPixelShader管理
這種Shader通過材質節點生成的shader程式碼來記錄每個Shader資訊,每個MaterialVertexShader需要只做MaterialPixelShader需要的資訊並在Shader程式碼中傳送給它
MaterialVertexShader管理
這類Shader最複雜,其中的控制程式碼生成的巨集需要由材質提供,例如是否使用TangentSpace。還有一些引數就更頭疼了, 不是材質在製作時能決定的,例如:一個材質可以應用給地形,模型,甚至粒子,所以我把這部分引數叫做晚繫結引數(Later Bind Material Parameter)
MaterialVertexShader本身是抽象的,需要在材質應用到具體物件時,由物件提供其特殊的VertexShader處理Shader,同時根據特性設定晚繫結引數
晚繫結引數:
MaterialParameter Parameter;
Parameter.Set( MPT_UseSkin, mSkinned );
mMaterialInstance->SetVertexShaderProvider( RTTI_CLASS_INFO( ModelMaterialVertexShader),Parameter );
材質緩衝系統
Shader 動態編譯在很多遊戲裡都有應用,例如:戰地2。遊戲第一次啟動時,就會編譯一次Shader。按照很多文章說的,編譯器會根據你顯示卡及配置編譯出最優化的程式碼。 我就納悶了, D3D編譯函式根本沒有傳入裝置控制代碼,怎麼可能根據機器配置編譯?我也嘗試過,不同機器上編譯出來根本就是一樣的。
在以後引擎啟動時,Shader系統就會自動從儲存好的緩衝內讀取,不用再次編譯。
這裡還要提一個微軟為D3DX做的升級Patch系統很噁心,類似於D3DXCompileShader及Shader相關的函式,在每次呼叫函式時,會載入一個D3DX9_xx.dll,呼叫完畢後又會解除安裝,極大的影響效能。 若不是因為這個,估計我不會寫緩衝系統的
動態編譯更新Shader
這個功能是很多引擎都有的,RenderMonkey也一樣,實現起來很簡單,就是一個檔案時間戳比較問題,此功能完全是為以後編輯器做準備。
MaterialShader部分終於告一段落,下面終於可以進入材質節點系統的進一步完善了