Direct3D轮回:基于ID3DXSprite的2D元素绘制

D3D中的2D元素绘制主要是通过ID3DXSprite来完成的。

我们通过调用D3DXCreateSprite来完成ID3DXSprite接口对象的创建,同时使用介于Begin与End之间的Draw方法来完成D3D中2D元素的绘制。

下面,我们对IDirect3DTexture9和ID3DXSprite进行二次封装,使其接口趋于人性化,使用起来更加便捷:

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

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

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

#include 
" D3DInit.h "

#pragma  once

class  CTexture2D
{
public :
    CTexture2D(
void );
    
~ CTexture2D( void );
public :
    
void  LoadTexture(                                              // 纹理加载
         char *  szFxFileName,                                        // 文件路径
        UINT SizeX  =  D3DX_DEFAULT_NONPOW2,                         // X默认非2次幂尺寸
        UINT SizeY  =  D3DX_DEFAULT_NONPOW2                          // Y默认非2次幂尺寸
        );
    
void  Release()  {ReleaseCOM(m_pTexture);}                      // 释放纹理
public :
    UINT               GetWidth()       {
return  m_Width;}          // 获得纹理宽
    UINT               GetHight()       { return  m_Height;}         // 获得纹理高
    RECT               GetRect()        { return  m_SurRect;}        // 获得纹理尺寸
    IDirect3DTexture9 *  GetTexture()     { return  m_pTexture;}       // 获得纹理指针
    D3DXIMAGE_INFO     GetTextureInfo() { return  m_TextureInfo;}    // 获得纹理信息
private :
    IDirect3DTexture9
*  m_pTexture;                                 // 纹理指针
    D3DXIMAGE_INFO     m_TextureInfo;                              // 纹理信息
    RECT               m_SurRect;                                  // 纹理尺寸
    UINT               m_Width;                                    // 纹理宽
    UINT               m_Height;                                   // 纹理高
};

 

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

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

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

#include 
" StdAfx.h "
#include 
" Texture2D.h "
#include 
" D3DGame.h "

extern  IDirect3DDevice9 *  g_pD3DDevice;

CTexture2D::CTexture2D(
void ):m_pTexture(NULL)
{
}

CTexture2D::
~ CTexture2D( void )
{
}

void  CTexture2D::LoadTexture( char *  szFxFileName, UINT SizeX, UINT SizeY)
{
    D3DXCreateTextureFromFileEx(
        g_pD3DDevice,
        szFxFileName,
        SizeX, 
        SizeY,
        D3DX_FROM_FILE,
        D3DPOOL_DEFAULT,
        D3DFMT_FROM_FILE,
        D3DPOOL_MANAGED,
        D3DX_DEFAULT,
        D3DX_DEFAULT,
        D3DCOLOR_COLORVALUE(
0.0f , 0.0f , 0.0f , 1.0f ),
        
& m_TextureInfo,
        NULL,
        
& m_pTexture);
    
if (SizeX == (UINT) - 2 )
        m_Width 
=  m_TextureInfo.Width;
    
else
        m_Width 
=  SizeX;
    
if (SizeY == (UINT) - 2 )
        m_Height 
=  m_TextureInfo.Height;
    
else
        m_Height 
=  SizeY;
    m_SurRect.top    
=   0 ;
    m_SurRect.left   
=   0 ;
    m_SurRect.right  
=  m_Width;
    m_SurRect.bottom 
=  m_Height;
}

 

我们依然通过调用D3DXCreateTextureFromFileEx函数从特定的Img文件产生纹理,只不过这次通过传入特定的参数使其产生专门用于2D绘制的纹理。

大家可以看到LoadTexture中的SizeX,SizeY我给定了默认值D3DX_DEFAULT_NONPOW2,意在使所获得的纹理默认支持非二次幂尺寸;而两个值如果默认为0的话,纹理尺寸会被自动拉伸到最相近的二次幂值,这不是我们所期待的结果。

加载完毕的纹理必要信息,会被存放到一个D3DXIMAGE_INFO类型的结构体中,其定义可以参看SDK,很好理解~

 

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

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

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

#include 
" Texture2D.h "

#pragma  once

class  CD3DSprite
{
public :
    CD3DSprite(IDirect3DDevice9
*  pDevice);
    
~ CD3DSprite( void );
public :
    
void  Begin(DWORD Flags);                  //  开启Sprite绘制
     void  End();                               //  结束Sprite绘制
     void  Draw(                                //  绘制Sprite
        CTexture2D *  pTexture,                 //  2D纹理
         const  POINT &  Position,                //  位置
        D3DCOLOR Color                        //  色相
        );
    
void  Draw(
        CTexture2D
*  pTexture, 
        
const  POINT &  Position, 
        
const  RECT &  SurRect,                  //  指定绘制纹理区域
        D3DCOLOR Color
        );
    
void  Draw(
        CTexture2D
*  pTexture, 
        
const  POINT &  Pos, 
        
const  D3DXMATRIX &  TransMatrix,        //  变换矩阵
         const  RECT &  SurRect, 
        D3DCOLOR Color
        );
    
void  Draw(
        CTexture2D
*  pTexture, 
        
const  POINT &  Pos, 
        
const  POINT &  Size,                    //  绘制尺寸
         const  RECT &  SurRect, 
        D3DCOLOR Color
        );
    
void  Draw(
        CTexture2D
*  pTexture, 
        
const  RECT &  DesRect,                  //  指定绘制目标区域
         const  RECT &  SurRect, 
        D3DCOLOR Color
        );
    
void  Draw(
        CTexture2D
*  pTexture, 
        
const  RECT &  DesRect, 
        D3DCOLOR Color
        );
    
void  Release(){ReleaseCOM(m_pSprite)};    //  释放Sprite
public :
    ID3DXSprite
*  GetSprite(){ return  m_pSprite;}    //  获得Sprite指针
private :
    ID3DXSprite
*  m_pSprite;                   //  Sprite指针
    D3DXMATRIX   m_orgMatrix;                 //  原始矩阵
};

 

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

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

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

#include 
" StdAfx.h "
#include 
" D3DSprite.h "

CD3DSprite::CD3DSprite(IDirect3DDevice9
*  pDevice)
{
    D3DXCreateSprite(pDevice, 
& m_pSprite);
    D3DXMatrixTranslation(
& m_orgMatrix, 1.0f , 1.0f , 0.0f );
}

CD3DSprite::
~ CD3DSprite( void )
{
}

void  CD3DSprite::Begin(DWORD Flags)
{
    m_pSprite
-> Begin(Flags);
}

void  CD3DSprite::End()
{
    m_pSprite
-> End();
}

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

void  CD3DSprite::Draw(CTexture2D *  pTexture,  const  POINT &  Pos,  const  RECT &  SurRect, D3DCOLOR Color)
{
    m_pSprite
-> Draw(pTexture -> GetTexture(), & SurRect, & D3DXVECTOR3( 0.0f , 0.0f , 0.0f ), & D3DXVECTOR3(Pos.x,Pos.y, 0.0f ),Color);
}

void  CD3DSprite::Draw(CTexture2D *  pTexture,  const  POINT &  Pos,  const  D3DXMATRIX &  TransMatrix,  const  RECT &  SurRect, D3DCOLOR Color)
{
    
//  设置缩放矩阵
    m_pSprite -> SetTransform( & TransMatrix);
    Draw(pTexture,Pos,SurRect,Color);
    
//  还原缩放矩阵
    m_pSprite -> SetTransform( & m_orgMatrix);
}

void  CD3DSprite::Draw(CTexture2D *  pTexture,  const  POINT &  Pos,  const  POINT &  Size,  const  RECT &  SurRect, D3DCOLOR Color)
{
    D3DXMATRIX TransMatrix;
    FLOAT ScalX, ScalY;
    ScalX 
=  (FLOAT)Size.x / (FLOAT)(SurRect.right - SurRect.left);
    ScalY 
=  (FLOAT)Size.y / (FLOAT)(SurRect.bottom - SurRect.top);
    D3DXMatrixScaling(
& TransMatrix,ScalX,ScalY, 0.0f );
    Draw(pTexture,Pos,TransMatrix,SurRect,Color);
}

void  CD3DSprite::Draw(CTexture2D *  pTexture,  const  RECT &  DesRect,  const  RECT &  SurRect, D3DCOLOR Color)
{
    POINT Pos;
    Pos.x 
=  DesRect.left;
    Pos.y 
=  DesRect.top;
    POINT Size;
    Size.x 
=  DesRect.right  -  DesRect.left;
    Size.y 
=  DesRect.bottom  -  DesRect.top;
    Draw(pTexture, Pos, Size, SurRect, Color);
}

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

 

我们的CD3DSprite在原有ID3DXSprite基础上所做的主要工作是提供了大量的重载Draw函数,以更加人性化的参数设计提供更加便捷的函数调用。

这里值得一提的是

m_pSprite->SetTransform(&TransMatrix);

方法的调用。所传入参数就目前测试来看,只可以是缩放矩阵,平移与旋转矩阵被认定是非法的。ID3DXSprite接口对象就是通过这种方式来完成2D图像的缩放工作的。(感谢CSDN游戏开发论坛一位大侠的提点 ^ ^)

 

Direct3D轮回:基于ID3DXSprite的2D元素绘制 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 
< 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;

// ---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;

//  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;
    
//  加载X网格
    g_pSimpleXMesh -> LoadXMesh( " teapot.X " );
    g_pD3DEffect 
=   new  CD3DEffect;
    
char  ErrMsg[ 60 ];
    
//  加载fx特效
     if ( ! g_pD3DEffect -> LoadEffect( " Light.fx " ,ErrMsg))
        ::MessageBox(g_hWnd,ErrMsg,
0 , 0 );
    
//  获得句柄
    GetParameters();
    g_pD3DSprite 
=   new  CD3DSprite(g_pD3DDevice);
    g_pTexture2D 
=   new  CTexture2D;
    
//  加载纹理
    g_pTexture2D -> LoadTexture( " img.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 ;
    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();

        
//  Sprite绘制开始
        g_pD3DSprite -> Begin(D3DXSPRITE_ALPHABLEND);
        
//  Sprite绘制
        g_pD3DSprite -> Draw(g_pTexture2D,pos,g_pTexture2D -> GetRect(),D3DXCOLOR_WHITE);
        
//  Sprite绘制结束
        g_pD3DSprite -> 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_pTexture2D);
    ReleaseCOM(g_pD3DSprite);
    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 " );
}

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);
}

效果图:

Direct3D轮回:基于ID3DXSprite的2D元素绘制

 

你可能感兴趣的:(Sprite)