我也知道我的文章并不是多么的不可或缺,沒了這個翻譯大家照樣過,目前為止基本都是些入門類的東西,有時候我會想到曾小賢的午夜節(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頂點格式代碼的。
讓我們來看看它如何做到這一點。比方說,我們希望包括位置和我們的頂點漫反射顏色。我們將建立一個代碼:

稍后,我們將簡單地使用CUSTOMFVF,而不是每次都輸出整個FVF代碼。我們將在一分鐘后來看這樣的一個例子。
我們可以在這個表達式里添加各種標識。以下是一組貫穿本套教程始終的標識表,以及他們做什么的說明。
標識 |
描述 |
參數類型 |
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 |
表示頂點格式包含任何將被應用到模型紋理坐標。 |
float, float |
|
|
當然了,還有更多的標識沒有被提及,它們已經是包含在DirectX文檔中了。而我們只需要本教程中使用到的這些標識。
創(chuàng)建頂點
現在我們需要使用我們的新格式創(chuàng)建頂點。我們不使用任何新函數或諸如此類的東西,我們通過建立一個簡單的結構體裝入FVF代碼中包含的變量。
例如,我們用在上面的例子用D3DFVF_XYZRHW和D3DFVF_DIFFUSE兩個標識一起的話,我們應該建立如下結構:







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



當然了,你也可以弄個頂點數組,就像這樣:














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








我們來逐個分析一下這些個參數
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。
值 |
描述 |
D3DPOOL_DEFAULT |
此標志表示該緩存應該創(chuàng)建在最適當的內存以便設置和資源可用。然而,強加一些限制并不總是對游戲有好處。 |
D3DPOOL_MANAGED |
這表明,緩沖將在位于顯存 |
D3DPOOL_SYSTEMMEM |
這表明,緩存將在系統(tǒng)內存中。頂點緩存設在這里通常不能由Direct3D設備訪問,但可以通過其他更高級的手段訪問。 |
D3DPOOL_SCRATCH |
這也表明了緩存將坐落在系統(tǒng)內存中,但是,又沒有辦法讓顯存訪問它。這種類型一般用于存儲圖像信息,現在我們用不到(但稍后將使用),比如屏幕已經轉到另一個地圖但角色暫時還沒有到達(不久后就到)。 |
|
LPDIRECT3DVERTEXBUFFER9 ppVertexBuffer,
如果你理解它,那我告訴你它是我們正在創(chuàng)建的頂點緩存的接口。我們給這個參數一個空指針,函數會給他賦值。
HANDLE* pSharedHandle
文檔里說過這個參數,我引述一下:“保留。設置這個參數為NULL。“我不能說肯定,但顯然微軟希望我們將其設置為NULL。就這樣吧。我們將它設置為NULL。
看完這些參數,讓我們來看看這個功能在我們的程序中如何寫:









現在您已經創(chuàng)建了頂點緩存,下面你需要把頂點加載進去。你用一個簡單的函數memcpy()就可以完成。但是,在您訪問到頂點緩存之前,你需要將其鎖定。
基于兩個原因,你需要鎖定這個緩存。首先,你需要告訴Direct3D你需要內存的完全控制權。換句話說,它不應該由任何可能的其他進程使用。第二,你需要告訴視頻硬件別動它。否則可沒法保證顯存保持不動。鎖定告訴顯存與內存當你正在使用它時別干蠢事兒。
要鎖定一個緩沖區(qū),可以使用函數Lock(),它有四個參數,但都相當簡單:




讓我們來看看這些參數:
UINT OffsetToLock, UINT SizeToLock,
如果我們只是想鎖定我們的頂點緩沖的一部分,我們將表明在這兩個參數。第一個指示自緩存的起始點到開始鎖定位置的偏移量,以字節(jié)為單位。第二個表示多少字節(jié)被鎖定。因為我們現在要鎖定整個緩沖區(qū),所以我們將設置這些都為0。
VOID** ppbData,
除非你是至少中等水平以上的C+ +,否則這個參數您老還是別動了。基本上這是一個void*指針并且沒有指向特定類型的變量。例如,一個**double,而一個int*指向一個int。每個指針類型都有它自己的格式,因此它不能轉換不會丟失數據為另一種類型。但是一個void *指針,卻可以轉換為任何類型。
在這里,我們有一個空指針*.這個指針被鎖定的存數去起始位置的指針。頂點緩沖區(qū)接口會處理其細節(jié),但我們在下一步會需要這個指針。所以函數lock()函數將填充恰當的地址給這個指針。有一個在下面的例子,看看我們如何填補這個參數。
DWORD Flags
這是一個很高級的參數,我們不會在本教程中深入。本上它提供特殊的方式來處鎖定內存。如果你是真正感興趣的,它們可以研究在DirectX文檔?,F在,我們只是將它設置為0。
讓我們來補完這個函數,看看它的樣子:



接下來,我們調用memcpy()復制頂點到頂點緩存。

最后,我們還有一個非常復雜的函數:Unlock()。這個函數沒有參數。它所做的是告訴Direct3D,跟內存搞完了,解開束縛吧。寫起來像這樣:

由于我們剛剛得知命令的數量,我們要把我們自己創(chuàng)建的功能放進一個單獨的函數里init_graphics()。


































在這里,我建議您多讀幾次以確保你徹底明白了這一切。這是3D編程中一個相當關鍵的的部分,我們將在教程的休息時間使用和修改它。
繪制圖元
現在,我們實際上已經獲得屏幕上的內容!但在此發(fā)生之前我們有三個非常簡單的函數要認識一下。每一個被從Direct3D設備接口調用。讓我們來看看。
SetFVF()
這些函數的第一個是SetFVF()。 SetFVF()是一種告訴Direct3D使用當前使用什么樣的FVF代碼的函數。我們當然可以有多個FVF代碼并使用在兩個不同的三維場景。在我們開始畫之前,我們只需要告訴我們的Direct3D使用的是哪一個。這個函數寫出來是這樣的:

SetStreamSource()
下一步,我們的函數SetStreamSource(),它告訴Direct3D我們從哪個頂點緩沖取頂點。這其中有一對參數,讓我們來看看函數原型:





第一個參數是要用的頂點緩存的序號。我們稍后深入它的工作原理,但現在將它設置為0,因為我們只有一個頂點緩沖區(qū)。
第二個參數是指向我們先前創(chuàng)建的頂點緩存的指針。
第三個參數指應該從頂點緩沖的第幾個字節(jié)開始。這通常是0。
最后一個參數是每個頂點的大小。我們填寫如下: SizeOf(CUSTOMVERTEX)。
讓我們來看看在函數怎樣被調用:

DrawPrimitive()
現在我們已經告訴Direct3D我們正在使用哪種格式的頂點以及哪里得到它們,我們告訴它請繪制我們已經建立的頂點。這個函數繪制在選定的頂點緩存的圖元到屏幕上。這里是函數原型:



第一個參數是使用的圖元類型。這些在第3課已經講過了,但所用的代碼在這里:
[Table 4.3 - D3DPRIMITIVETYPE Values]
Value |
Description |
D3DPT_POINTLIST |
點陣 |
D3DPT_LINELIST |
線列表 |
D3DPT_LINESTRIP |
線帶 |
D3DPT_TRIANGLELIST |
三角形列表 |
D3DPT_TRIANGLESTRIP |
三角形帶 |
D3DPT_TRIANGLEFAN |
三角扇形 |
|
第二個參數是我們要繪制在屏幕上的第一個頂點的序號。如果我們愿意,我們可以在頂點緩沖區(qū)的中間開始。但是,現在我們希望繪制整個緩沖區(qū),因此我們將在這里把0。
第三個也是最后一個參數是我們要繪制圖元的數量。如果我們要畫一個三角形,我們設1(只有一個三角形)。如果我們畫點,我們會設為3,有三點。畫線條也是設為3。
現在讓我們來看看整個render_frame()函數,現在我們已經修改了它。






















在看整個程序之前,先來看看最后一個步驟是很有必要的。
釋放頂點緩存
就像Direct3D設備和Direct3D一樣,頂點緩沖區(qū)也必須在程序關閉之前被釋放。









現在讓我們來看看整個程序,看看我們都干了什么。
最終代碼
好吧,讓我們來看看這個三角長啥樣。如果你從來沒有見過三角形,這將是一個教育的經驗。否則你可以看到一個三角形是made in Direct3D。
無論如何,讓我們來看看最后的DirectX代碼。在本課程中所涵蓋的新的部分像往常是加粗的。

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24



25

26

27

28

29

30

31

32

33

34

35

36



37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72



73

74



75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94



95

96



97

98



99

100

101

102

103

104

105

106

107

108

109

110



111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137



138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159



160

161

162

163

164

165

166

167

168



169

170

171



172



173



174



175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

來吧,更新您的程序,讓我們看看我們得到的。如果你運行這個,你應該在屏幕上看到以下內容:
如果你看到這樣的三角,那么恭喜你!你成功了。當然,后面還有更多,在開始下一課之前我建議你試著做做下面的小練習,更可讓你更熟悉程序。
1。改變三角形的顏色。
2。在程序運行時改變三角的形狀。
3。將一個點的顏色褪色成另一個點的顏色。
當然,你可能會失望地發(fā)現,這一個三角形算哪門子三維?。孔屛覀兝^續(xù)下一課的學習,并使其通過旋轉,調整大小和移動讓你感覺到它確確實實在三維空間中。
下一課:轉變頂點
英文原文:http://www.directxtutorial.com/tutorial9/b-direct3dbasics/dx9B4.aspx
Translate By 王大寶(OneDouble.net)