超基本的なシェーダ
普通に頂点変換して普通にライティングして普通にテクスチャマッピングするだけのシェーダ。
float4x4 g_WorldViewProj : WorldViewProjection; float4x4 g_World; float4 g_MaterialDiffuse; float3 g_LightDirection; float4 g_LightDiffuse; float4 g_LightAmbient; texture g_MeshTexture; sampler MeshTextureSampler = sampler_state { Texture = <g_MeshTexture>; MipFilter = LINEAR; MinFilter = LINEAR; MagFilter = LINEAR; }; struct VS_OUTPUT { float4 Position : POSITION; float4 Diffuse : COLOR0; float2 TextureUV: TEXCOORD0; }; VS_OUTPUT mainVS( float3 vPos : POSITION, float3 vNormal : NORMAL, float4 vDiffuse : COLOR0, float2 vTexCoord0 : TEXCOORD0) { VS_OUTPUT Output; float3 vNormalWorld; Output.Position = mul(float4(vPos.xyz, 1.0), g_WorldViewProj); vNormalWorld = normalize(mul(vNormal, (float3x3)g_World)); Output.Diffuse = g_MaterialDiffuse * g_LightDiffuse * max(0, -dot(vNormalWorld, g_LightDirection)) + g_LightAmbient; Output.TextureUV = vTexCoord0; return Output; } struct PS_OUTPUT { float4 RGBColor : COLOR0; }; PS_OUTPUT mainPS(VS_OUTPUT In, uniform bool bTexture) { PS_OUTPUT Output; if ( bTexture ) Output.RGBColor = tex2D(MeshTextureSampler, In.TextureUV) * In.Diffuse; else Output.RGBColor = In.Diffuse; return Output; } technique TechniqueNoTexture { pass p0 { CullMode = None; VertexShader = compile vs_2_0 mainVS(); PixelShader = compile ps_2_0 mainPS(false); } } technique TechniqueTexture { pass p0 { CullMode = None; VertexShader = compile vs_2_0 mainVS(); PixelShader = compile ps_2_0 mainPS(true); } }
グローバル変数は適当に外から与える。
ポイント解説。
Output.Position = mul(float4(vPos.xyz, 1.0), g_WorldViewProj);
ローカル頂点座標をワールドビュー射影行列で一気にスクリーン座標に変換します。
vNormalWorld = normalize(mul(vNormal, (float3x3)g_World));
ライティングには法線が必要なので、ローカル空間の法線をワールド空間に変換します。
Output.Diffuse = g_MaterialDiffuse * g_LightDiffuse * max(0, -dot(vNormalWorld, g_LightDirection)) + g_LightAmbient;
ライトによる反射の強さは、光線の逆方向ベクトルと法線の内積になります。ライトの当たっていない反対側は内積が負になるので、0でクリップします。ただしそれだと真っ黒になってしまうので、アンビエントライトで下駄を履かせてちょっと見えるようにします。
Output.RGBColor = tex2D(MeshTextureSampler, In.TextureUV) * In.Diffuse;
ピクセルシェーダではテクスチャの色とポリゴンの色を乗算して出力します。
以上、ほとんどサンプル丸写しでした。
マテリアルカラーはグローバル変数として外から与えてるけど、頂点シェーダの入力セマンティックとしても渡るんじゃないのかな。