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.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);
}
效果图: