立方體——只比三角形稍微復雜一點,這個程序渲染一個線框立方體。
這個簡單的繪制和渲染立方體的程序的運行結果如下圖所示:
源程序:
/**************************************************************************************
? 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方法來繪制立方體。
最后,我們釋放使用過的所有內存。這意味著釋放頂點和索引緩存接口。
下載立方體演示程序