Direct3D中的绘制(3)
立方体——只比三角形稍微复杂一点,这个程序渲染一个线框立方体。
这个简单的绘制和渲染立方体的程序的运行结果如下图所示:
源程序:
/**************************************************************************************
Renders a spinning cube in wireframe mode. Demonstrates vertex and index buffers,
world and view transformations, render states and drawing commands.
**************************************************************************************/
#include "d3dUtility.h"
#pragma warning(disable : 4100)
const int WIDTH = 640;
const int HEIGHT = 480;
IDirect3DDevice9* g_d3d_device = NULL;
IDirect3DVertexBuffer9* g_vertex_buffer = NULL;
IDirect3DIndexBuffer9* g_index_buffer = NULL;
class cVertex
{
public:
float m_x, m_y, m_z;
cVertex() {}
cVertex(float x, float y, float z)
{
m_x = x;
m_y = y;
m_z = z;
}
};
const DWORD VERTEX_FVF = D3DFVF_XYZ;
////////////////////////////////////////////////////////////////////////////////////////////////////
bool setup()
{
g_d3d_device->CreateVertexBuffer(8 * sizeof(cVertex), D3DUSAGE_WRITEONLY, VERTEX_FVF,
D3DPOOL_MANAGED, &g_vertex_buffer, NULL);
g_d3d_device->CreateIndexBuffer(36 * sizeof(WORD), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16,
D3DPOOL_MANAGED, &g_index_buffer, NULL);
// fill the buffers with the cube data
cVertex* vertices;
g_vertex_buffer->Lock(0, 0, (void**)&vertices, 0);
// vertices of a unit cube
vertices[0] = cVertex(-1.0f, -1.0f, -1.0f);
vertices[1] = cVertex(-1.0f, 1.0f, -1.0f);
vertices[2] = cVertex( 1.0f, 1.0f, -1.0f);
vertices[3] = cVertex( 1.0f, -1.0f, -1.0f);
vertices[4] = cVertex(-1.0f, -1.0f, 1.0f);
vertices[5] = cVertex(-1.0f, 1.0f, 1.0f);
vertices[6] = cVertex( 1.0f, 1.0f, 1.0f);
vertices[7] = cVertex( 1.0f, -1.0f, 1.0f);
g_vertex_buffer->Unlock();
// define the triangles of the cube
WORD* indices = NULL;
g_index_buffer->Lock(0, 0, (void**)&indices, 0);
// front side
indices[0] = 0; indices[1] = 1; indices[2] = 2;
indices[3] = 0; indices[4] = 2; indices[5] = 3;
// back side
indices[6] = 4; indices[7] = 6; indices[8] = 5;
indices[9] = 4; indices[10] = 7; indices[11] = 6;
// left side
indices[12] = 4; indices[13] = 5; indices[14] = 1;
indices[15] = 4; indices[16] = 1; indices[17] = 0;
// right side
indices[18] = 3; indices[19] = 2; indices[20] = 6;
indices[21] = 3; indices[22] = 6; indices[23] = 7;
// top
indices[24] = 1; indices[25] = 5; indices[26] = 6;
indices[27] = 1; indices[28] = 6; indices[29] = 2;
// bottom
indices[30] = 4; indices[31] = 0; indices[32] = 3;
indices[33] = 4; indices[34] = 3; indices[35] = 7;
g_index_buffer->Unlock();
// position and aim the camera
D3DXVECTOR3 position(0.0f, 0.0f, -5.0f);
D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
D3DXMATRIX view_matrix;
D3DXMatrixLookAtLH(&view_matrix, &position, &target, &up);
g_d3d_device->SetTransform(D3DTS_VIEW, &view_matrix);
// set the projection matrix
D3DXMATRIX proj;
D3DXMatrixPerspectiveFovLH(&proj, D3DX_PI * 0.5f, (float)WIDTH/HEIGHT, 1.0f, 1000.0f);
g_d3d_device->SetTransform(D3DTS_PROJECTION, &proj);
// set wireframe mode render state
g_d3d_device->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
return true;
}
void cleanup()
{
safe_release<IDirect3DVertexBuffer9*>(g_vertex_buffer);
safe_release<IDirect3DIndexBuffer9*>(g_index_buffer);
}
bool display(float time_delta)
{
// spin the cube
D3DXMATRIX rx, ry;
// rotate 45 degree on x-axis
D3DXMatrixRotationX(&rx, 3.14f/4.0f);
// increment y-rotation angle each frame
static float y = 0.0f;
D3DXMatrixRotationY(&ry, y);
y += time_delta;
// reset angle to zero when angle reaches 2*PI
if(y >= 6.28f)
y = 0.0f;
// combine x and y axis ratation transformations
D3DXMATRIX rxy = rx * ry;
g_d3d_device->SetTransform(D3DTS_WORLD, &rxy);
// draw the scene
g_d3d_device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
g_d3d_device->BeginScene();
g_d3d_device->SetStreamSource(0, g_vertex_buffer, 0, sizeof(cVertex));
g_d3d_device->SetIndices(g_index_buffer);
g_d3d_device->SetFVF(VERTEX_FVF);
// draw cube
g_d3d_device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 0, 12);
g_d3d_device->EndScene();
g_d3d_device->Present(NULL, NULL, NULL, NULL);
return true;
}
LRESULT CALLBACK wnd_proc(HWND hwnd, UINT msg, WPARAM word_param, LPARAM long_param)
{
switch(msg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_KEYDOWN:
if(word_param == VK_ESCAPE)
DestroyWindow(hwnd);
break;
}
return DefWindowProc(hwnd, msg, word_param, long_param);
}
int WINAPI WinMain(HINSTANCE inst, HINSTANCE, PSTR cmd_line, int cmd_show)
{
if(! init_d3d(inst, WIDTH, HEIGHT, true, D3DDEVTYPE_HAL, &g_d3d_device))
{
MessageBox(NULL, "init_d3d() - failed.", 0, MB_OK);
return 0;
}
if(! setup())
{
MessageBox(NULL, "Steup() - failed.", 0, MB_OK);
return 0;
}
enter_msg_loop(display);
cleanup();
g_d3d_device->Release();
return 0;
}
setup函数创建顶点和索引缓存,锁定它们,把构成立方体的顶点写入顶点缓存,以及把定义立方体的三角形的索引写入索引缓存。然后把摄象机向后移动几个单位以便我们能够看见在世界坐标系中原点处被渲染的立方体。
display方法有两个任务;它必须更新场景并且紧接着渲染它。既然想旋转立方体,那么我们将对每一帧增加一个角度使立方体能在这一帧旋转。对于这每一帧,立方体将被旋转一个很小的角度,这样我们看起来旋转就会更平滑。接着我们使用IDirect3DDevice9::DrawIndexedPrimitive方法来绘制立方体。
最后,我们释放使用过的所有内存。这意味着释放顶点和索引缓存接口。