頂點屬性與頂點格式 頂點緩衝

2021-06-07 14:06:11 字數 4870 閱讀 6291

頂點屬性與頂點格式

頂點可謂是3d世界中的基本元素。在計算機所能描繪的3d世界中,任何物體都是由多邊形構成的,可以是三邊形,也可以是四邊形等。由於三邊形,即三角形所具有的特殊性質決定其在3d世界中得到廣泛的使用。構成三角形需要三個點,這些點的性質就是這章所要講的內容。

也許你已經知道頂點的結構定義,你可能會奇怪為什麼d3d會知道我們「隨便」定義的那些結構呢?其實那些頂點的定義可不是那麼隨便的哦。下面列舉在direct3d中,頂點所具有的所有屬性。

(1)位置:頂點的位置,可以分別指定x,y,x三個值,也可以使用d3dxvector3結構來定義。

(2)rhw:齊次座標w的倒數。如果頂點為變換頂點的話,就要有這個值。設定這個值意味著你所定義的頂點將不需要direct3d的輔助(不能作變換、旋轉、放大縮小、光照等),要求你自己對頂點資料進行處理。至於w是什麼,w和xyz一樣,只是乙個四元組的一部分。rhw的英文是reciprocal of the homogenous w,即1/w,它是為了處理矩陣的工作變得容易一些(呼,線性代數的東東快都忘了,要惡補一下才行)。一般設rhw的值為1.0。

(3)混合加權:用於矩陣混合。高階應用,這裡不講了(其實我不會,^_^)

(4)頂點法線:學過高等數學就應該知道法線是什麼吧?在這裡是指經過頂點且和由頂點引出的邊相垂直的線,即和三角形那個面垂直。用三個分量來描述它的方向,這個屬性用於光照計算。

(5)頂點大小:設定頂點的大小,這樣頂點就可以不用只佔乙個畫素了。

(6)漫反射色:即光線照射到物體上產生反射的著色。理解這個比較麻煩,因為3d光照和真實光照沒什麼關係,不能像理解真實光照那樣去理解3d光照。

(7)鏡面反射色:它可以讓乙個3d物體的表面看起來很光滑。

(8)紋理座標:如果想要在那些用多邊形組成的物體上面貼上紋理,就要使用紋理座標。由於紋理都是二維的,所以用兩個值就可以表示紋理上面某一點的位置。在紋理座標中,只能在0.0到1.0之間取值。例如(0.0 , 0.0)表示紋理的左上角,(1.0 , 1.0)表示紋理的右下角。

好了,請記住上面屬性的順序。我們定義乙個頂點結構的時候,不一定要包括全部的屬性,但是一定要按照上面的順序來定義。例如:

struct myvertex

上面定義了乙個有漫反射色的變換頂點。

定義完了頂點的結構後,我們就要告訴d3d我們定義的是什麼格式。為了方便,我們通常會用#define來定義乙個叫做描述「靈活頂點格式」(fvf:flexible vertex format)的巨集。例如:#define myfvf d3dfvf_xyz | d3dfvf_normal。根據之前定義的頂點屬性結構體,我們要定義相對應的巨集。假如頂點結構中有位置屬性,那麼就要使用d3dfvf_xyz;如果是變換頂點的話,就要使用d3dfvf_xyzrhw;如果使用了漫反射色屬性的話,就要使用d3dfvf_diffuse。這些值是可以組合使用的,像上面那樣用「|」符號作為鏈結符。定義完靈活頂點格式後,使用idirect3ddevice9::setfvf函式來告訴d3d我們所定義的頂點格式,例如:g_pd3ddevice->setfvf( myfvf );

頂點緩衝

處理頂點資訊的地方有兩個,乙個是在陣列裡,另乙個是在d3d所定義的頂點緩衝裡。換個說法的話就是乙個在我們所能直接操作的記憶體裡,另乙個在d3d管理的記憶體裡。對於我們這些對作業系統底層了解不多的菜鳥來說,直接操作記憶體實在是太恐怖了,所以還是交給d3d幫我們處理吧,雖然不知道背後有些什麼操作。要想把頂點資訊交給d3d處理,我們就要先建立乙個頂點緩衝區,可以使用idirect3ddevice9->createvertexbuffer,它的原型是:

hresult createvertexbuffer(

uint length,

dword usage,

dword fvf,

d3dpool pool,

idirect3dvertexbuffer9** ppvertexbuffer,

handle* psharedhandle

);

length:緩衝區的長度。通常是頂點數目乘以頂點大小,使用sizeof( myvertex )就可以知道頂點的大小了。

usage:高階應用。設為0就可以了。

fvf:就是我們之前定義的靈活頂點格式。

pool:告訴d3d將頂點緩衝儲存在記憶體中的哪個位置。高階應用,通常可取的三個值是:d3dpool_default,d3dpool_managed,d3dpool_systemmem。多數情況下使用d3dpool_default就可以了。

ppvertexbuffer:返回來的指向idirect3dvertexbuffer9的指標。之後對頂點緩衝進行的操作就是通過這個指標啦。到這裡還要再提醒一下,對於這些介面指標,在使用完畢後,一定要使用release來釋放它。

psharedhandle:設為null就行了。

得到乙個指向idirect3dvertexbuffer9的指標後,頂點緩衝也就建立完畢了。現在要做的就是把之前儲存在陣列中的頂點資訊放在頂點緩衝區裡面。首先,使用idirect3dvertexbuffer9::lock來鎖定頂點緩衝區:

hresult lock(

uint offsettolock,

uint sizetolock,

void **ppbdata,

dword flags

);

offsettolock:指定要開始鎖定的緩衝區的位置。通常在起始位置0開始鎖定。

sizetolock:指定在鎖定的緩衝區的大小。設為0的話就是表示要鎖定整個緩衝區。

ppbdata:用來儲存返回的指向頂點緩衝區的指標。通過這個指標來向頂點緩衝區填充資料。

flags:高階應用。通常設為0。

填充為頂點緩衝區後,使用idirect3ddevice9::unlock來解鎖。

最後在渲染的時候使用idirect3ddevice9::setstreamsource來告訴d3d要渲染哪個頂點緩衝區裡面的頂點。

hresult setstreamsource(

uint streamnumber,

idirect3dvertexbuffer9 *pstreamdata,

uint offsetinbytes,

uint stride

);

streamnumber:設定資料流的數量。頂點緩衝最多可以使用16個資料流。確定所支援的資料流的數量,可以檢查d3dcaps中的maxstreams成員的值。通常設為0,表示使用單資料流。

pstreamdata:要與資料流繫結的資料。在這裡我們要把頂點緩衝區與資料流繫結。

offsetinbytes:設定從哪個位置開始讀資料。設為0表示從頭讀起。

stride:資料流裡面資料單元的大小。在這裡是每個頂點的大小。

索引緩衝

很多時候,相鄰的三角形會共用一些頂點,例如組成四方形的兩個三角形就共用了一條邊,即共用了兩個頂點資訊。如果不使用索引,我們需要六個頂點的資訊來繪製這個四方形,但實際上繪製乙個四方形只要四個頂點資訊就足夠了。如果使用了索引就不一樣了,在頂點緩衝區裡我們可以只儲存四個頂點的資訊,然後通過索引來讀取頂點資訊。要使用索引得先建立乙個索引緩衝。也許讀到這裡你會有個疑問,建立乙個索引緩衝不就更浪費記憶體空間了嗎?其實不然,索引緩衝區的元素儲存的是數字,乙個數字所占用的記憶體肯定要比乙個頂點所占用的小得多啦。當你節省了幾千個頂點,你就會發現浪費那麼一點點索引緩衝區是很值得的。

建立索引緩衝的函式是:idirect3ddevice9::createindexbuffer

hresult createindexbuffer(

uint length,

dword usage,

d3dformat format,

d3dpool pool,

idirect3dindexbuffer9** ppindexbuffer

);

length:索引緩衝區的長度。通常使用索引數目乘以sizeof(word)或sizeof(dword)來設定,因為索引號的資料型別是位元組(word)或雙位元組(dword),嗯,乙個word只有兩個位元組,dword也就只有四個位元組,比頂點的大小小多了吧。

usage:和createvertexbuffer中的usage設定一樣。一般設為0。

format:設定索引格式。不是d3dfmt_index16就是d3dfmt_index32的啦。

pool:又是和createvertexbuffer中的一樣。一般設為d3dpool_default。

ppindexbuffer:指向idirect3dindexbuffer9的指標。操作索引緩衝區就靠它的啦。記得使用完後要release啊。

和填充頂點緩衝區一樣,要填充索引緩衝區,要先使用idirect3dindexbuffer9::lock來鎖定緩衝區。

hresult lock(

uint offsettolock,

uint sizetolock,

void **ppbdata,

dword flags

);

是不是和idirect3dvertexbuffer9::lock一樣呢?具體說明也可以參照上面的內容。填充完之後使用idirect3dindexbuffer9::unlock來解鎖。

最後使用idirect3ddevice9::setindices來告訴裝置要使用哪個索引。

hresult setindices(

idirect3dindexbuffer9* pindexdata,

uint basevertexindex

);

pindexdata:設定使用哪個索引緩衝。

basevertexindex:設定以頂點緩衝區中的哪個頂點為索引0。

有關頂點的知識就說到這了。一下章說說點、線、三角形這種d3d所支援的圖元(drawing primitives)。

自動計算頂點緩衝中所有頂點的法線

問題 當繪製自定義的結構時,你會發現光照不正確。這是因為你沒有指定正確的法線向量,顯示卡要求每個頂點都有法線資訊,這樣它才可以決定每個三角形獲得多少光照,詳細資訊可見第六章。為每個頂點計算法線向量看起來很複雜,因為大多數頂點被多個三角形共享。如果每個頂點只被乙個三角形使用,你只需找到三角形的法線向量...

自動計算頂點緩衝中所有頂點的法線

當繪製自定義的結構時,你會發現光照不正確。這是因為你沒有指定正確的法線向量,顯示卡要求每個頂點都有法線資訊,這樣它才可以決定每個三角形獲得多少光照,詳細資訊可見第六章。為每個頂點計算法線向量看起來很複雜,因為大多數頂點被多個三角形共享。如果每個頂點只被乙個三角形使用,你只需找到三角形的法線向量 換句...

shader 頂點顏色屬性

1.頂點除了包含位置資訊之外增加顏色屬性 2.取頂點屬性資料 步長 以及偏移量 3.上面的0 1 對應shader中的location glewexperimental gl true 使用有問題 注釋掉if glewinit glew ok glviewport 0 0,800 600 glpol...