HLSL实现蒙皮动画(1)

   这两天在做  3D蒙皮动画时遇到些问题,折腾了一天半,嗨!很郁闷啊!我要大叫来发泄一下。
本来打算用D3D设备直接设置世界坐标矩阵来实现动画的,但发现有一个问题,当我不使用D3DXEFFECT来设置渲染效果的时候就可以正常显示动画;当我使用它来设置渲染效果的时候,动画就没了。我想可能是用D3DXEFFECT来设置渲染效果的时候把D3D设备的 SetTransform功能屏蔽掉了(其实我不理解这个渲染过程^_^)。
   下面说一下加载和渲染蒙皮动画的大概流程吧。
   首先继承2个结构:D3DXFRAME、D3DMESHCONTAINER 和一个接口:ID3DXAllocateHierarchy。

//------------------------------------------------------------
//说明:框架
//------------------------------------------------------------

struct GFrame : public D3DXFRAME
{
 D3DXMATRIXA16 CombinedTransformationMatrix; //最终变换矩阵
};

 

 

//------------------------------------------------------------
//说明:网格容器
//------------------------------------------------------------

struct GMeshContainer : public D3DXMESHCONTAINER
{
 LPDIRECT3DTEXTURE9 *  _ppTexs;  //纹理列表

 LPD3DXMESH     _pOrigMesh;  //原mesh

 DWORD      _dwNumAttrGroups; //属性组个数
 DWORD      _dwMaxNumInfl;  //一个面最多受多少骨骼影响
 DWORD      _dwNumPaletteEntries; //样色个数

 LPD3DXBUFFER    _pBoneCombBuf;  //邻接矩阵列表
 D3DXMATRIX**    _ppBoneMatrixPtr; //骨骼矩阵列表
 D3DXMATRIX*     _pBoneOffsetMatrices; //骨骼矩阵引用

 DWORD      _iAttrSW; //用户 GenerateSkinnedMesh
};


//------------------------------------------------------------
//说明:封装网格的创建类
//------------------------------------------------------------

class GAllocateHierarchy : public ID3DXAllocateHierarchy
{
public:

// 下面4个方法是对父类的实现
    STDMETHOD(CreateFrame)(THIS_ LPCSTR Name, LPD3DXFRAME *ppNewFrame);

    STDMETHOD(CreateMeshContainer)(THIS_
        LPCSTR Name,
        CONST D3DXMESHDATA *pMeshData,
        CONST D3DXMATERIAL *pMaterials,
        CONST D3DXEFFECTINSTANCE *pEffectInstances,
        DWORD NumMaterials,
        CONST DWORD *pAdjacency,
        LPD3DXSKININFO pSkinInfo,
        LPD3DXMESHCONTAINER *ppNewMeshContainer);

    STDMETHOD(DestroyFrame)(THIS_ LPD3DXFRAME pFrameToFree);

    STDMETHOD(DestroyMeshContainer)(THIS_ LPD3DXMESHCONTAINER pMeshContainerBase);

};

 

//----------------------------------------------------
// 创建框架
//----------------------------------------------------
HRESULT GAllocateHierarchy::CreateFrame( LPCSTR Name, LPD3DXFRAME * ppNewFrame)
{
 HRESULT hr;
 GFrame * pFrame;
 pFrame = new GFrame();

 *ppNewFrame = NULL;

 if( !pFrame)
 {
  hr = E_OUTOFMEMORY;
  goto e_Exit;
 }

 //复制框架名称
 hr = HeapCopy( Name, &pFrame->Name);
 if( FAILED( hr) )
  goto e_Exit;

 //初始化其它属性
 D3DXMatrixIdentity( &pFrame->TransformationMatrix);
 D3DXMatrixIdentity( &pFrame->CombinedTransformationMatrix);

 pFrame->pMeshContainer = NULL;
 pFrame->pFrameFirstChild = NULL;
 pFrame->pFrameSibling = NULL;

//复制到新框架
 *ppNewFrame = pFrame;
 pFrame = NULL;

e_Exit:
 delete pFrame;
 return hr;
}

 

//----------------------------------------------------
// 创建Mesh
//----------------------------------------------------
HRESULT GAllocateHierarchy::CreateMeshContainer(
 LPCSTR Name,
 CONST D3DXMESHDATA * pMeshData,
 CONST D3DXMATERIAL * pMaterials,
 CONST D3DXEFFECTINSTANCE * pEffectInst,
 DWORD dwNumMaterials,
 CONST DWORD * pAdjacency,
 LPD3DXSKININFO pSkinInfo,
 LPD3DXMESHCONTAINER * ppNewMeshContainer)
{
 HRESULT hr;
 GMeshContainer * pMeshContainer = NULL;
 UINT iNumFaces;
 LPDIRECT3DDEVICE9 pDev = NULL;

 LPD3DXMESH pMesh = NULL;

 *ppNewMeshContainer = NULL;

 //----------------------------
 //验证异常
 if( pMeshData->Type != D3DXMESHTYPE_MESH)
 {
  hr = E_FAIL;
  goto e_Exit;
 }

 pMesh = pMeshData->pMesh;

 if( pMesh->GetFVF() == 0)
 {
  hr = E_FAIL;
  goto e_Exit;
 }

 pMeshContainer = new GMeshContainer();
 if( pMeshContainer == NULL)
 {
  hr = E_OUTOFMEMORY;
  goto e_Exit;
 }

 
 //-------------------------
 //初始化 pMeshContainer ,复制名字, 获取pDev , 获取面信息

 memset( pMeshContainer, 0, sizeof( GMeshContainer));

 hr = HeapCopy( Name, &pMeshContainer->Name);
 if( FAILED( hr))
  goto e_Exit;

 pMesh->GetDevice( & pDev);

 iNumFaces = pMesh->GetNumFaces();


 //--------------------------
 //判断是否要处理法向量,并复制 Mesh

 if( !(pMesh->GetFVF() & D3DFVF_NORMAL) ) //如果没有法向量,则添加法向量
 {
  pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;

  hr = pMesh->CloneMeshFVF( pMesh->GetOptions(),
        pMesh->GetFVF() | D3DFVF_NORMAL,
        pDev,
        &pMeshContainer->MeshData.pMesh);

  if( FAILED( hr))
   goto e_Exit;

  pMesh = pMeshContainer->MeshData.pMesh;

  D3DXComputeNormals( pMesh, NULL);
 }
 else //如果有法向量,则直接复制 Mesh
 {
  pMeshContainer->MeshData.pMesh = pMesh;
  pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;
  pMesh->AddRef();
 }

 
 //----------------------------
 // 获取材质个数,并初始化材质、纹理、邻接矩阵信息
 pMeshContainer->NumMaterials = max( 1, dwNumMaterials);
 pMeshContainer->pMaterials = new D3DXMATERIAL[ pMeshContainer->NumMaterials ];
 pMeshContainer->_ppTexs = new LPDIRECT3DTEXTURE9[ pMeshContainer->NumMaterials ];
 pMeshContainer->pAdjacency = new DWORD[ iNumFaces * 3];

 if( pMeshContainer->pMaterials == NULL || pMeshContainer->pAdjacency == NULL)
 {
  hr = E_OUTOFMEMORY;
  goto e_Exit;
 }

 memcpy( pMeshContainer->pAdjacency, pAdjacency, sizeof( DWORD) * iNumFaces * 3);
 memset( pMeshContainer->_ppTexs, 0, sizeof( LPDIRECT3DTEXTURE9) * pMeshContainer->NumMaterials);


 //--------------------------------
 // 复制材质,创建纹理
 if( dwNumMaterials > 0) //如果有材质,则复制材质
 {
  memcpy( pMeshContainer->pMaterials, pMaterials, sizeof( D3DXMATERIAL) * dwNumMaterials);
  for( UINT i = 0; i < dwNumMaterials; ++i)
  {
   //如果有纹理则加载纹理
   if( pMeshContainer->pMaterials[ i ].pTextureFilename != NULL)
   {
    LPSTR pFileName = pMeshContainer->pMaterials[ i ].pTextureFilename;
    if( FAILED( D3DXCreateTextureFromFileA( pDev, pFileName, &pMeshContainer->_ppTexs[ i ])) )
     pMeshContainer->_ppTexs[ i ] = NULL;

    //清除纹理文件名
    pMeshContainer->pMaterials[ i ].pTextureFilename = NULL;
   }
  }
 }
 else //如果没有材质则初始化默认值
 {
  pMeshContainer->pMaterials[ 0 ].pTextureFilename = NULL;
  memset( &pMeshContainer->pMaterials[ 0 ].MatD3D, 0, sizeof( D3DMATERIAL9));
  pMeshContainer->pMaterials[ 0 ].MatD3D.Diffuse.r = 0.5f;
  pMeshContainer->pMaterials[ 0 ].MatD3D.Diffuse.g = 0.5f;
  pMeshContainer->pMaterials[ 0 ].MatD3D.Diffuse.b = 0.5f;
  pMeshContainer->pMaterials[ 0 ].MatD3D.Specular = pMeshContainer->pMaterials[ 0 ].MatD3D.Diffuse;
 }


 //----------------------------
 //如果有 Skin 则创建 Skin,并创建拷贝它的骨骼矩阵信息
 if( pSkinInfo != NULL)
 {
  pMeshContainer->pSkinInfo = pSkinInfo;
  pSkinInfo->AddRef();

  pMeshContainer->_pOrigMesh = pMesh;
  pMesh->AddRef();

  UINT iTotalBones = pSkinInfo->GetNumBones();

  pMeshContainer->_pBoneOffsetMatrices = new D3DXMATRIX[ iTotalBones ];
  if( pMeshContainer->_pBoneOffsetMatrices == NULL)
  {
   hr = E_OUTOFMEMORY;
   goto e_Exit;
  }

  for( UINT i = 0; i < iTotalBones; ++i)
  {
   pMeshContainer->_pBoneOffsetMatrices[ i ] = *(pSkinInfo->GetBoneOffsetMatrix( i ));
  }

  hr = GenerateSkinnedMesh( pDev, pMeshContainer);
  if( FAILED( hr ) )
   goto e_Exit;
 }


 //--------------------------
 // 赋值 MeshContainer
 *ppNewMeshContainer = pMeshContainer;
 pMeshContainer = NULL;

e_Exit:
 SAFE_RELEASE( pDev);

 if( pMeshContainer != NULL)
  DestroyMeshContainer( pMeshContainer);

 return hr;
}

 

 


//----------------------------------------------------
// 销毁 Frame
//----------------------------------------------------
HRESULT GAllocateHierarchy::DestroyFrame( LPD3DXFRAME pFrameToFree)
{
 SAFE_DELETE_ARRAY( pFrameToFree->Name);
 SAFE_DELETE( pFrameToFree);
 return S_OK;
}

 

//----------------------------------------------------
// 销毁 MeshContainer
//----------------------------------------------------
HRESULT GAllocateHierarchy::DestroyMeshContainer( LPD3DXMESHCONTAINER pMeshContainerToFree)
{
 GMeshContainer * pMeshContainer = ( GMeshContainer *) pMeshContainerToFree;

 SAFE_DELETE_ARRAY( pMeshContainer->Name);
 SAFE_DELETE_ARRAY( pMeshContainer->pAdjacency );
 SAFE_DELETE_ARRAY( pMeshContainer->pMaterials );
 SAFE_DELETE_ARRAY( pMeshContainer->_pBoneOffsetMatrices);

 if( pMeshContainer->_ppTexs != NULL)
 {
  for( UINT i = 0; i < pMeshContainer->NumMaterials; ++i)
  {
   SAFE_RELEASE( pMeshContainer->_ppTexs[ i ]);
  }
 }

 SAFE_DELETE_ARRAY( pMeshContainer->_ppTexs );
 SAFE_DELETE_ARRAY( pMeshContainer->_ppBoneMatrixPtr);
 SAFE_RELEASE( pMeshContainer->_pBoneCombBuf);
 SAFE_RELEASE( pMeshContainer->MeshData.pMesh);
 SAFE_RELEASE( pMeshContainer->pSkinInfo );
 SAFE_RELEASE( pMeshContainer->_pOrigMesh);
 SAFE_DELETE( pMeshContainer );
 return S_OK;
}

 

//----------------------------------------------------
// 为 MeshContainer生成纹理
//----------------------------------------------------
// pNumBoneMatrixMax 为最大受骨骼影响的数目
HRESULT GAllocateHierarchy::GenerateSkinnedMesh( IDirect3DDevice9 * pDev, GMeshContainer * pMeshContainer)
{
 HRESULT hr = S_OK;
 D3DCAPS9 caps;
 pDev->GetDeviceCaps( & caps);

 if( pMeshContainer->pSkinInfo == NULL)
  return hr;

 SAFE_RELEASE( pMeshContainer->MeshData.pMesh);
 SAFE_RELEASE( pMeshContainer->_pBoneCombBuf );

 
  UINT iMaxMatrices = 26;

  pMeshContainer->_dwNumPaletteEntries = min( iMaxMatrices, pMeshContainer->pSkinInfo->GetNumBones());

  DWORD Flags = D3DXMESHOPT_VERTEXCACHE;
   Flags |= D3DXMESH_MANAGED;

  SAFE_RELEASE( pMeshContainer->MeshData.pMesh);

  hr = pMeshContainer->pSkinInfo->ConvertToIndexedBlendedMesh(
   pMeshContainer->_pOrigMesh,
   Flags,
   pMeshContainer->_dwNumPaletteEntries,
   pMeshContainer->pAdjacency,
   NULL, NULL, NULL,
   & pMeshContainer->_dwMaxNumInfl,
   & pMeshContainer->_dwNumAttrGroups,
   & pMeshContainer->_pBoneCombBuf,
   & pMeshContainer->MeshData.pMesh );

  if( FAILED( hr ) )
   goto e_Exit;

  DWORD NewFVF = ( pMeshContainer->MeshData.pMesh->GetFVF() & D3DFVF_POSITION_MASK) | D3DFVF_NORMAL | D3DFVF_TEX1 | D3DFVF_LASTBETA_UBYTE4;
  if( NewFVF != pMeshContainer->MeshData.pMesh->GetFVF() )
  {
   LPD3DXMESH pMesh;
   hr = pMeshContainer->MeshData.pMesh->CloneMeshFVF( pMeshContainer->MeshData.pMesh->GetOptions(), NewFVF, pDev, &pMesh);
   if( ! FAILED( hr ) )
   {
    pMeshContainer->MeshData.pMesh->Release();
    pMeshContainer->MeshData.pMesh = pMesh;
    pMesh = NULL;
   }
  }

  D3DVERTEXELEMENT9 pDecl[ MAX_FVF_DECL_SIZE];
  LPD3DVERTEXELEMENT9 pDeclCur;
  hr = pMeshContainer->MeshData.pMesh->GetDeclaration( pDecl);
  if( FAILED( hr ) )
   goto e_Exit;

  pDeclCur = pDecl;
  while( pDeclCur->Stream != 0xff)
  {
   if( (pDeclCur->Usage == D3DDECLUSAGE_BLENDINDICES) && ( pDeclCur->UsageIndex == 0 ) )
    pDeclCur->Type = D3DDECLTYPE_D3DCOLOR;
   pDeclCur++;
  }

  hr = pMeshContainer->MeshData.pMesh->UpdateSemantics( pDecl);
  if( FAILED( hr ) )
   goto e_Exit;

  if( m_iNumBoneMatricesMax < pMeshContainer->pSkinInfo->GetNumBones() )
  {
   m_iNumBoneMatricesMax = pMeshContainer->pSkinInfo->GetNumBones();

   SAFE_DELETE_ARRAY( m_pBoneMatrices);
   m_pBoneMatrices = new D3DXMATRIXA16[ m_iNumBoneMatricesMax ];
   if( *m_pBoneMatrices == NULL)
   {
    hr = E_OUTOFMEMORY;
    goto e_Exit;
   }
  }
          
 //}

e_Exit:
 return hr;
}


   创建两个全局指针:

LPD3DXFRAME             g_pFrameRoot = NULL;      //根Frame
ID3DXAnimationController* g_pAnimCtl = NULL; //动画控制类

   接着在初始化的地方(如果使用DXUT,则可以在OnCreateDevice中)调用 D3DXLoadMeshHierarchyFromX 来加载x文件。

 GAllocateHierarchy ah;

D3DXLoadMeshHierarchyFromX( strXFileName, D3DXMESH_MANAGED, pDev, 
         & ah, NULL, & g_pFrameRoot, &g_pAnimCtl );

SetupBoneMatrixPointers( g_pFrameRoot, g_pFrameRoot);  //建立矩阵指针
 D3DXFrameCalculateBoundingSphere( g_pFrameRoot, & g_vObjCenter,  g_fObjRadius );  //获取模型边界球

SetupBoneMatrixPointers 实现如下:


//------------------------------------------------------------
//desc:为框架建立骨骼矩阵
//param: pFrame 当前框架
//param: pFrameRoot 根框架
//return: 操作是否成功
//------------------------------------------------------------

HRESULT XFileObjBuilder::SetupBoneMatrixPointers(LPD3DXFRAME pFrame, LPD3DXFRAME pFrameRoot)
{
 HRESULT hr;

 if( pFrame->pMeshContainer != NULL)
 {
  hr = SetupBoneMatrixPointersOnMesh( pFrame->pMeshContainer, pFrameRoot);
  if( FAILED( hr ) )
   return hr;
 }

 if( pFrame->pFrameSibling != NULL)
 {
  hr = SetupBoneMatrixPointers( pFrame->pFrameSibling, pFrameRoot);
  if( FAILED( hr ) )
   return hr;
 }

 if( pFrame->pFrameFirstChild != NULL)
 {
  hr = SetupBoneMatrixPointers( pFrame->pFrameFirstChild, pFrameRoot);
  if( FAILED( hr ) )
   return hr;
 }

 return S_OK;
}

 


//------------------------------------------------------------
//desc: 为网格容器创建骨骼矩阵
//param: pMeshContainer 当前容器
//param: pFrameRoot 根框架
//return: 操作是否成功
//------------------------------------------------------------

HRESULT XFileObjBuilder::SetupBoneMatrixPointersOnMesh( LPD3DXMESHCONTAINER pMeshContainerBase, LPD3DXFRAME pFrameRoot)
{
 GFrame * pFrame;

 GMeshContainer * pMeshContainer = (GMeshContainer *) pMeshContainerBase;

 
 if( pMeshContainer->pSkinInfo != NULL)
 {
  UINT iTotalBones = pMeshContainer->pSkinInfo->GetNumBones();

  pMeshContainer->_ppBoneMatrixPtr = new D3DXMATRIX * [ iTotalBones ];
  if( pMeshContainer->_ppBoneMatrixPtr == NULL)
   return E_OUTOFMEMORY;

  for( UINT i = 0; i < iTotalBones; ++i)
  {
   pFrame = (GFrame *) D3DXFrameFind( pFrameRoot, pMeshContainer->pSkinInfo->GetBoneName( i));

   if( NULL == pFrame)
    return E_FAIL;

   pMeshContainer->_ppBoneMatrixPtr[ i ] = & pFrame->CombinedTransformationMatrix;
  }
 }

 return S_OK;
}


   接着在更新信息的地方(如果使用DXUT,则可以在OnFrameMove中添加)添加以下代码:
 UpdateFrameMatrices( g_pFrameRoot, &matWorld); //更新骨骼矩阵(其中 matWorld 可以包含模型的平移、缩放、旋转信息)

 if( g_pAnimCtl != NULL)
  g_pAnimCtl->AdvanceTime( fElapsedTime, NULL); //更新动画信息就靠它了
UpdateFrameMatrices 的实现如下:

//------------------------------------------------------------
//desc: 更新框架矩阵
//param: pFrameBase 当前框架
//param: pParentMatrix 父框架矩阵
//------------------------------------------------------------

void G3DObjEntity::UpdateFrameMatrices( LPD3DXFRAME pFrameBase, LPD3DXMATRIX pParentMatrix)
{
 assert( pFrameBase != NULL);
 assert( pParentMatrix != NULL);

 GFrame * pFrame = (GFrame *) pFrameBase;

 if( pParentMatrix != NULL)
  D3DXMatrixMultiply( &pFrame->CombinedTransformationMatrix, &pFrame->TransformationMatrix, pParentMatrix);
 else
  pFrame->CombinedTransformationMatrix = pFrame->TransformationMatrix;

 if( pFrame->pFrameSibling != NULL)
  UpdateFrameMatrices( pFrame->pFrameSibling, pParentMatrix);

 if( pFrame->pFrameFirstChild != NULL)
  UpdateFrameMatrices( pFrame->pFrameFirstChild, & pFrame->CombinedTransformationMatrix);

}

 


   最后在渲染的地方(如果使用DXUT,则在 OnFrameRender中)调用:
 DrawFrame( pDev, g_pFrameRoot); 

DrawFrame 的实现如下:

//------------------------------------------------------------
//desc: 画框架
//param: matView 视口矩阵
//param: pDev 设备
//param: pFrame 框架
//------------------------------------------------------------

void G3DObjEntity::DrawFrame(IDirect3DDevice9 * pDev, LPD3DXFRAME  pFrame)
{
 LPD3DXMESHCONTAINER pMeshContainer = pFrame->pMeshContainer;

 while( pMeshContainer != NULL)
 {
  DrawMeshContainer( pDev, pMeshContainer, pFrame);
  pMeshContainer = pMeshContainer->pNextMeshContainer;
 }

 if( pFrame->pFrameSibling != NULL)
  DrawFrame( pDev, pFrame->pFrameSibling);

 if( pFrame->pFrameFirstChild != NULL)
  DrawFrame( pDev, pFrame->pFrameFirstChild);
}

 

 

//------------------------------------------------------------
//desc: 画网格
//param: matView 视口矩阵
//param: pDev 设备
//param: pMeshContainerBase 网格指针
//param: pFrameBase 框架指针
//------------------------------------------------------------

void G3DObjEntity::DrawMeshContainer( IDirect3DDevice9 * pDev, LPD3DXMESHCONTAINER pMeshContainerBase, LPD3DXFRAME pFrameBase)
{
 HRESULT hr;
 GFrame * pFrame = ( GFrame *) pFrameBase;
 GMeshContainer * pMeshContainer = ( GMeshContainer *) pMeshContainerBase;

 UINT iMaterial;
 UINT iNumBlend;
 UINT iAttr;
 DWORD iAttrIdPrev;
 LPD3DXBONECOMBINATION pBoneComb;
 UINT iMatrixIndex;
 UINT iPaletteEntry;
 D3DXMATRIXA16 matTemp;

 LPD3DXEFFECT pEffect = NULL;
 if( m_pObjInfo != NULL && m_pObjInfo->GetEffectProxy() != NULL)
 {
  pEffect = m_pObjInfo->GetEffectProxy()->GetEffect();
 }

 D3DCAPS9 caps;
 pDev->GetDeviceCaps( & caps);

 if( pMeshContainer->pSkinInfo != NULL) //如果有蒙皮信息,则用HLSL处理蒙皮动画
 {

  D3DXMATRIX matView = * GlobalState::GetInstance()->GetCamera()->GetViewMatrix(); //这里使用DXUT 提供的摄像机

   pBoneComb = reinterpret_cast<LPD3DXBONECOMBINATION>(pMeshContainer->_pBoneCombBuf->GetBufferPointer());
   for( iAttr = 0; iAttr < pMeshContainer->_dwNumAttrGroups; ++iAttr)
   {
    for( iPaletteEntry = 0; iPaletteEntry < pMeshContainer->_dwNumPaletteEntries; ++iPaletteEntry)
    {
     iMatrixIndex = pBoneComb[ iAttr].BoneId[ iPaletteEntry];
     if( iMatrixIndex != UINT_MAX )
     {       
      D3DXMatrixMultiply( & m_pObjInfo->m_pBoneMatrices[ iPaletteEntry], & pMeshContainer->_pBoneOffsetMatrices[ iMatrixIndex ], pMeshContainer->_ppBoneMatrixPtr[ iMatrixIndex ]);   
     }
    }

   //把骨骼矩阵信息添加到 D3DXEFFECT 中
    V( pEffect->SetMatrixArray( "amPalette", m_pObjInfo->m_pBoneMatrices, pMeshContainer->_dwNumPaletteEntries) );
    
    D3DXCOLOR color1( pMeshContainer->pMaterials[ pBoneComb[iAttr].AttribId].MatD3D.Ambient);
    D3DXCOLOR color2(0.25, 0.25, 0.25, 1.0);
    D3DXCOLOR ambEmm;
    D3DXColorModulate( &ambEmm, &color1, &color2);
    ambEmm += D3DXCOLOR( pMeshContainer->pMaterials[ pBoneComb[iAttr].AttribId].MatD3D.Emissive);

    //把材质信息添加到D3DXEFFECT中
V( pEffect->SetVector("g_materialDiffuse", (D3DXVECTOR4*) &(pMeshContainer->pMaterials[pBoneComb[iAttr].AttribId].MatD3D.Diffuse)) );
    V( pEffect->SetVector("g_materialAmbient", (D3DXVECTOR4*) & ambEmm) );

    V( pDev->SetTexture( 0, pMeshContainer->_ppTexs[ pBoneComb[iAttr].AttribId] ) );

    V( pEffect->SetInt( "g_curNumBones", pMeshContainer->_dwMaxNumInfl - 1) );

    UINT numPasses;
    V( pEffect->Begin( &numPasses, D3DXFX_DONOTSAVESTATE) );
    for( UINT iPass = 0; iPass < numPasses; ++iPass)
    {
     V( pEffect->BeginPass( iPass));
     V( pMeshContainer->MeshData.pMesh->DrawSubset( iAttr));
     V( pEffect->EndPass() );
    }

    V( pEffect->End() );
    
    V( pDev->SetVertexShader( NULL) );
   }

 }
 else //如果没有skin ,则直接设置材质
 {
  V( pDev->SetTransform( D3DTS_WORLD, &pFrame->CombinedTransformationMatrix ) );

  for( iMaterial = 0; iMaterial < pMeshContainer->NumMaterials; ++iMaterial)
  {
   V( pDev->SetMaterial( &pMeshContainer->pMaterials[ iMaterial ].MatD3D) );
   V( pDev->SetTexture( 0, pMeshContainer->_ppTexs[ iMaterial ] ) );
   V( pMeshContainer->MeshData.pMesh->DrawSubset( iMaterial) );
  }
 }
}


  到此为止就可以实现加载和渲染动画了,这个实现的过程也有点复杂,一不小心搞错了某个地方,可能折腾半天都找不出原因。

你可能感兴趣的:(HLSL实现蒙皮动画(1))