SkinningMesh.fx#include "skin.vsh"
//----------- normal global value-----------------
//
extern matrix g_vMatrix;
extern matrix g_pMatrix;
extern matrix g_vpMatrix;
extern vector g_eyePos;
extern vector g_lightDir;
//------------ global value for skinned mesh----------
//
extern float4 g_lightDiffuse = { 0.6f, 0.6f, 0.6f, 1.0f};
extern float4 g_materialAmbient : MATERIALAMBIENT = {0.1f, 0.1f, 0.1f, 1.0f};
extern float4 g_materialDiffuse : MATERIALDIFFUSE = {0.8f, 0.8f, 0.8f, 1.0f};
static const int MAX_MATRICES = 26;
extern float4x3 g_mWorldMatrixArray[ MAX_MATRICES] : WORLDMATRIXARRAY;
extern int g_curNumBones = 2;
struct VS_INPUT
{
float4 pos : POSITION;
//---- for skinned mesh---
//
float3 blendWeights : BLENDWEIGHT;
float4 blendIndices : BLENDINDICES;
float3 nor : NORMAL;
float3 tex : TEXCOORD0;
};
struct VS_OUTPUT
{
float4 pos : POSITION;
float4 diffuse : COLOR;
float2 tex : TEXCOORD0;
};
VS_OUTPUT VS_SkinningMesh(VS_INPUT input)
{
VS_OUTPUT output = (VS_OUTPUT)0;
//---------- skinned mesh------------
float3 pos = 0.0f;
float3 nor = 0.0f;
float lastWeight = 0.0f;
VS_SKIN_INPUT vsi = { input.pos, input.blendWeights, input.blendIndices, input.nor };
VS_SKIN_OUTPUT vso = VS_Skin( vsi, g_curNumBones);
matrix vpMatrix = mul( g_vMatrix, g_pMatrix);
output.pos = mul( float4( vso.vPos.xyz, 1.0f), vpMatrix);
nor = normalize( vso.vNor );
output.diffuse = float4( g_materialAmbient.xyz + saturate( dot( nor, g_lightDir.xyz ) ) * g_materialDiffuse.xyz, 1.0 );
output.tex = input.tex.xy;
return output;
}
technique tec0
{
pass pass0
{
vertexShader = compile vs_2_0 VS_SkinningMesh();
}
}
在这里使用到DirectX例子里面使用到的一个文件:skin.vsh。代码如下:
skin.vsh//
// HLSL function for skinning a mesh. In your shader, you can #define
// MATRIX_PALETTE_SIZE if desired, and then #include this file.
// Copyright (c) 2000-2003 Microsoft Corporation. All rights reserved.
//
#ifndef VS_SKIN_VSH
#define VS_SKIN_VSH
//----------------------------------------------------------------------------
// Global parameters
//----------------------------------------------------------------------------
// Declare the 4x3 matrix palette. This is the array of bone matrices used in
// skinning vertices.
// The palette size is 26 by default. This is sufficiently small for most
// vs_1_1 shaders. Shaders targeted at vs_2_0 and above can set this higher
// to accommondate more bones in a call. For example, tiny_anim.x has 35
// bones, and so can be rendered in a single call if MATRIX_PALETTE_SIZE is
// set to 35 or more.
// An HLSL shader can set MATRIX_PALETTE_SIZE_DEFAULT to a different value.
// The calling app can also set it in the D3DXMACRO structure when compiling
// the shader. The calling app can query the actual palette size by examining
// MATRIX_PALETTE_SIZE (but changing it after compilation will not change the
// palette size in the compiled shader, of course).
#ifndef MATRIX_PALETTE_SIZE_DEFAULT
#define MATRIX_PALETTE_SIZE_DEFAULT 26
#endif
const int MATRIX_PALETTE_SIZE = MATRIX_PALETTE_SIZE_DEFAULT;
float4x3 amPalette[ MATRIX_PALETTE_SIZE_DEFAULT ];
//----------------------------------------------------------------------------
// Shader body - VS_ Skin
//----------------------------------------------------------------------------
// define the inputs -- caller must fill this, usually right from the VB
struct VS_SKIN_INPUT
{
float4 vPos;
float3 vBlendWeights;
float4 vBlendIndices;
float3 vNor;
};
// return skinned position and normal
struct VS_SKIN_OUTPUT
{
float4 vPos;
float3 vNor;
};
// call this function to skin VB position and normal
VS_SKIN_OUTPUT VS_Skin( const VS_SKIN_INPUT vInput, int iNumBones )
{
VS_SKIN_OUTPUT vOutput = (VS_SKIN_OUTPUT) 0;
float fLastWeight = 1.0;
float fWeight;
float afBlendWeights[ 3 ] = (float[ 3 ]) vInput.vBlendWeights;
int aiIndices[ 4 ] = (int[ 4 ]) D3DCOLORtoUBYTE4( vInput.vBlendIndices );
for( int iBone = 0; (iBone < 3) && (iBone < iNumBones - 1); ++ iBone )
{
fWeight = afBlendWeights[ iBone ];
fLastWeight -= fWeight;
vOutput.vPos.xyz += mul( vInput.vPos, amPalette[ aiIndices[ iBone ] ] ) * fWeight;
vOutput.vNor += mul( vInput.vNor, amPalette[ aiIndices[ iBone ] ] ) * fWeight;
}
vOutput.vPos.xyz += mul( vInput.vPos, amPalette[ aiIndices[ iNumBones - 1 ] ] ) * fLastWeight;
vOutput.vNor += mul( vInput.vNor, amPalette[ aiIndices[ iNumBones - 1 ] ] ) * fLastWeight;
return vOutput;
}
#endif // #ifndef VS_SKIN_VSH