FXファイルのコンパイラを作成します。ただし一部の仕様のみに対応した簡易コンパイラです。複雑な構文解析は行わないので、文字列によって処理を分岐させる程度のプログラムになります。
コンパイラ
コンパイラといっても内容に従って構造体に値を代入するだけの処理です。シェーダコード自体はD3DCompileを使用し、シェーダバイナリコードを保持します。シェーダの変数については直接扱わず、シェーダバイナリコードを介して操作(ID3D11ShaderReflection)。
FXファイル仕様 Effect Format (Direct3D 11)の一部の仕様に対応。
検証に使用したFXファイル
作成したコンパイルが対応できる書式、これ以外のFXファイル仕様は未対応。
// 構造体定義
struct CBuffScene
{
matrix mtxProj;
matrix mtxView;
matrix mtxWorld;
};
//-------------
struct VS_INPUT
{
float4 Pos : POSITION;
float2 Tex : TEXCOORD0;
};
//-------------
struct PS_INPUT
{
float4 Pos : SV_POSITION;
float2 Tex : TEXCOORD0;
};
// 定数バッファ
cbuffer CB1 : register( b0 )
{
CBuffScene Scene;
};
// 変数
Texture2D txDiffuse : register( t0 );
// サンプラーステート
SamplerState samLinear : register( s0 )
{
Filter = MIN_MAG_MIP_LINEAR; // MIN_MAG_MIP_POINT MIN_MAG_POINT_MIP_LINEAR MIN_POINT_MAG_LINEAR_MIP_POINT
// MIN_POINT_MAG_MIP_LINEAR MIN_LINEAR_MAG_MIP_POINT MIN_LINEAR_MAG_POINT_MIP_LINEAR
// MIN_MAG_LINEAR_MIP_POINT MIN_MAG_MIP_LINEAR ANISOTROPIC
// COMPARISON_MIN_MAG_MIP_POINT COMPARISON_MIN_MAG_POINT_MIP_LINEAR
// COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT COMPARISON_MIN_POINT_MAG_MIP_LINEAR
// COMPARISON_MIN_LINEAR_MAG_MIP_POINT COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR
// COMPARISON_MIN_MAG_LINEAR_MIP_POINT COMPARISON_MIN_MAG_MIP_LINEAR
// COMPARISON_ANISOTROPIC;
AddressU = CLAMP; // WRAP MIRROR CLAMP BORDER MIRROR_ONCE
AddressV = CLAMP;
AddressW = CLAMP;
MipLODBias = 0.0; // float
MaxAnisotropy = 1; // uint
ComparisonFunc = NEVER; // NEVER LESS EQUAL LESS_EQUAL GREATER NOT_EQUAL GREATER_EQUAL ALWAYS
BorderColor = float4(1,1,1,1); // float4
MinLOD = -99999999.0; // float
MaxLOD = 99999999.0; // float
};
// 関数
//-------------------------
PS_INPUT vsBasic( VS_INPUT input)
{
PS_INPUT output = (PS_INPUT)0;
float4 pos = mul( input.Pos, Scene.mtxWorld );
pos = mul( pos, Scene.mtxView );
output.Pos = mul( pos, Scene.mtxProj );
output.Tex = input.Tex;
return output;
}
//----------------------------
float4 psBasic( PS_INPUT input ) : SV_Target
{
return txDiffuse.Sample( samLinear, input.Tex);
}
// ステート定義 ※大文字小文字の区別なし
BlendState NoBlend {
AlphaToCoverageEnable = False; // bool
//IndependentBlendEnable = False;//未対応
BlendEnable[0] = False; // bool
SrcBlend[0] = ONE; // ZERO ONE SRC_COLOR INV_SRC_COLOR SRC_ALPHA INV_SRC_ALPHA DEST_ALPHA INV_DEST_ALPHA DEST_COLOR INV_DEST_COLOR SRC_ALPHA_SAT BLEND_FACTOR INV_BLEND_FACTO SRC1_COLOR INV_SRC1_COLOR SRC1_ALPHA INV_SRC1_ALPHA
DestBlend[0] = ZERO;// ZERO ONE SRC_COLOR INV_SRC_COLOR SRC_ALPHA INV_SRC_ALPHA DEST_ALPHA INV_DEST_ALPHA DEST_COLOR INV_DEST_COLOR SRC_ALPHA_SAT BLEND_FACTOR INV_BLEND_FACTO SRC1_COLOR INV_SRC1_COLOR SRC1_ALPHA INV_SRC1_ALPHA
BlendOp[0] = ADD; // ADD SUBTRACT REV_SUBTRACT MIN MAX
SrcBlendAlpha[0] = ONE;
DestBlendAlpha[0] = ZERO;
BlendOpAlpha[0] = ADD;
RenderTargetWriteMask[0] = 0xf; //uint8 R=1 G=2 B=4 A=8
};
DepthStencilState DepthTestOn {
DepthEnable = True; // bool
DepthWriteMask = All; // Zero All
DepthFunc = LESS; // NEVER LESS EQUAL LESS_EQUAL GREATER NOT_EQUAL GREATER_EQUAL ALWAYS
StencilEnable = False; // bool
StencilReadMask = 255; // uint8
StencilWriteMask = 0xff; // uint8
FrontFaceStencilFail = KEEP; // KEEP ZERO REPLACE INCR_SAT DECR_SAT INVERT INCR DECR
FrontFaceStencilDepthFail = KEEP; // KEEP ZERO REPLACE INCR_SAT DECR_SAT INVERT INCR DECR
FrontFaceStencilPass = KEEP; // KEEP ZERO REPLACE INCR_SAT DECR_SAT INVERT INCR DECR
FrontFaceStencilFunc = ALWAYS; // NEVER LESS EQUAL LESS_EQUAL GREATER NOT_EQUAL GREATER_EQUAL ALWAYS
BackFaceStencilFail = KEEP; // KEEP ZERO REPLACE INCR_SAT DECR_SAT INVERT INCR DECR
BackFaceStencilDepthFail = KEEP; // KEEP ZERO REPLACE INCR_SAT DECR_SAT INVERT INCR DECR
BackFaceStencilPass = KEEP; // KEEP ZERO REPLACE INCR_SAT DECR_SAT INVERT INCR DECR
BackFaceStencilFunc = ALWAYS; // NEVER LESS EQUAL LESS_EQUAL GREATER NOT_EQUAL GREATER_EQUAL ALWAYS
};
RasterizerState rsWireframe {
FillMode = Solid; // WireFrame Solid
CullMode = Back; // None Front Back
FrontCounterClockwise = False; // bool;
DepthBias = 0; // int
DepthBiasClamp = 0.0f; // float
SlopeScaledDepthBias = 0.0f; // float
DepthClipEnable = True; // bool
ScissorEnable = False; // bool
MultisampleEnable = False; // bool
AntialiasedLineEnable = False; // bool
};
// テクニック
technique11 t0 {
//パス
pass p0 {
// ステート設定
SetBlendState( NoBlend, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
SetDepthStencilState( DepthTestOn, 0 );
SetRasterizerState( rsWireframe );
// シェーダ
SetVertexShader( CompileShader( vs_5_0, vsBasic() ) );
SetPixelShader( CompileShader( ps_5_0, psBasic() ) );
// とりあえずこの書式のみ対応
}
}
コンパイル結果
結果を保存するコンテナクラスを作成。DirectX11関連のオブジェクトはこの時点では作成しない。単純な構造体に値を書き込みとシェーダバイナリコード作成のみ。
//--------------------------------------------------------
// zgFXコンテナ
class FXContainer
{
public:
// D3D11ラスタライザステート定義取得
bool getDesc(Uint32 idx, RasterizerDesc& desc) const;
// D3D11デプスステンシルステート定義取得
bool getDesc(Uint32 idx, DepthStencilDesc& desc) const;
// D3D11ブレンドステート定義取得
bool getDesc(Uint32 idx, BlendDesc& desc) const;
// D3D11サンプラステート定義取得
bool getDesc(Uint32 idx, SamplerDesc& desc) const;
//名前からindex
Uint32 getRasterizerIdx(const Char* name) const;
Uint32 getDepthStencilIdx(const Char* name) const;
Uint32 getBlendIdx(const Char* name) const;
Uint32 getSamplerIdx(const Char* name) const;
// 各ステート定義数
Uint32 getRasterizeNum() const;
Uint32 getDepthStencilNum() const;
Uint32 getBlendNum() const;
Uint32 getSamplerNum() const;
// テクニックとパス情報取得
Uint32 getTechNum() const;
Uint32 getTechIdx(const Char* name) const;
bool getTech(Uint32 idx, TechniqueDesc& tech) const;
bool getPass(Uint32 tech_idx, Uint32 pass_idx, PassDesc&) const;
FXContainer();
~FXContainer();
}
使用例
コンパイル結果(FXContainer)から取得した構造体を使用してDirectX11のオブジェクトを生成。
// シェーダコンパイル
zgfx::FXContainer fx_cntr;
{
zgfx::ZGFXCompiler compile;
if( !compile.CompileFile("data\\shader.fx", fx_cntr) ){
return E_FAIL;
}
}
// テクニック情報取得
zgfx::TechniqueDesc fxtech;
zgfx::PassDesc fxpass;
UINT tech_idx = fx_cntr.getTechIdx( ZGFXCHAR("t0") );
if( !fx_cntr.getTech(tech_idx, fxtech) )return E_FAIL;
// パス情報の取得
if( !fx_cntr.getPass(tech_idx, 0, fxpass) )return E_FAIL;
//ステート定義の取得
zgfx::RasterizerDesc rs_desc;
zgfx::DepthStencilDesc ds_desc;
zgfx::BlendDesc bd_desc;
zgfx::SamplerDesc sp_desc;
UINT sp_idx = fx_cntr.getSamplerIdx( ZGFXCHAR("samLinear") );
if( !fx_cntr.getDesc(fxpass.idxRasterizer, rs_desc)
|| !fx_cntr.getDesc(fxpass.idxDepthStencil, ds_desc)
|| !fx_cntr.getDesc(fxpass.idxBlend, bd_desc)
|| !fx_cntr.getDesc(sp_idx, sp_desc)){
return E_FAIL;
}
// 頂点シェーダ作成
hr = pCtx->pDevice->CreateVertexShader( fxpass.VShader.pCode, fxpass.VShader.sizeCode, NULL, &pObj->pVShader );
if( FAILED( hr ) ){
return hr;
}
// ピクセルシェーダ作成
hr = pCtx->pDevice->CreatePixelShader( fxpass.PShader.pCode, fxpass.PShader.sizeCode, NULL, &pObj->pPShader );
if( FAILED( hr ) ){
return hr;
}
//ステート設定
// ラスタライザステート
hr = pCtx->pDevice->CreateRasterizerState(&rs_desc.Desc, &pObj->pRsState);
if( FAILED( hr ) ){ return hr; }
// ブレンドステート
hr = pCtx->pDevice->CreateBlendState(&bd_desc.Desc, &pObj->pBdState);
if( FAILED( hr ) ){ return hr; }
// デプスステンシルステート
hr = pCtx->pDevice->CreateDepthStencilState(&ds_desc.Desc, &pObj->pDsState);
if( FAILED( hr ) ){ return hr; }
// サンプラステート
hr = pCtx->pDevice->CreateSamplerState( &sp_desc.Desc, &pObj->pSampler );
if( FAILED( hr ) ){
return hr;
}
for(int i=0;i<4;++i){pObj->f4BdFactor[i] = fxpass.f4BdFactor.v[i];}
pObj->bitBdMask = fxpass.bitBdMask;
pObj->uStencilRef = fxpass.uStencilRef;
サンプルプログラム
エフェクトシステムの作成 Part2 コンパイラ作成
“DX11エフェクトシステムの作成 Part2 コンパイラ作成” をダウンロード dx11Effect1.zip – 659 回のダウンロード – 53 KB