HLSL实现蒙皮动画(2)

Posted on 2008-12-02 16:39 Herbert 阅读(1449) 评论(0)  编辑 收藏 引用 所属分类: DirectX
   HLSL怎么实现蒙皮动画的呢?其实就是在顶点着色阶段根据传入的顶点权重、骨骼矩阵信息来计算顶点的实际位置。

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



只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理