您的位置:首页 > 其它

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

2011-07-05 21:53 281 查看
上一节中,我们大致讲述了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; // 精灵节点列表
};

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);
}
最后是特效运用前后的效果对比:





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

Xna下的SpiritBatch以及本文中实现的CSpiritBatch可以兼容Shazzam提供的所有特效,直接拿来用即可^ ^
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: