//----------------------------------------------------------------------------- // SkinnedEffect.fx // // Microsoft XNA Community Game Platform // Copyright (C) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- #include "Macros.fxh" #define SKINNED_EFFECT_MAX_BONES 72 DECLARE_TEXTURE(Texture, 0); BEGIN_CONSTANTS float4 DiffuseColor _vs(c0) _ps(c1) _cb(c0); float3 EmissiveColor _vs(c1) _ps(c2) _cb(c1); float3 SpecularColor _vs(c2) _ps(c3) _cb(c2); float SpecularPower _vs(c3) _ps(c4) _cb(c2.w); float3 DirLight0Direction _vs(c4) _ps(c5) _cb(c3); float3 DirLight0DiffuseColor _vs(c5) _ps(c6) _cb(c4); float3 DirLight0SpecularColor _vs(c6) _ps(c7) _cb(c5); float3 DirLight1Direction _vs(c7) _ps(c8) _cb(c6); float3 DirLight1DiffuseColor _vs(c8) _ps(c9) _cb(c7); float3 DirLight1SpecularColor _vs(c9) _ps(c10) _cb(c8); float3 DirLight2Direction _vs(c10) _ps(c11) _cb(c9); float3 DirLight2DiffuseColor _vs(c11) _ps(c12) _cb(c10); float3 DirLight2SpecularColor _vs(c12) _ps(c13) _cb(c11); float3 EyePosition _vs(c13) _ps(c14) _cb(c12); float3 FogColor _ps(c0) _cb(c13); float4 FogVector _vs(c14) _cb(c14); float4x4 World _vs(c19) _cb(c15); float3x3 WorldInverseTranspose _vs(c23) _cb(c19); float4x3 Bones[SKINNED_EFFECT_MAX_BONES] _vs(c26) _cb(c22); MATRIX_CONSTANTS float4x4 WorldViewProj _vs(c15) _cb(c0); END_CONSTANTS #include "Structures.fxh" #include "Common.fxh" #include "Lighting.fxh" void Skin(inout VSInputNmTxWeights vin, uniform int boneCount) { float4x3 skinning = 0; [unroll] for (int i = 0; i < boneCount; i++) { skinning += Bones[vin.Indices[i]] * vin.Weights[i]; } vin.Position.xyz = mul(vin.Position, skinning); vin.Normal = mul(vin.Normal, (float3x3)skinning); } // Vertex shader: vertex lighting, one bone. VSOutputTx VSSkinnedVertexLightingOneBone(VSInputNmTxWeights vin) { VSOutputTx vout; Skin(vin, 1); CommonVSOutput cout = ComputeCommonVSOutputWithLighting(vin.Position, vin.Normal, 3); SetCommonVSOutputParams; vout.TexCoord = vin.TexCoord; return vout; } // Vertex shader: vertex lighting, two bones. VSOutputTx VSSkinnedVertexLightingTwoBones(VSInputNmTxWeights vin) { VSOutputTx vout; Skin(vin, 2); CommonVSOutput cout = ComputeCommonVSOutputWithLighting(vin.Position, vin.Normal, 3); SetCommonVSOutputParams; vout.TexCoord = vin.TexCoord; return vout; } // Vertex shader: vertex lighting, four bones. VSOutputTx VSSkinnedVertexLightingFourBones(VSInputNmTxWeights vin) { VSOutputTx vout; Skin(vin, 4); CommonVSOutput cout = ComputeCommonVSOutputWithLighting(vin.Position, vin.Normal, 3); SetCommonVSOutputParams; vout.TexCoord = vin.TexCoord; return vout; } // Vertex shader: one light, one bone. VSOutputTx VSSkinnedOneLightOneBone(VSInputNmTxWeights vin) { VSOutputTx vout; Skin(vin, 1); CommonVSOutput cout = ComputeCommonVSOutputWithLighting(vin.Position, vin.Normal, 1); SetCommonVSOutputParams; vout.TexCoord = vin.TexCoord; return vout; } // Vertex shader: one light, two bones. VSOutputTx VSSkinnedOneLightTwoBones(VSInputNmTxWeights vin) { VSOutputTx vout; Skin(vin, 2); CommonVSOutput cout = ComputeCommonVSOutputWithLighting(vin.Position, vin.Normal, 1); SetCommonVSOutputParams; vout.TexCoord = vin.TexCoord; return vout; } // Vertex shader: one light, four bones. VSOutputTx VSSkinnedOneLightFourBones(VSInputNmTxWeights vin) { VSOutputTx vout; Skin(vin, 4); CommonVSOutput cout = ComputeCommonVSOutputWithLighting(vin.Position, vin.Normal, 1); SetCommonVSOutputParams; vout.TexCoord = vin.TexCoord; return vout; } // Vertex shader: pixel lighting, one bone. VSOutputPixelLightingTx VSSkinnedPixelLightingOneBone(VSInputNmTxWeights vin) { VSOutputPixelLightingTx vout; Skin(vin, 1); CommonVSOutputPixelLighting cout = ComputeCommonVSOutputPixelLighting(vin.Position, vin.Normal); SetCommonVSOutputParamsPixelLighting; vout.Diffuse = float4(1, 1, 1, DiffuseColor.a); vout.TexCoord = vin.TexCoord; return vout; } // Vertex shader: pixel lighting, two bones. VSOutputPixelLightingTx VSSkinnedPixelLightingTwoBones(VSInputNmTxWeights vin) { VSOutputPixelLightingTx vout; Skin(vin, 2); CommonVSOutputPixelLighting cout = ComputeCommonVSOutputPixelLighting(vin.Position, vin.Normal); SetCommonVSOutputParamsPixelLighting; vout.Diffuse = float4(1, 1, 1, DiffuseColor.a); vout.TexCoord = vin.TexCoord; return vout; } // Vertex shader: pixel lighting, four bones. VSOutputPixelLightingTx VSSkinnedPixelLightingFourBones(VSInputNmTxWeights vin) { VSOutputPixelLightingTx vout; Skin(vin, 4); CommonVSOutputPixelLighting cout = ComputeCommonVSOutputPixelLighting(vin.Position, vin.Normal); SetCommonVSOutputParamsPixelLighting; vout.Diffuse = float4(1, 1, 1, DiffuseColor.a); vout.TexCoord = vin.TexCoord; return vout; } // Pixel shader: vertex lighting. float4 PSSkinnedVertexLighting(PSInputTx pin) : SV_Target0 { float4 color = SAMPLE_TEXTURE(Texture, pin.TexCoord) * pin.Diffuse; AddSpecular(color, pin.Specular.rgb); ApplyFog(color, pin.Specular.w); return color; } // Pixel shader: vertex lighting, no fog. float4 PSSkinnedVertexLightingNoFog(PSInputTx pin) : SV_Target0 { float4 color = SAMPLE_TEXTURE(Texture, pin.TexCoord) * pin.Diffuse; AddSpecular(color, pin.Specular.rgb); return color; } // Pixel shader: pixel lighting. float4 PSSkinnedPixelLighting(PSInputPixelLightingTx pin) : SV_Target0 { float4 color = SAMPLE_TEXTURE(Texture, pin.TexCoord) * pin.Diffuse; float3 eyeVector = normalize(EyePosition - pin.PositionWS.xyz); float3 worldNormal = normalize(pin.NormalWS); ColorPair lightResult = ComputeLights(eyeVector, worldNormal, 3); color.rgb *= lightResult.Diffuse; AddSpecular(color, lightResult.Specular); ApplyFog(color, pin.PositionWS.w); return color; } VertexShader VSArray[9] = { compile vs_2_0 VSSkinnedVertexLightingOneBone(), compile vs_2_0 VSSkinnedVertexLightingTwoBones(), compile vs_2_0 VSSkinnedVertexLightingFourBones(), compile vs_2_0 VSSkinnedOneLightOneBone(), compile vs_2_0 VSSkinnedOneLightTwoBones(), compile vs_2_0 VSSkinnedOneLightFourBones(), compile vs_2_0 VSSkinnedPixelLightingOneBone(), compile vs_2_0 VSSkinnedPixelLightingTwoBones(), compile vs_2_0 VSSkinnedPixelLightingFourBones(), }; int VSIndices[18] = { 0, // vertex lighting, one bone 0, // vertex lighting, one bone, no fog 1, // vertex lighting, two bones 1, // vertex lighting, two bones, no fog 2, // vertex lighting, four bones 2, // vertex lighting, four bones, no fog 3, // one light, one bone 3, // one light, one bone, no fog 4, // one light, two bones 4, // one light, two bones, no fog 5, // one light, four bones 5, // one light, four bones, no fog 6, // pixel lighting, one bone 6, // pixel lighting, one bone, no fog 7, // pixel lighting, two bones 7, // pixel lighting, two bones, no fog 8, // pixel lighting, four bones 8, // pixel lighting, four bones, no fog }; PixelShader PSArray[3] = { compile ps_2_0 PSSkinnedVertexLighting(), compile ps_2_0 PSSkinnedVertexLightingNoFog(), compile ps_2_0 PSSkinnedPixelLighting(), }; int PSIndices[18] = { 0, // vertex lighting, one bone 1, // vertex lighting, one bone, no fog 0, // vertex lighting, two bones 1, // vertex lighting, two bones, no fog 0, // vertex lighting, four bones 1, // vertex lighting, four bones, no fog 0, // one light, one bone 1, // one light, one bone, no fog 0, // one light, two bones 1, // one light, two bones, no fog 0, // one light, four bones 1, // one light, four bones, no fog 2, // pixel lighting, one bone 2, // pixel lighting, one bone, no fog 2, // pixel lighting, two bones 2, // pixel lighting, two bones, no fog 2, // pixel lighting, four bones 2, // pixel lighting, four bones, no fog }; int ShaderIndex = 0; Technique SkinnedEffect { Pass { VertexShader = (VSArray[VSIndices[ShaderIndex]]); PixelShader = (PSArray[PSIndices[ShaderIndex]]); } }