立方体——只比三角形稍微复杂一点,这个程序渲染一个线框立方体。

这个简单的绘制和渲染立方体的程序的运行结果如下图所示:

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方法来绘制立方体。

最后,我们释放使用过的所有内存。这意味着释放顶点和索引缓存接口。

下载立方体演示程序

我最擅长从零开始创造世界,所以从来不怕失败,它最多也就让我一无所有。