首先向大家道歉自3出了以后隔這么久才出4,一方面過年期間我天天在外面走親戚,另一方面我最近確實有些消沉,我不是個會太監(jiān)的人,卻總是有時會陷入一種消沉的狀態(tài),因為想從軟件行業(yè)轉型,碰了許多壁,關起門來看龍書和算法導論,基本保持不上網狀態(tài),偶爾手機上上人人網分享點日志。
我也知道我的文章并不是多么的不可或缺,沒了這個翻譯大家照樣過,目前為止基本都是些入門類的東西,有時候我會想到曾小賢的午夜節(jié)目,那個夜晚被胡一非痛罵才明白原來自己做的并不是沒有意義,消沉的這段時間,看到陸續(xù)還有幾個網友留言鼓勵我,我真的非常感謝你們,我不是什么大神,也不是什么天才,我高數重修了兩遍才過,非是不努力而是真的智力不足學起來比別人要多花幾倍的時間,但我只是一直努力著,欠了38個學分的時候我沒有選擇提前留級(如果學年結束時欠了36分以上會退學),我苦行僧般地過了下半學年勉強保住不留級(24學分),剛來上海的時候我是C盲(之前一直搞WEB),沒有數據結構的基礎不懂STL但我還是撐過來了,四個月以后輕松地完成工作,八個月以后我覺得我們的代碼到處是問題,不管遇到怎樣的困境,我從來沒有放棄過,就像我經常消沉但我總會走出來結束太監(jiān)狀態(tài),希望在看這篇翻譯的你,無論在技術還是生活上,永遠不要輕言放棄,不管在怎樣的困境,只要有1%的希望,就值得我們拼盡全力去爭取,人之所以能戰(zhàn)勝神,是因為我們相信著的奇跡。
課程概述
有一個簡單的方式來學習的DirectX。杯具的是,簡單的方法往往有很多功能上的限制,即使沒有,在一個比較大型的游戲使用它仍然會很麻煩。當然,更簡單的 方法是,努力地學習,本教程會盡量寫得更易于編程,以便不使理論的部分太艱深晦澀。
在本節(jié)中,您將學習如何在屏幕上畫一個三角形。我們將通過創(chuàng)造一系列頂點來構建三角并通過Direct3D設備在屏幕上繪制之。
首先,我們將涵蓋如何工作的,那么我們將在代碼本身和生成程序的理論。
靈活頂點格式(Flexible Vertex Formats)
如果您完成了第3課中的學習,你會記得頂點的定義:一個確定在在三維空間中的點的精確位置和屬性。位置只包含三個坐標數值以描述頂點在空間中的位置。頂點的屬性也用數值定義。
Direct3D使用一種稱為靈活頂點格式(Flexible Vertex Format簡稱FVF)的技術。該技術中一個頂點格式包含一個頂點的位置和多個屬性數據。一個FVF頂點會是一個格式化的數據,您可以根據您的需要修改和設置。讓我們來看看究竟丫是如何工作的。
頂點可以用一個結構體來描述,它包含所有與創(chuàng)建該3D圖像有關的數據。為了展示這個圖像,我們要把所有的信息復制到視頻RAM,然后讓Direct3D來復制數據到后臺緩沖區(qū)。然而,如果我們不得不把一個頂點所有可能需要的數據發(fā)送過去會怎樣呢?如下圖所示。

Image 4.1 - 一個頂點格式包含了所有的信息
當然,你可能不會馬上看到這兒有什么問題,但讓我們不得不說我們只需要這些信息中的兩塊。我們可以看到將其發(fā)送到視頻RAM會快得多,就像這樣:

Image 4.2 – FVF格式會快得多
這就是在我們使用FVF時發(fā)生的。我們選擇我們要使用的信息,并發(fā)送之,這樣就可以使我們在每幀之間發(fā)送更多的頂點。
FVF 代碼
在Direct3D中,每個頂點都是預先設定好的頂點格式。正如標題聲稱,這種格式是靈活的,是使用的Direct3D提供的某些元素。這些元素通過使用特殊標識來設置,比如何時邏輯或在一起,創(chuàng)建一個頂點的定義,或一個告訴Direct3D頂點格式代碼的。
讓我們來看看它如何做到這一點。比方說,我們希望包括位置和我們的頂點漫反射顏色。我們將建立一個代碼:
#define CUSTOMFVF (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)
稍后,我們將簡單地使用CUSTOMFVF,而不是每次都輸出整個FVF代碼。我們將在一分鐘后來看這樣的一個例子。
我們可以在這個表達式里添加各種標識。以下是一組貫穿本套教程始終的標識表,以及他們做什么的說明。
[Table 4.1 - FVF Code Flags]
標識
|
描述
|
參數類型
|
D3DFVF_XYZ
|
表示該頂點格式包括X,Y和Z的一個未轉換的頂點坐標。未轉化意味著頂點尚未轉化為屏幕坐標。
|
float, float, float
|
D3DFVF_XYZRHW
|
表示該頂點格式包括X,Y和Z坐標以及一個轉換過的額外的RHW值。這意味著頂點已經在屏幕坐標系。Z和RHW會在構建軟件引擎時使用,我們不會進入。
|
float, float, float, float
|
D3DFVF_DIFFUSE
|
表示頂點格式包含一個32位顏色代碼,用于表示漫射光顏色。
|
DWORD
|
D3DFVF_SPECULAR
|
表示頂點格式包含一個32位顏色代碼,用于鏡面高亮使用的顏色。
|
DWORD
|
D3DFVF_TEX0 through D3DFVF_TEX8
|
表示頂點格式包含任何將被應用到模型紋理坐標。
|
float, float
|
[Close Table]
|
|
|
當然了,還有更多的標識沒有被提及,它們已經是包含在DirectX文檔中了。而我們只需要本教程中使用到的這些標識。
創(chuàng)建頂點
現在我們需要使用我們的新格式創(chuàng)建頂點。我們不使用任何新函數或諸如此類的東西,我們通過建立一個簡單的結構體裝入FVF代碼中包含的變量。
例如,我們用在上面的例子用D3DFVF_XYZRHW和D3DFVF_DIFFUSE兩個標識一起的話,我們應該建立如下結構:
struct CUSTOMVERTEX


{
FLOAT x, y, z, rhw; // from the D3DFVF_XYZRHW flag
DWORD color; // from the D3DFVF_DIFFUSE flag
}
如你所見,前四個浮點數是D3DFVF_XYZRHW標識的值,而DWORD是D3DFVF_DIFFUSE標識的值。如果您看看上表,你會發(fā)現這其中的變量類型與FVF標識。
現在,讓我們使用我們的新CUSTOMVERTEX結構來構建一個實際的頂點。我們可以像下面這樣做:

CUSTOMVERTEX OurVertex =
{320.0f, 50.0f, 1.0f, 1.0f, D3DCOLOR_XRGB(0, 0, 255)};
當然了,你也可以弄個頂點數組,就像這樣:
CUSTOMVERTEX OurVertices[] =


{

{320.0f, 50.0f, 1.0f, 1.0f, D3DCOLOR_XRGB(0, 0, 255),},

{520.0f, 400.0f, 1.0f, 1.0f, D3DCOLOR_XRGB(0, 255, 0),},

{120.0f, 400.0f, 1.0f, 1.0f, D3DCOLOR_XRGB(255, 0, 0),},
};
結果會是一個三角形,我們很快會在屏幕上看到。
這僅僅是一個靈活頂點格式的示例。我們稍后會繼續(xù)就如何建立更復雜的頂點格式,恩,就從現在開始吧。
頂點緩存
現在,我們已經完成了兩件事情。首先,我們建立了FVF代碼。第二,我們已經創(chuàng)建了一個三角形?,F在我們需要得到那個三角形以準備給Direct3D使用。要做到這一點,我們創(chuàng)建了所謂的頂點緩沖區(qū)。
一個頂點緩沖區(qū)是一個簡單的接口,它存儲在一段內存中(顯存或內存),以持有你的游戲中頂點或模型的信息。我們通過函數CreateVertexBuffer()來創(chuàng)建這個接口。不過它的參數有點復雜。下面是函數原型:
HRESULT CreateVertexBuffer(
UINT Length,
DWORD Usage,
DWORD FVF,
D3DPOOL Pool,
LPDIRECT3DVERTEXBUFFER9 ppVertexBuffer,
HANDLE* pSharedHandle);

我們來逐個分析一下這些個參數
UINT Length,
這個參數包含將要創(chuàng)建的頂點緩存的大小。我們得到將存儲在緩沖區(qū)中的頂點數目乘以一個頂點大小的結果。例如,一個三角形包含三個頂點,因此該三角形的緩沖區(qū)大小是:3* sizeof(CUSTOMVERTEX)。
DWORD Usage,
有時候,有些特殊的方法能改變DirectX處理的頂點集。在本教程我們不會深入討論這些。這個參數可以包含標志表明這些特殊的方式。因為我們不會使用任何所以我們只要把它設置為0。
DWORD FVF,
這是FVF代碼中我們接觸得比較早的。我們只需填寫CUSTOMFVF。如果我們要改變FVF代碼,這部分也將改變(改變那個#define)。這是告訴DirectX頂點是什么格式了,這個參數很重要。
D3DPOOL Pool,
這個參數告訴Direct3D在哪創(chuàng)建頂點緩存以及如何創(chuàng)建之。以下是一個表,說明該參數的可能的條目。在本教程中,我們將使用標志D3DPOOL_MANAGED。
[Table 4.2 - D3DPOOL Values]
值
|
描述
|
D3DPOOL_DEFAULT
|
此標志表示該緩存應該創(chuàng)建在最適當的內存以便設置和資源可用。然而,強加一些限制并不總是對游戲有好處。
|
D3DPOOL_MANAGED
|
這表明,緩沖將在位于顯存
|
D3DPOOL_SYSTEMMEM
|
這表明,緩存將在系統(tǒng)內存中。頂點緩存設在這里通常不能由Direct3D設備訪問,但可以通過其他更高級的手段訪問。
|
D3DPOOL_SCRATCH
|
這也表明了緩存將坐落在系統(tǒng)內存中,但是,又沒有辦法讓顯存訪問它。這種類型一般用于存儲圖像信息,現在我們用不到(但稍后將使用),比如屏幕已經轉到另一個地圖但角色暫時還沒有到達(不久后就到)。
|
[Close Table]
|
|
LPDIRECT3DVERTEXBUFFER9 ppVertexBuffer,
如果你理解它,那我告訴你它是我們正在創(chuàng)建的頂點緩存的接口。我們給這個參數一個空指針,函數會給他賦值。
HANDLE* pSharedHandle
文檔里說過這個參數,我引述一下:“保留。設置這個參數為NULL。“我不能說肯定,但顯然微軟希望我們將其設置為NULL。就這樣吧。我們將它設置為NULL。
看完這些參數,讓我們來看看這個功能在我們的程序中如何寫:
LPDIRECT3DVERTEXBUFFER9 v_buffer;

d3ddev->CreateVertexBuffer(3*sizeof(CUSTOMVERTEX),
0,
CUSTOMFVF,
D3DPOOL_MANAGED,
&v_buffer,
NULL);

現在您已經創(chuàng)建了頂點緩存,下面你需要把頂點加載進去。你用一個簡單的函數memcpy()就可以完成。但是,在您訪問到頂點緩存之前,你需要將其鎖定。
基于兩個原因,你需要鎖定這個緩存。首先,你需要告訴Direct3D你需要內存的完全控制權。換句話說,它不應該由任何可能的其他進程使用。第二,你需要告訴視頻硬件別動它。否則可沒法保證顯存保持不動。鎖定告訴顯存與內存當你正在使用它時別干蠢事兒。
要鎖定一個緩沖區(qū),可以使用函數Lock(),它有四個參數,但都相當簡單:
HRESULT Lock(UINT OffsetToLock,
UINT SizeToLock,
VOID** ppbData,
DWORD Flags);
讓我們來看看這些參數:
UINT OffsetToLock, UINT SizeToLock,
如果我們只是想鎖定我們的頂點緩沖的一部分,我們將表明在這兩個參數。第一個指示自緩存的起始點到開始鎖定位置的偏移量,以字節(jié)為單位。第二個表示多少字節(jié)被鎖定。因為我們現在要鎖定整個緩沖區(qū),所以我們將設置這些都為0。
VOID** ppbData,
除非你是至少中等水平以上的C+ +,否則這個參數您老還是別動了?;旧线@是一個void*指針并且沒有指向特定類型的變量。例如,一個**double,而一個int*指向一個int。每個指針類型都有它自己的格式,因此它不能轉換不會丟失數據為另一種類型。但是一個void *指針,卻可以轉換為任何類型。
在這里,我們有一個空指針*.這個指針被鎖定的存數去起始位置的指針。頂點緩沖區(qū)接口會處理其細節(jié),但我們在下一步會需要這個指針。所以函數lock()函數將填充恰當的地址給這個指針。有一個在下面的例子,看看我們如何填補這個參數。
DWORD Flags
這是一個很高級的參數,我們不會在本教程中深入。本上它提供特殊的方式來處鎖定內存。如果你是真正感興趣的,它們可以研究在DirectX文檔?,F在,我們只是將它設置為0。
讓我們來補完這個函數,看看它的樣子:
VOID* pVoid; // the void* we were talking about

v_buffer->Lock(0, 0, (void**)&pVoid, 0); // locks v_buffer, the buffer we made earlier
接下來,我們調用memcpy()復制頂點到頂點緩存。
memcpy(pVoid, OurVertices, sizeof(OurVertices)); // copy vertices to the vertex buffer
最后,我們還有一個非常復雜的函數:Unlock()。這個函數沒有參數。它所做的是告訴Direct3D,跟內存搞完了,解開束縛吧。寫起來像這樣:
v_buffer->Unlock(); // unlock v_buffer
由于我們剛剛得知命令的數量,我們要把我們自己創(chuàng)建的功能放進一個單獨的函數里init_graphics()。
void init_graphics(void)


{
// create three vertices using the CUSTOMVERTEX struct built earlier
CUSTOMVERTEX vertices[] =

{

{ 320.0f, 50.0f, 0.5f, 1.0f, D3DCOLOR_XRGB(0, 0, 255), },

{ 520.0f, 400.0f, 0.5f, 1.0f, D3DCOLOR_XRGB(0, 255, 0), },

{ 120.0f, 400.0f, 0.5f, 1.0f, D3DCOLOR_XRGB(255, 0, 0), },
};

// create the vertex and store the pointer into v_buffer, which is created globally
d3ddev->CreateVertexBuffer(3*sizeof(CUSTOMVERTEX),
0,
CUSTOMFVF,
D3DPOOL_MANAGED,
&v_buffer,
NULL);

VOID* pVoid; // the void pointer

v_buffer->Lock(0, 0, (void**)&pVoid, 0); // lock the vertex buffer
memcpy(pVoid, vertices, sizeof(vertices)); // copy the vertices to the locked buffer
v_buffer->Unlock(); // unlock the vertex buffer
}
在這里,我建議您多讀幾次以確保你徹底明白了這一切。這是3D編程中一個相當關鍵的的部分,我們將在教程的休息時間使用和修改它。
繪制圖元
現在,我們實際上已經獲得屏幕上的內容!但在此發(fā)生之前我們有三個非常簡單的函數要認識一下。每一個被從Direct3D設備接口調用。讓我們來看看。
SetFVF()
這些函數的第一個是SetFVF()。 SetFVF()是一種告訴Direct3D使用當前使用什么樣的FVF代碼的函數。我們當然可以有多個FVF代碼并使用在兩個不同的三維場景。在我們開始畫之前,我們只需要告訴我們的Direct3D使用的是哪一個。這個函數寫出來是這樣的:
d3ddev->SetFVF(CUSTOMFVF);
SetStreamSource()
下一步,我們的函數SetStreamSource(),它告訴Direct3D我們從哪個頂點緩沖取頂點。這其中有一對參數,讓我們來看看函數原型:
HRESULT SetStreamSource(UINT StreamNumber,
LPDIRECT3DVERTEXBUFFER9 pStreamData,
UINT OffsetInBytes,
UINT Stride);

第一個參數是要用的頂點緩存的序號。我們稍后深入它的工作原理,但現在將它設置為0,因為我們只有一個頂點緩沖區(qū)。
第二個參數是指向我們先前創(chuàng)建的頂點緩存的指針。
第三個參數指應該從頂點緩沖的第幾個字節(jié)開始。這通常是0。
最后一個參數是每個頂點的大小。我們填寫如下: SizeOf(CUSTOMVERTEX)。
讓我們來看看在函數怎樣被調用:
d3ddev->SetStreamSource(0, v_buffer, 0, sizeof(CUSTOMVERTEX));
DrawPrimitive()
現在我們已經告訴Direct3D我們正在使用哪種格式的頂點以及哪里得到它們,我們告訴它請繪制我們已經建立的頂點。這個函數繪制在選定的頂點緩存的圖元到屏幕上。這里是函數原型:
HRESULT DrawPrimitive(D3DPRIMITIVETYPE PrimitiveType,
UINT StartVertex,
UINT PrimitiveCount);
第一個參數是使用的圖元類型。這些在第3課已經講過了,但所用的代碼在這里:
[Table 4.3 - D3DPRIMITIVETYPE Values]
Value
|
Description
|
D3DPT_POINTLIST
|
點陣

|
D3DPT_LINELIST
|
線列表

|
D3DPT_LINESTRIP
|
線帶

|
D3DPT_TRIANGLELIST
|
三角形列表

|
D3DPT_TRIANGLESTRIP
|
三角形帶

|
D3DPT_TRIANGLEFAN
|
三角扇形

|
[Close Table]
|
|
第二個參數是我們要繪制在屏幕上的第一個頂點的序號。如果我們愿意,我們可以在頂點緩沖區(qū)的中間開始。但是,現在我們希望繪制整個緩沖區(qū),因此我們將在這里把0。
第三個也是最后一個參數是我們要繪制圖元的數量。如果我們要畫一個三角形,我們設1(只有一個三角形)。如果我們畫點,我們會設為3,有三點。畫線條也是設為3。
現在讓我們來看看整個render_frame()函數,現在我們已經修改了它。
// this is the function used to render a single frame
void render_frame(void)


{
d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);

d3ddev->BeginScene();

// select which vertex format we are using
d3ddev->SetFVF(CUSTOMFVF);

// select the vertex buffer to display
d3ddev->SetStreamSource(0, v_buffer, 0, sizeof(CUSTOMVERTEX));

// copy the vertex buffer to the back buffer
d3ddev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);

d3ddev->EndScene();

d3ddev->Present(NULL, NULL, NULL, NULL);
}

在看整個程序之前,先來看看最后一個步驟是很有必要的。
釋放頂點緩存
就像Direct3D設備和Direct3D一樣,頂點緩沖區(qū)也必須在程序關閉之前被釋放。
// this is the function that cleans up Direct3D and COM
void cleanD3D(void)


{
v_buffer->Release(); // close and release the vertex buffer
d3ddev->Release(); // close and release the 3D device
d3d->Release(); // close and release Direct3D
}

現在讓我們來看看整個程序,看看我們都干了什么。
最終代碼
好吧,讓我們來看看這個三角長啥樣。如果你從來沒有見過三角形,這將是一個教育的經驗。否則你可以看到一個三角形是made in Direct3D。
無論如何,讓我們來看看最后的DirectX代碼。在本課程中所涵蓋的新的部分像往常是加粗的。
1
// include the basic windows header files and the Direct3D header file
2
#include <windows.h>
3
#include <windowsx.h>
4
#include <d3d9.h>
5
6
// define the screen resolution
7
#define SCREEN_WIDTH 800
8
#define SCREEN_HEIGHT 600
9
10
// include the Direct3D Library file
11
#pragma comment (lib, "d3d9.lib")
12
13
// global declarations
14
LPDIRECT3D9 d3d; // the pointer to our Direct3D interface
15
LPDIRECT3DDEVICE9 d3ddev; // the pointer to the device class
16
LPDIRECT3DVERTEXBUFFER9 v_buffer = NULL; // the pointer to the vertex buffer
17
18
// function prototypes
19
void initD3D(HWND hWnd); // sets up and initializes Direct3D
20
void render_frame(void); // renders a single frame
21
void cleanD3D(void); // closes Direct3D and releases memory
22
void init_graphics(void); // 3D declarations
23
24
struct CUSTOMVERTEX
{FLOAT X, Y, Z, RHW; DWORD COLOR;};
25
#define CUSTOMFVF (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)
26
27
// the WindowProc function prototype
28
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
29
30
31
// the entry point for any Windows program
32
int WINAPI WinMain(HINSTANCE hInstance,
33
HINSTANCE hPrevInstance,
34
LPSTR lpCmdLine,
35
int nCmdShow)
36

{
37
HWND hWnd;
38
WNDCLASSEX wc;
39
40
ZeroMemory(&wc, sizeof(WNDCLASSEX));
41
42
wc.cbSize = sizeof(WNDCLASSEX);
43
wc.style = CS_HREDRAW | CS_VREDRAW;
44
wc.lpfnWndProc = WindowProc;
45
wc.hInstance = hInstance;
46
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
47
wc.lpszClassName = L"WindowClass";
48
49
RegisterClassEx(&wc);
50
51
hWnd = CreateWindowEx(NULL,
52
L"WindowClass",
53
L"Our Direct3D Program",
54
WS_OVERLAPPEDWINDOW,
55
0, 0,
56
SCREEN_WIDTH, SCREEN_HEIGHT,
57
NULL,
58
NULL,
59
hInstance,
60
NULL);
61
62
ShowWindow(hWnd, nCmdShow);
63
64
// set up and initialize Direct3D
65
initD3D(hWnd);
66
67
// enter the main loop:
68
69
MSG msg;
70
71
while(TRUE)
72
{
73
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
74
{
75
TranslateMessage(&msg);
76
DispatchMessage(&msg);
77
}
78
79
if(msg.message == WM_QUIT)
80
break;
81
82
render_frame();
83
}
84
85
// clean up DirectX and COM
86
cleanD3D();
87
88
return msg.wParam;
89
}
90
91
92
// this is the main message handler for the program
93
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
94

{
95
switch(message)
96
{
97
case WM_DESTROY:
98
{
99
PostQuitMessage(0);
100
return 0;
101
} break;
102
}
103
104
return DefWindowProc (hWnd, message, wParam, lParam);
105
}
106
107
108
// this function initializes and prepares Direct3D for use
109
void initD3D(HWND hWnd)
110

{
111
d3d = Direct3DCreate9(D3D_SDK_VERSION);
112
113
D3DPRESENT_PARAMETERS d3dpp;
114
115
ZeroMemory(&d3dpp, sizeof(d3dpp));
116
d3dpp.Windowed = TRUE;
117
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
118
d3dpp.hDeviceWindow = hWnd;
119
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
120
d3dpp.BackBufferWidth = SCREEN_WIDTH;
121
d3dpp.BackBufferHeight = SCREEN_HEIGHT;
122
123
// create a device class using this information and the info from the d3dpp stuct
124
d3d->CreateDevice(D3DADAPTER_DEFAULT,
125
D3DDEVTYPE_HAL,
126
hWnd,
127
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
128
&d3dpp,
129
&d3ddev);
130
131
init_graphics(); // call the function to initialize the triangle
132
}
133
134
135
// this is the function used to render a single frame
136
void render_frame(void)
137

{
138
d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
139
140
d3ddev->BeginScene();
141
142
// select which vertex format we are using
143
d3ddev->SetFVF(CUSTOMFVF);
144
145
// select the vertex buffer to display
146
d3ddev->SetStreamSource(0, v_buffer, 0, sizeof(CUSTOMVERTEX));
147
148
// copy the vertex buffer to the back buffer
149
d3ddev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);
150
151
d3ddev->EndScene();
152
153
d3ddev->Present(NULL, NULL, NULL, NULL);
154
}
155
156
157
// this is the function that cleans up Direct3D and COM
158
void cleanD3D(void)
159

{
160
v_buffer->Release(); // close and release the vertex buffer
161
d3ddev->Release(); // close and release the 3D device
162
d3d->Release(); // close and release Direct3D
163
}
164
165
166
// this is the function that puts the 3D models into video RAM
167
void init_graphics(void)
168

{
169
// create the vertices using the CUSTOMVERTEX struct
170
CUSTOMVERTEX vertices[] =
171
{
172
{ 400.0f, 62.5f, 0.5f, 1.0f, D3DCOLOR_XRGB(0, 0, 255), },
173
{ 650.0f, 500.0f, 0.5f, 1.0f, D3DCOLOR_XRGB(0, 255, 0), },
174
{ 150.0f, 500.0f, 0.5f, 1.0f, D3DCOLOR_XRGB(255, 0, 0), },
175
};
176
177
// create a vertex buffer interface called v_buffer
178
d3ddev->CreateVertexBuffer(3*sizeof(CUSTOMVERTEX),
179
0,
180
CUSTOMFVF,
181
D3DPOOL_MANAGED,
182
&v_buffer,
183
NULL);
184
185
VOID* pVoid; // a void pointer
186
187
// lock v_buffer and load the vertices into it
188
v_buffer->Lock(0, 0, (void**)&pVoid, 0);
189
memcpy(pVoid, vertices, sizeof(vertices));
190
v_buffer->Unlock();
191
}
192

來吧,更新您的程序,讓我們看看我們得到的。如果你運行這個,你應該在屏幕上看到以下內容:
如果你看到這樣的三角,那么恭喜你!你成功了。當然,后面還有更多,在開始下一課之前我建議你試著做做下面的小練習,更可讓你更熟悉程序。
1。改變三角形的顏色。
2。在程序運行時改變三角的形狀。
3。將一個點的顏色褪色成另一個點的顏色。
當然,你可能會失望地發(fā)現,這一個三角形算哪門子三維???讓我們繼續(xù)下一課的學習,并使其通過旋轉,調整大小和移動讓你感覺到它確確實實在三維空間中。
下一課:轉變頂點
Translate By 王大寶(OneDouble.net)
posted on 2011-02-24 00:46
叫我老王吧 閱讀(3904)
評論(4) 編輯 收藏 引用 所屬分類:
DierectX