代码改变世界

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

2011-07-03 11:07  独孤残云  阅读(6173)  评论(14编辑  收藏  举报

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游戏开发论坛一位大侠的提点 ^ ^)

 

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.0f0);
    
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.0f0.0f-1.0f1.0f);
    g_pD3DEffect 
-> GetEffect() -> SetVector(g_vecLightDir,&vLightDirection);
    D3DXVECTOR4 vColorDiffuse 
= D3DXVECTOR4(0.8f0.0f0.0f1.0f);
    D3DXVECTOR4 vColorSpecular 
= D3DXVECTOR4(1.0f1.0f1.0f1.0f);
    D3DXVECTOR4 vColorAmbient 
= D3DXVECTOR4(0.1f0.1f0.1f1.0f);
    g_pD3DEffect 
-> GetEffect() -> SetVector(g_vDiffuseColor,&vColorDiffuse);
    g_pD3DEffect 
-> GetEffect() -> SetVector(g_vSpecularColor,&vColorSpecular);
    g_pD3DEffect 
-> GetEffect() -> SetVector(g_vAmbient,&vColorAmbient);
}

效果图: