C#でツールを作る その15 -HLSLを使ってみる-
今ではシェーダも一般的になっているようなので、私もちょっと遊んでみようと思います。
Effectオブジェクトの作成と破棄
- コンパイルエラーがあるとerrに文字列返ってくる
private Effect effect = null;
String err; //コンパイルエラー時の情報を取得 effect = Effect.FromFile( device, エフェクトファイル名, null, ShaderFlags.None, null, out err );
if (effect != null) { effect.Dispose(); effect = null; }
Techniqueの取得と設定
private EffectHandle tech = null;
tech = effect.GetTechnique( テクニック名 );
effect.Technique = tech;
Effect変数の取得と設定
private EffectHandle handle = null;
handle = effect.GetParameter( null, "WorldViewProjection" ); //WorldViewProjectionはエフェクトファイル内の変数
Matrix WorldViewProjection = ...;
effect.SetValue( handle, WorldViewProjection );
//effect.SetValue( "WorldViewProjection", WorldViewProjection );
- EffectHandleは文字列を渡すことも可能
描画
- エフェクトを開始するとパス数が返ってくるので、その回数分ループで描画
int n = effect.Begin( FX.None ); for( int pass = 0; pass < n; pass ++ ) { effect.BeginPass( pass ); 描画; effect.EndPass(); } effect.End();
fxファイル
//----------------------------------------------------------- //global //----------------------------------------------------------- float4x4 WorldViewProjection; //ワールド*ビュー*プロジェクション行列 //----------------------------------------------------------- //struct //----------------------------------------------------------- struct VertexInput { float4 pos : POSITION; }; struct VertexOutput { float4 pos : POSITION; float4 color : COLOR0; }; struct PixelOutput { float4 color : COLOR0; }; //----------------------------------------------------------- //vertex shader //----------------------------------------------------------- VertexOutput TestVertexShader( VertexInput input ) { VertexOutput output; //座標変換 output.pos = mul( input.pos, WorldViewProjection ); //ライティング float4 diffuse = { 0.0f, 0.0f, 0.0f }; output.color = diffuse; return output; } //----------------------------------------------------------- //pixel shader //----------------------------------------------------------- PixelOutput TestPixelShader( VertexOutput input ) { Pixeloutput output; output.color = input.color; return output; } //----------------------------------------------------------- //technique //----------------------------------------------------------- technique test { pass P0 { VertexShader = compile vs_2_0 TestVertexShader(); PixelShader = compile ps_2_0 TestPixelShader(); } }
C#でツールを作る その15.1 -ランバート反射-
もっとも単純なライティングですね。
輪郭線もシェーダで描画したいので、はちゅねのモデルから面を反転した黒いメッシュを削除しました。
サンプル
- download
- VC#2008EE
- VertexShader2.0
- PixelShader2.0
- miku
- miku01.x
- miku01.fx
- miku01.mqo
- miku.dds
- miku.jpg
- miku_alpha.tga
fxファイル
//----------------------------------------------------------- //global //----------------------------------------------------------- float4x4 Mw; //ワールド行列 float4x4 Mv; //ビュー行列 float4x4 Mp; //プロジェクション行列 float4 mat_diffuse = { 1.0f, 1.0f, 1.0f, 1.0f }; float4 mat_ambient = { 0.0f, 0.0f, 0.0f, 0.0f }; float4 light_dir = { 0.0f, 0.0f, 1.0f, 0.0f }; float4 light_diffuse = { 1.0f, 1.0f, 1.0f, 1.0f }; float4 light_ambient = { 0.2f, 0.2f, 0.2f, 1.0f }; texture tex; sampler test_sampler = sampler_state { Texture = <tex>; MinFilter = POINT; MagFilter = POINT; MipFilter = NONE; AddressU = Clamp; AddressV = Clamp; };
//----------------------------------------------------------- //struct //----------------------------------------------------------- struct VertexInput { float4 pos : POSITION; float3 normal : NORMAL; float2 tex : TEXCOORD0; }; struct VertexOutput { float4 pos : POSITION; float4 color : COLOR0; float2 tex : TEXCOORD0; }; struct PixelOutput { float4 color : COLOR0; };
//----------------------------------------------------------- //vertex shader //----------------------------------------------------------- VertexOutput TestVertexShader( VertexInput input ) { VertexOutput output; //座標変換 float4 world_pos = mul( input.pos, Mw ); float4 view_pos = mul( world_pos, Mv ); output.pos = mul( view_pos, Mp ); //ライティング(lambert) float3 L = -light_dir.xyz; output.color.rgb = mat_diffuse.rgb * light_diffuse * max( dot( L, input.normal ), 0.0f ) + mat_ambient.rgb * light_ambient; output.color.a = mat_diffuse.a; output.tex = input.tex; return output; }
//----------------------------------------------------------- //pixel shader //----------------------------------------------------------- PixelOutput TestPixelShader( VertexOutput input ) { PixelOutput output; output.color = tex2D( test_sampler, input.tex ) * input.color; return output; }
//----------------------------------------------------------- //technique //----------------------------------------------------------- technique test { pass P0 { VertexShader = compile vs_2_0 TestVertexShader(); PixelShader = compile ps_2_0 TestPixelShader(); ZEnable = true; ZWriteEnable = true; Lighting = false; AlphaBlendEnable = true; CullMode = CCW; SrcBlend = SRCALPHA; DestBlend = INVSRCALPHA; } }