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游戏开发论坛一位大侠的提点 ^ ^)
![](http://www.th7.cn/d/file/p/2011/07/07/fdb15c4e19d991af2731c8ab607ad2de.gif)
代码清单: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);
}
效果图: