Direct3D轮回:为D3D量身订做SpriteBatch类

上一节中,我们大致讲述了Direct3D环境下,如何使用ID3DXSprite绘制2D对象。

ID3DXSprite虽然使用起来非常方便,但其自身存在着诸多的限制与弊端,一个最明显的体现,ID3DXSprite没有提供自身顶点级操作,因此无法应用特效;另外,其接口的设计也不是十分的友好~

这一节,我们使用D3D中最基本的图元绘制法,为其量身订做一个专属于D3D的CSpriteBatch类。

如下是CSpriteBatch的实现代码:

 

/* -------------------------------------

代码清单:SpriteBatch.h
来自:
http://www.cnblogs.com/kenkao

-------------------------------------
*/

#include 
" Texture2D.h "
#include 
" D3DEffect.h "
#include 
< list >

using   namespace  std;

#pragma  once

//  精灵节点
struct  SpriteNode
{
    RECT         _DesRect;        
//  目标区域
    RECT         _SurRect;         //  纹理区域
     float         _layerDepth;      //  深度(Z坐标)
    D3DCOLOR     _Color;           //  色相
    SpriteNode(){}
    SpriteNode(RECT DesRect,RECT SurRect,
float  layerDepth,D3DCOLOR Color){
        _DesRect
= DesRect; _SurRect = SurRect; _layerDepth = layerDepth; _Color = Color;
    }
};

class  CSpriteBatch
{
public :
    CSpriteBatch(IDirect3DDevice9
*  pDevice);
    
~ CSpriteBatch( void );
public :
    
void  Begin(CD3DEffect *  pD3DEffect = NULL);                     //  开始绘制
     void  End();                                                  //  结束绘制
     void  Release(){                                              //  释放CSpriteBatch
         if (m_pSpriteNodeList -> size() > 0
            m_pSpriteNodeList
-> clear(); 
        delete m_pSpriteNodeList;}
public :                                                          //  一系列的重载Draw函数 ^ ^
     void  Draw(
        CTexture2D
*   pTexture,                                   //  目标纹理
         const  RECT &   DesRect,                                    //  目标区域
         const  RECT &   SurRect,                                    //  纹理区域
         const   float &  layerDepth  =   0.0f ,                          //  深度值(0、1之间)
        D3DCOLOR     Color  =  D3DXCOLOR_WHITE                     //  色相
        );
    
void  Draw(
        CTexture2D
*  pTexture,
        
const  POINT &  Pos,
        
const  RECT &  SurRect,
        
const   float &  layerDepth  =   0.0f
        D3DCOLOR Color 
=  D3DXCOLOR_WHITE
        );
    
void  Draw(
        CTexture2D
*  pTexture,
        
const  POINT &  Pos,
        
const   float &  layerDepth  =   0.0f
        D3DCOLOR Color 
=  D3DXCOLOR_WHITE
        );
    
void  Draw(
        CTexture2D
*  pTexture,
        
const  RECT &  DesRect,
        
const   float &  layerDepth  =   0.0f
        D3DCOLOR Color 
=  D3DXCOLOR_WHITE
        );
    
void  Draw(
        CTexture2D
*  pTexture,
        
const  POINT &  Pos,
        
const  POINT &  Size,
        
const  RECT &  SurRect,
        
const   float &  layerDepth  =   0.0f
        D3DCOLOR Color 
=  D3DXCOLOR_WHITE
        );
    
void  Draw(
        CTexture2D
*  pTexture,
        
const  POINT &  Pos,
        
const  POINT &  Size,
        
const   float &  layerDepth  =   0.0f
        D3DCOLOR Color 
=  D3DXCOLOR_WHITE
        );
public :
    IDirect3DDevice9
*  GetDevice(){ return  m_pDevice;}             //  获得设备指针
    CD3DEffect *        GetEffect(){ return  m_pD3DEffect;}          //  获得特效指针
    CTexture2D *        GetTexture2D(){ return  m_pCurrentTexture;}  //  获得活动纹理
private :
    
void  PostFrame(                                              //  单帧投递
        RECT   DesRect, 
        RECT   SurRect,
        
float   layerDepth,
        D3DCOLOR Color
        );
    
void  Flush();                                                //  遍历所有节点并一次性完成绘制
private :
    IDirect3DDevice9
*  m_pDevice;                                 //  设备指针
    CTexture2D *        m_pCurrentTexture;                         //  活动纹理指针
    CD3DEffect *        m_pD3DEffect;                              //  特效指针
    UINT              m_NumPasses;                               //  特效路径数目
    D3DXMATRIX        m_OriViewMatrix;                           //  原始摄影矩阵
    D3DXMATRIX        m_OriProjMatrix;                           //  原始投影矩阵
    D3DXMATRIX        m_ViewMatrix;                              //  摄影矩阵
    D3DXMATRIX        m_ProjMatrix;                              //  投影矩阵
private :
    list
< SpriteNode >*  m_pSpriteNodeList;                         //  精灵节点列表
};

 

Direct3D轮回:为D3D量身订做SpriteBatch类 SpriteBatch.cpp
/* -------------------------------------

代码清单:SpriteBatch.cpp
来自:
http://www.cnblogs.com/kenkao

-------------------------------------
*/

#include 
" StdAfx.h "
#include 
" SpriteBatch.h "

//  精灵顶点缓冲结构定义
struct  VertexSprite{
    VertexSprite(){}
    VertexSprite(
float  x,  float  y,  float  z,  float  nx,  float  ny,  float  nz, D3DCOLOR color,  float  u,  float  v){
        _x 
=  x; _y  =  y; _z  =  z;
        _nx 
=  nx; _ny  =  ny; _nz  =  nz;
        _color 
=  color;
        _u 
=  u; _v  =  v;
    }
    
float  _x, _y, _z;
    
float  _nx, _ny, _nz;
    D3DCOLOR _color;
    
float  _u, _v;
    
static   const  DWORD FVF;
};
const  DWORD VertexSprite::FVF  =  (D3DFVF_XYZ  |  D3DFVF_NORMAL  | D3DFVF_DIFFUSE  |  D3DFVF_TEX1);

CSpriteBatch::CSpriteBatch(IDirect3DDevice9
*  pDevice) : m_pDevice(NULL),
                                                        m_pD3DEffect(NULL),
                                                        m_pCurrentTexture(NULL),
                                                        m_NumPasses(
0 ),
                                                        m_OriViewMatrix(D3DXMATRIX_IDENTITY),
                                                        m_OriProjMatrix(D3DXMATRIX_IDENTITY),
                                                        m_pSpriteNodeList(NULL)
{
    
//  传入3D设备
     this -> m_pDevice = pDevice;
    
//  获得单位摄影矩阵
    m_ViewMatrix  =  D3DXMATRIX_IDENTITY;
    
//  获得正交投影矩阵
    D3DXMatrixOrthoOffCenterLH( & m_ProjMatrix,  0.0f 640.0f 480.0f 0.0f 0.0f 1.0f );
    
//  初始化精灵节点列表
    m_pSpriteNodeList  =   new  list < SpriteNode > ;
}

CSpriteBatch::
~ CSpriteBatch( void )
{
}

void  CSpriteBatch::Begin(CD3DEffect *  pD3DEffect)
{
    
//  获得原始状态
    m_pDevice -> GetTransform(D3DTS_VIEW,        & m_OriViewMatrix);
    m_pDevice
-> GetTransform(D3DTS_PROJECTION,  & m_OriProjMatrix);
    
//  设置单位摄影矩阵及正交投影矩阵
    m_pDevice -> SetTransform(D3DTS_VIEW,        & m_ViewMatrix);
    m_pDevice
-> SetTransform(D3DTS_PROJECTION,  & m_ProjMatrix);
    
//  如果存在特效则应用之
     if (pD3DEffect)
    {
        
this -> m_pD3DEffect = pD3DEffect;
        m_pD3DEffect
-> BeginEffect(m_NumPasses);
    }
}

void  CSpriteBatch::End()
{
    
//  结束绘制之前Flush一次全部节点
    Flush();
    
//  如果存在特效则结束之
     if (m_pD3DEffect)
        m_pD3DEffect
-> EndEffect();
    
//  还原原始摄影矩阵及投影矩阵
    m_pDevice -> SetTransform(D3DTS_VIEW,        & m_OriViewMatrix);
    m_pDevice
-> SetTransform(D3DTS_PROJECTION,  & m_OriProjMatrix);
}

void  CSpriteBatch::PostFrame(RECT DesRect,RECT SurRect, float  layerDepth,D3DCOLOR Color)
{
    
//  列表新增一个节点
    m_pSpriteNodeList -> push_back(SpriteNode(DesRect,SurRect,layerDepth,Color));
}

void  CSpriteBatch::Flush()
{
    
//  错误排查
     int  NumNodes  =  m_pSpriteNodeList -> size();
    
if (NumNodes  <=   0   ||   ! m_pCurrentTexture)
        
return ;

    
//  动态申请顶点缓冲区与索引缓冲区
    VertexSprite *  vb  =   new  VertexSprite[NumNodes  *   4 ];
    UINT16
*        ib  =   new  UINT16      [NumNodes  *   6 ];
    memset(vb, 
0 sizeof (VertexSprite)  *  NumNodes  *   4 );
    memset(ib, 
0 sizeof (UINT16)        *  NumNodes  *   6 );

    
//  遍历全部节点,合并顶点缓冲及索引缓冲
     int  i  =   0 ;
    
for (list < SpriteNode > ::iterator ptr  =  m_pSpriteNodeList -> begin();ptr  !=  m_pSpriteNodeList -> end(); ++ ptr)
    {
        
//  将纹理区域折合成uv坐标
         float  Txcrd_LU_u  =  ptr -> _SurRect.left / m_pCurrentTexture -> GetWidth();
        
float  Txcrd_LU_v  =  ptr -> _SurRect.top / m_pCurrentTexture -> GetHeight();

        
float  Txcrd_RU_u  =  ptr -> _SurRect.right / m_pCurrentTexture -> GetWidth();
        
float  Txcrd_RU_v  =  ptr -> _SurRect.top / m_pCurrentTexture -> GetHeight();

        
float  Txcrd_RD_u  =  ptr -> _SurRect.right / m_pCurrentTexture -> GetWidth();
        
float  Txcrd_RD_v  =  ptr -> _SurRect.bottom / m_pCurrentTexture -> GetHeight();

        
float  Txcrd_LD_u  =  ptr -> _SurRect.left / m_pCurrentTexture -> GetWidth();
        
float  Txcrd_LD_v  =  ptr -> _SurRect.bottom / m_pCurrentTexture -> GetHeight();

        
//  填充顶点缓冲区数据
        vb[i  *   4     ]  =  VertexSprite(ptr -> _DesRect.left, ptr -> _DesRect.top,   ptr -> _layerDepth,  0.0f 0.0f 0.0f , ptr -> _Color, Txcrd_LU_u, Txcrd_LU_v);
        vb[i 
*   4   +   1 =  VertexSprite(ptr -> _DesRect.right,ptr -> _DesRect.top,   ptr -> _layerDepth,  0.0f 0.0f 0.0f , ptr -> _Color, Txcrd_RU_u, Txcrd_RU_v);
        vb[i 
*   4   +   2 =  VertexSprite(ptr -> _DesRect.right,ptr -> _DesRect.bottom,ptr -> _layerDepth,  0.0f 0.0f 0.0f , ptr -> _Color, Txcrd_RD_u, Txcrd_RD_v);
        vb[i 
*   4   +   3 =  VertexSprite(ptr -> _DesRect.left, ptr -> _DesRect.bottom,ptr -> _layerDepth,  0.0f 0.0f 0.0f , ptr -> _Color, Txcrd_LD_u, Txcrd_LD_v);

        
//  填充索引缓冲区数据
        ib[i  *   6     ]  =  i  *   4 ;
        ib[i 
*   6   +   1 =  i  *   4   +   1 ;
        ib[i 
*   6   +   2 =  i  *   4   +   2 ;
        ib[i 
*   6   +   3 =  i  *   4 ;
        ib[i 
*   6   +   4 =  i  *   4   +   2 ;
        ib[i 
*   6   +   5 =  i  *   4   +   3 ;

        i
++ ;
    }

    
//  应用活动纹理
    m_pDevice -> SetTexture( 0 ,m_pCurrentTexture -> GetTexture());

    
//  如果存在特效则应用全部路径
     if (m_pD3DEffect)
    {
        
for (UINT i = 0 ;i < m_NumPasses;i ++ )
        {
            
//  开启路径
            m_pD3DEffect -> GetEffect() -> BeginPass(i);

            
//  一次性绘制全部顶点
            m_pDevice -> SetFVF(VertexSprite::FVF);
            m_pDevice
-> DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST,  0 , NumNodes  *   4 , NumNodes  *   2 & ib[ 0 ],
                D3DFMT_INDEX16, 
& vb[ 0 ],  sizeof (VertexSprite));

            
//  路径结束
            m_pD3DEffect -> GetEffect() -> EndPass();
        }
    }
    
//  如果不存在特效则采用普通绘制
     else
    {
        
//  一次性绘制全部顶点
        m_pDevice -> SetFVF(VertexSprite::FVF);
        m_pDevice
-> DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST,  0 , NumNodes  *   4 , NumNodes  *   2 & ib[ 0 ],
            D3DFMT_INDEX16, 
& vb[ 0 ],  sizeof (VertexSprite));
    }

    
//  注销顶点缓冲区与索引缓冲区
    delete[] vb;
    delete[] ib;
    
//  清空节点列表数据
    m_pSpriteNodeList -> clear();
}

void  CSpriteBatch::Draw(CTexture2D *  pTexture, const  RECT &  DesRect, const  RECT &  SurRect, const   float &  layerDepth, D3DCOLOR Color)
{
    
//  如果当前没有活动纹理则应用之
     if ( ! m_pCurrentTexture)
        m_pCurrentTexture 
=  pTexture;
    
//  如果当前纹理状态发生变化,则flush现有全部节点
     if (m_pCurrentTexture  !=  pTexture)
    {
        Flush();
        
//  重新应用新的活动纹理
        m_pCurrentTexture  =  pTexture;
    }
    
//  投递新节点数据
    PostFrame(DesRect,SurRect,layerDepth,Color);
}

//  一系列的重载Draw函数

void  CSpriteBatch::Draw(CTexture2D *  pTexture, const  POINT &  Pos, const  RECT &  SurRect, const   float &  layerDepth, D3DCOLOR Color)
{
    RECT rect;
    rect.left   
=  Pos.x;
    rect.top    
=  Pos.y;
    rect.right  
=  Pos.x  +  pTexture -> GetWidth();
    rect.bottom 
=  Pos.y  +  pTexture -> GetHeight();
    Draw(pTexture,rect,SurRect,layerDepth,Color);
}

void  CSpriteBatch::Draw(CTexture2D *  pTexture, const  POINT &  Pos, const   float &  layerDepth, D3DCOLOR Color)
{
    Draw(pTexture,Pos,pTexture
-> GetRect(),layerDepth,Color);
}

void  CSpriteBatch::Draw(CTexture2D *  pTexture, const  RECT &  DesRect, const   float &  layerDepth, D3DCOLOR Color)
{
    Draw(pTexture,DesRect,pTexture
-> GetRect(),layerDepth,Color);
}

void  CSpriteBatch::Draw(CTexture2D *  pTexture, const  POINT &  Pos, const  POINT &  Size, const  RECT &  SurRect, const   float &  layerDepth, D3DCOLOR Color)
{
    RECT rect;
    rect.left   
=  Pos.x;
    rect.top    
=  Pos.y;
    rect.right  
=  Pos.x  +  Size.x;
    rect.bottom 
=  Pos.y  +  Size.y;
    Draw(pTexture,rect,SurRect,layerDepth,Color);
}

void  CSpriteBatch::Draw(CTexture2D *  pTexture, const  POINT &  Pos, const  POINT &  Size, const   float &  layerDepth, D3DCOLOR Color)
{
    Draw(pTexture,Pos,Size,pTexture
-> GetRect(),layerDepth,Color);
}

实现思路上主要参照了Irrlicht引擎的开源代码和shallway 兄的一篇《[SheRO]用D3D绘制2D图像》(http://shallway.net/blog/?p=515)中提到的思路,大家可以点击链接参考一下~

基本的原理是这样的:

如果客户始终采取同一种纹理进行绘制,则我们在不打断设备渲染状态的前提下合并所有精灵节点的顶点缓冲和索引缓冲,然后一次性绘制出来;

如果客户中途切换纹理,则于此前一时刻执行步骤一,如此反复~

需要注意的地方有两点:

1>绘制2D图像相当于直接在屏幕上画图,因此摄影矩阵选取单位矩阵,投影矩阵则由正交投影得来,而并非常规下的透视投影;

2>关于动态生成顶点缓冲区方面,我们使用D3D下的DrawIndexedPrimitiveUP函数。这个函数虽然效率不如DrawIndexedPrimitive函数一次性lock顶点及索引缓冲区再一次性绘制,但却优于此方法反复lock反复绘制。这一问题shallway兄在其博文中使用其他方法解决了,本文的做法主要参照了Irrlicht引擎的实现。

另外,这个类在接口设计上部分借鉴了Xna4.0下SpriteBatch的实现。其Begin函数允许传入一个CD3DEffect对象指针,并在绘制过程中自动应用特效到2D图元——这一点单靠ID3DXSprite是做不到的~

以下是主体代码部分:

Direct3D轮回:为D3D量身订做SpriteBatch类 D3DGame.cpp
/* -------------------------------------

代码清单:D3DGame.cpp
来自:
http://www.cnblogs.com/kenkao

-------------------------------------
*/

#include 
" StdAfx.h "
#include 
" D3DGame.h "
#include 
" D3DCamera.h "
#include 
" D3DEffect.h "
#include 
" CoordCross.h "
#include 
" SimpleXMesh.h "
#include 
" Texture2D.h "
#include 
" D3DSprite.h "
#include 
" SpriteBatch.h "
#include 
< stdio.h >

// ---通用全局变量

HINSTANCE  g_hInst;
HWND       g_hWnd;
D3DXMATRIX g_matProjection;

// ---D3D全局变量

IDirect3D9       
* g_pD3D            =  NULL;
IDirect3DDevice9 
* g_pD3DDevice      =  NULL;
CMouseInput      
* g_pMouseInput     =  NULL;
CKeyboardInput   
* g_pKeyboardInput  =  NULL;
CD3DCamera       
* g_pD3DCamera      =  NULL;
CCoordCross      
* g_pCoordCross     =  NULL;
CSimpleXMesh     
* g_pSimpleXMesh    =  NULL;
CD3DEffect       
* g_pD3DEffect      =  NULL;
CD3DSprite       
* g_pD3DSprite      =  NULL;
CTexture2D       
* g_pTexture2D      =  NULL;
CSpriteBatch     
* g_SpriteBatch     =  NULL;
CTexture2D       
* g_pTexture2D2     =  NULL;
CD3DEffect       
* g_pD3DEffect2     =  NULL;


// ---HLSL全局变量句柄

D3DXHANDLE   g_CurrentTechHandle 
=  NULL;
D3DXHANDLE   g_matWorldViewProj  
=  NULL;  
D3DXHANDLE   g_matWorld          
=  NULL;
D3DXHANDLE   g_vecEye            
=  NULL;
D3DXHANDLE   g_vecLightDir       
=  NULL;
D3DXHANDLE   g_vDiffuseColor     
=  NULL;
D3DXHANDLE   g_vSpecularColor    
=  NULL;
D3DXHANDLE   g_vAmbient          
=  NULL;

D3DXHANDLE   g_CurrentTechHandle2 
=  NULL;
D3DXHANDLE   g_Scale              
=  NULL;

//  HLSL特效参数设置
void  GetParameters();
void  SetParameters();


void  Initialize(HINSTANCE hInst, HWND hWnd)
{
    g_hInst 
=  hInst;
    g_hWnd  
=  hWnd;
    InitD3D(
& g_pD3D,  & g_pD3DDevice, g_matProjection, hWnd);
    g_pMouseInput 
=   new  CMouseInput;
    g_pMouseInput
-> Initialize(hInst,hWnd);
    g_pKeyboardInput 
=   new  CKeyboardInput;
    g_pKeyboardInput
-> Initialize(hInst,hWnd);
    g_pD3DCamera 
=   new  CD3DCamera;
}

void  LoadContent()
{
    g_pCoordCross 
=   new  CCoordCross;

    g_pD3DCamera
-> SetCameraPos(D3DXVECTOR3( 0.5f , 0.5f , - 5.0f ));

    g_pSimpleXMesh 
=   new  CSimpleXMesh;
    g_pSimpleXMesh
-> LoadXMesh( " teapot.X " );

    g_pD3DEffect 
=   new  CD3DEffect;
    g_pD3DEffect2 
=   new  CD3DEffect;
    g_pD3DEffect
-> LoadEffect( " Light.fx " );
    
if ( ! g_pD3DEffect2 -> LoadEffect( " Thunder.fx " ))
        g_pD3DEffect2
-> GetEffectError();

    GetParameters();

    g_pD3DSprite 
=   new  CD3DSprite(g_pD3DDevice);
    g_SpriteBatch 
=   new  CSpriteBatch(g_pD3DDevice);

    g_pTexture2D 
=   new  CTexture2D;
    g_pTexture2D
-> LoadTexture( " img.jpg " );
    g_pTexture2D2 
=   new  CTexture2D;
    g_pTexture2D2
-> LoadTexture( " img2.jpg " );
}

void  Update()
{
    g_pMouseInput
-> GetState();
    g_pKeyboardInput
-> GetState();
    g_pD3DCamera
-> Update();
}

void  Draw()
{
    
//  参数设定
    SetParameters();
    g_pD3DDevice
-> SetTransform(D3DTS_VIEW, & g_pD3DCamera -> GetViewMatrix());

    POINT pos;
    pos.x
= 0 ;
    pos.y
= 0 ;

    POINT pos2;
    pos2.x 
=   440 ;
    pos2.y 
=   260 ;

    g_pD3DDevice
-> Clear( 0 , NULL, D3DCLEAR_TARGET  |  D3DCLEAR_ZBUFFER, D3DCOLOR_RGBA( 100 , 149 , 237 , 255 ),  1.0f 0 );
    
if (SUCCEEDED(g_pD3DDevice -> BeginScene())) 
    {
        g_pCoordCross
-> Draw();

        
//  开始绘制并应用特效
        g_SpriteBatch -> Begin(g_pD3DEffect2);

        
//  CSpriteBatch绘制
        g_SpriteBatch -> Draw(g_pTexture2D2,pos);
        g_SpriteBatch
-> Draw(g_pTexture2D,pos2);

        
//  结束绘制并终止特效
        g_SpriteBatch -> End();

        UINT numPasses;
        
//  开启特效
        g_pD3DEffect -> BeginEffect(numPasses);
        
for (UINT i = 0 ;i < numPasses;i ++ )
        {
            
//  开启路径
            g_pD3DEffect -> GetEffect() -> BeginPass(i);
            
for (DWORD j = 0 ;j < g_pSimpleXMesh -> GetMaterialNum();j ++ )
            {
                g_pSimpleXMesh
-> DrawXMeshSubset(j);
            }
            
//  路径结束
            g_pD3DEffect -> GetEffect() -> EndPass();
        }
        
//  特效结束
        g_pD3DEffect -> EndEffect();
    
        g_pD3DDevice
-> EndScene();
    }
    g_pD3DDevice
-> Present(NULL, NULL, NULL, NULL);
}

void  UnloadContent()
{
    ReleaseCOM(g_pTexture2D2);
    ReleaseCOM(g_pTexture2D);
    ReleaseCOM(g_SpriteBatch);
    ReleaseCOM(g_pD3DSprite);
    ReleaseCOM(g_pD3DEffect2);
    ReleaseCOM(g_pD3DEffect);
    ReleaseCOM(g_pSimpleXMesh);
    ReleaseCOM(g_pCoordCross);
}

void  Dispose()
{
    ReleaseCOM(g_pD3DCamera);
    ReleaseCOM(g_pKeyboardInput);
    ReleaseCOM(g_pMouseInput);
    ReleaseCOM(g_pD3DDevice);
    ReleaseCOM(g_pD3D);
}

void  GetParameters()
{
    
//  获得HLSL中各个全局变量句柄
    g_CurrentTechHandle  =  g_pD3DEffect  ->  GetEffect()  ->  GetTechniqueByName( " SpecularLight " );
    g_matWorldViewProj  
=  g_pD3DEffect  ->  GetEffect()  ->  GetParameterByName( 0 " matWorldViewProj " );
    g_matWorld          
=  g_pD3DEffect  ->  GetEffect()  ->  GetParameterByName( 0 " matWorld " );
    g_vecEye            
=  g_pD3DEffect  ->  GetEffect()  ->  GetParameterByName( 0 " vecEye " );
    g_vecLightDir       
=  g_pD3DEffect  ->  GetEffect()  ->  GetParameterByName( 0 " vecLightDir " );
    g_vDiffuseColor     
=  g_pD3DEffect  ->  GetEffect()  ->  GetParameterByName( 0 " vDiffuseColor " );
    g_vSpecularColor    
=  g_pD3DEffect  ->  GetEffect()  ->  GetParameterByName( 0 " vSpecularColor " );
    g_vAmbient          
=  g_pD3DEffect  ->  GetEffect()  ->  GetParameterByName( 0 " vAmbient " );

    g_CurrentTechHandle2 
=  g_pD3DEffect2  ->  GetEffect()  ->  GetTechniqueByName( " Technique1 " );
    g_Scale              
=  g_pD3DEffect2  ->  GetEffect()  ->  GetParameterByName( 0 " Scale " );
}

void  SetParameters()
{
    
//  设定当前技术
    g_pD3DEffect  ->  GetEffect()  ->  SetTechnique(g_CurrentTechHandle);
    
//  设定HLSL中的各个参数
    D3DXMATRIX worldMatrix;
    D3DXMatrixTranslation(
& worldMatrix, 0.0f , 0.0f , 0.0f );
    g_pD3DEffect 
->  GetEffect()  ->  SetMatrix(g_matWorldViewProj, & (worldMatrix * g_pD3DCamera -> GetViewMatrix() * g_matProjection));
    g_pD3DEffect 
->  GetEffect()  ->  SetMatrix(g_matWorld, & worldMatrix);
    D3DXVECTOR3 cameraPos 
=  g_pD3DCamera -> GetCameraPos();
    D3DXVECTOR4 vecEye 
=  D3DXVECTOR4(cameraPos.x,cameraPos.y,cameraPos.z, 0.0f );
    g_pD3DEffect 
->  GetEffect()  ->  SetVector(g_vecEye, & vecEye);
    D3DXVECTOR4 vLightDirection 
=  D3DXVECTOR4( 0.0f 0.0f - 1.0f 1.0f );
    g_pD3DEffect 
->  GetEffect()  ->  SetVector(g_vecLightDir, & vLightDirection);
    D3DXVECTOR4 vColorDiffuse 
=  D3DXVECTOR4( 0.8f 0.0f 0.0f 1.0f );
    D3DXVECTOR4 vColorSpecular 
=  D3DXVECTOR4( 1.0f 1.0f 1.0f 1.0f );
    D3DXVECTOR4 vColorAmbient 
=  D3DXVECTOR4( 0.1f 0.1f 0.1f 1.0f );
    g_pD3DEffect 
->  GetEffect()  ->  SetVector(g_vDiffuseColor, & vColorDiffuse);
    g_pD3DEffect 
->  GetEffect()  ->  SetVector(g_vSpecularColor, & vColorSpecular);
    g_pD3DEffect 
->  GetEffect()  ->  SetVector(g_vAmbient, & vColorAmbient);

    g_pD3DEffect2 
->  GetEffect()  ->  SetTechnique(g_CurrentTechHandle2);
    g_pD3DEffect2 
->  GetEffect()  ->  SetFloat(g_Scale, 0.8f );
}

最后是特效运用前后的效果对比:

Direct3D轮回:为D3D量身订做SpriteBatch类   Direct3D轮回:为D3D量身订做SpriteBatch类

右图在绘制过程中应用了Thunder.fx代码中的高亮效果(g_pD3DEffect2),代码来源于深蓝团长在其教程中为大家反复推荐的Silverlight专属渲染工具——Shazzam,感兴趣的朋友可以拜读一下团长的教程或者登录Shazzam的官网~

Xna下的SpiritBatch以及本文中实现的CSpiritBatch可以兼容Shazzam提供的所有特效,直接拿来用即可^ ^

 

 

你可能感兴趣的:(Sprite)