【前置条件】:
完成第二篇的内容。
【说明】
在学DirectX SDK 9.0自带的Sample时,总是感觉手痒,因为代码不是面向对象的,看起来很不爽。于是就想着自己来封装下,同时也在一步一步的学习D3D。
在前两篇,把D3D相关的对象抽取到了Graphics类里,今天,打算把渲染的一些数据对象抽取出来。
【具体做法】
首先,定义一个纯虚类——RenderObject
#ifndef __RENDER_OBJECT_H__
#define __RENDER_OBJECT_H__
#include <d3dx9.h>
class RenderObject
{
public:
RenderObject(){}
virtual ~RenderObject() {}
virtual bool Setup(LPDIRECT3DDEVICE9 pD3dDevice) = 0;
virtual void Render(LPDIRECT3DDEVICE9 pD3dDevice) = 0;
};
#endif // end __RENDER_OBJECT_H__
然后,写一个Box类:
Box.h
#ifndef __BOX_H__
#define __BOX_H__
#include "RenderObject.h"
#include "Common.h"
class MyBox : public RenderObject
{
public:
MyBox();
~MyBox();
bool Setup(LPDIRECT3DDEVICE9 pD3dDevice);
void Render(LPDIRECT3DDEVICE9 pD3dDevice);
private:
// Vertex buffer
LPDIRECT3DVERTEXBUFFER9 m_pVertexBuffer;
// Index buffer
LPDIRECT3DINDEXBUFFER9 m_pIndexBuffer;
};
#endif
Box.cpp
#include "Box.h"
MyBox::MyBox()
{
m_pVertexBuffer = NULL;
m_pIndexBuffer = NULL;
}
MyBox::~MyBox()
{
if( m_pVertexBuffer != NULL )
m_pVertexBuffer->Release();
if( m_pIndexBuffer != NULL )
m_pIndexBuffer->Release();
}
bool MyBox::Setup(LPDIRECT3DDEVICE9 pD3dDevice)
{
if( FAILED( pD3dDevice->CreateVertexBuffer(8*sizeof(CUSTOM_VERTEX),
D3DUSAGE_WRITEONLY,
D3DFVF_CUSTOMVERTEX,
D3DPOOL_MANAGED,
&m_pVertexBuffer,
0) ) )
return false;
if( FAILED( pD3dDevice->CreateIndexBuffer(36*sizeof(WORD),
D3DUSAGE_WRITEONLY,
D3DFMT_INDEX16,
D3DPOOL_MANAGED,
&m_pIndexBuffer,
0) ) )
return false;
CUSTOM_VERTEX* vertices;
if( FAILED( m_pVertexBuffer->Lock(0, 0, (void**)&vertices, 0) ) )
return false;
vertices[0].position = D3DXVECTOR3(-1.0f, -1.0f, -1.0f);
vertices[1].position = D3DXVECTOR3(-1.0f, 1.0f, -1.0f);
vertices[2].position = D3DXVECTOR3( 1.0f, 1.0f, -1.0f);
vertices[3].position = D3DXVECTOR3( 1.0f, -1.0f, -1.0f);
vertices[4].position = D3DXVECTOR3(-1.0f, -1.0f, 1.0f);
vertices[5].position = D3DXVECTOR3(-1.0f, 1.0f, 1.0f);
vertices[6].position = D3DXVECTOR3( 1.0f, 1.0f, 1.0f);
vertices[7].position = D3DXVECTOR3( 1.0f, -1.0f, 1.0f);
vertices[0].color = 0xffffffff;
vertices[1].color = 0xffffffff;
vertices[2].color = 0xffffffff;
vertices[3].color = 0xffffffff;
vertices[4].color = 0xffffffff;
vertices[5].color = 0xffffffff;
vertices[6].color = 0xffffffff;
vertices[7].color = 0xffffffff;
m_pVertexBuffer->Unlock();
WORD* indices = 0;
if( FAILED( m_pIndexBuffer->Lock(0, 0, (void**)&indices, 0) ) )
return false;
indices[0] = 0; indices[1] = 1; indices[2] = 2;
indices[3] = 0; indices[4] = 2; indices[5] = 3;
indices[6] = 4; indices[7] = 6; indices[8] = 5;
indices[9] = 4; indices[10] = 7; indices[11] = 6;
indices[12] = 4; indices[13] = 5; indices[14] = 1;
indices[15] = 4; indices[16] = 1; indices[17] = 0;
indices[18] = 3; indices[19] = 2; indices[20] = 6;
indices[21] = 3; indices[22] = 6; indices[23] = 7;
indices[24] = 1; indices[25] = 5; indices[26] = 6;
indices[27] = 1; indices[28] = 6; indices[29] = 2;
indices[30] = 4; indices[31] = 0; indices[32] = 3;
indices[33] = 4; indices[34] = 3; indices[35] = 7;
m_pIndexBuffer->Unlock();
return true;
}
void MyBox::Render(LPDIRECT3DDEVICE9 pD3dDevice)
{
pD3dDevice->SetStreamSource(0, // 管道流水线编号
m_pVertexBuffer, // 顶点缓冲区指针
0, // 缓冲区的数据字节偏移
sizeof(CUSTOM_VERTEX)); // 顶点带宽
pD3dDevice->SetIndices(m_pIndexBuffer);
pD3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
<span style="white-space:pre"> </span>pD3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, 8, 0, 12);
}
Common.h 里存放的自定义顶点格式:
#ifndef __COMMON_H__
#define __COMMON_H__
// #define SHOW_HOW_TO_USE_TCI
struct CUSTOM_VERTEX
{
D3DXVECTOR3 position; // The 3D position for the vertex
//D3DXVECTOR3 normal; // The surface normal for the vertex
D3DCOLOR color; // The color
#ifndef SHOW_HOW_TO_USE_TCI
FLOAT tu, tv; // The texture coordinates
#endif
};
// Our custom FVF, which describes our custom vertex structure
#ifndef SHOW_HOW_TO_USE_TCI
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)
#else
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)
#endif
#endif // __COMMON_H__
接下来,精简 Graphics 类的 InitTestGeometry 方法:
m_pRenderBox = new MyBox();
if( m_pRenderBox->Setup(m_pD3dDevice); )
return true;
return false;
在 Graphics::Render 里,在 EndScene 之前,调用:
m_pRenderBox->Render(m_pD3dDevice);
即可。