2012-08-06 107 views
80

我剛剛開始從本教程開始學習OpenGL:http://openglbook.com/the-book/
我到了第2章,繪製了一個三角形,並且我瞭解除了VAO之外的所有東西(這個縮寫是否可以?)。本教程有這樣的代碼:什麼是頂點數組對象?

glGenVertexArrays(1, &VaoId); 
glBindVertexArray(VaoId); 

雖然我明白代碼是必要的,但我不知道它幹了什麼。儘管我從未使用VaoId(除了銷燬它),但代碼在沒有它的情況下無法運行。我假設這是因爲它需要綁定,但我不知道爲什麼。這個確切的代碼是否需要成爲每個OpenGL程序的一部分?本教程將VAO解釋爲:

頂點數組對象(或VAO)是描述頂點屬性如何存儲在頂點緩衝對象(或VBO)中的對象。這意味着VAO不是存儲頂點數據的實際對象,而是頂點數據的描述符。頂點屬性可以用glVertexAttribPointer函數及其兩個姐妹函數glVertexAttribIPointer和glVertexAttribLPointer來描述,我們將在下面探討其中的第一個函數。

我不明白VAO如何描述頂點屬性。我沒有以任何方式描述它們。它是否從glVertexAttribpointer獲取信息?我想這一定是它。 VAO只是來自glVertexAttribPointer的信息的目的地嗎?

請注意,我接受的教程是否可以接受?有什麼我應該留意的或更好的教程要遵循嗎?

回答

77

「頂點數組對象」由OpenGL ARB小組委員會爲您提供。

將其視爲幾何對象。 (作爲舊時代的SGI Performer程序員,我稱他們爲geosets。)實例變量/對象的成員是你的頂點指針,普通指針,顏色指針,attrib N指針,...

當VAO是第一個請通過致電

glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer...; 
glEnableClientState(GL_NORMAL_ARRAY); glNormalPointer...; 

等指定這些成員。哪些屬性已啓用,並且您提供的指針存儲在VAO中。

之後,當您再次綁定VAO時,所有這些屬性和指針也變爲當前。所以一個glBindVertexArray調用相當於以前設置所有屬性所需的所有代碼。無需創建自己的結構或對象,便可在函數或方法之間傳遞幾何圖形。

(一次性設置,多次使用是使用VAOs最簡單的方法,但你也可以只通過結合,並做更多的啓用/指針調用更改屬性。VAOs不是常量)。

更多的信息迴應Patrick的問題:

新創建的VAO的默認值是空(AFAIK)。根本沒有幾何體,甚至沒有頂點,所以如果你試圖繪製它,你會得到一個OpenGL錯誤。這是相當理智的,如「將所有內容初始化爲False/NULL /零」。

當您設置時您只需要glEnableClientState。 VAO記住每個指針的啓用/禁用狀態。

是的VAO將存儲glEnableVertexAttribArrayglVertexAttrib。舊的頂點,正常,顏色,...數組與頂點==#0等屬性數組相同。

+41

''頂點數組對象'由OpenGL ARB小組委員會爲您提供。是的,一個存儲**頂點** **數組**綁定的**對象**這樣一個愚蠢的名字。 – 2012-08-06 01:34:26

+0

如果我正確地理解你,調用'glGenVertexArrays(1,&VaoId);'和'glBindVertexArray(VaoId);'創建一個VAO,並使用理智的默認值將你從'glEnableClientState'中解救出來?或者我完全誤解了你?將來我會使用很多'glEnableClientState'嗎? – Patrick 2012-08-06 02:13:49

+2

此外,所有與「glVertexAttribPointer」相關的VAOs – Patrick 2012-08-06 02:16:19

8

頂點數組對象在文字處理程序等中類似於。一個很好的描述被發現here

宏剛記得你做的動作,如激活該屬性,綁定該緩衝區,等當你調用glBindVertexArray(yourVAOId),它只是重播這些屬性指針綁定和綁定緩衝。

所以你下一次抽獎就會使用任何被VAO綁定的內容。

VAO的不存儲頂點數據。不可以。頂點數據存儲在頂點緩衝區中或存儲在客戶端存儲器陣列中。

+12

-1:它們不像宏。如果是,則綁定新的VAO不會禁用先前VAO啓用的頂點陣列,除非新的VAO已經「明確」記錄*禁用這些陣列。 VAO與* all * OpenGL對象一樣,保存* state *,而不是命令。命令只是改變*狀態,但對象以默認狀態設置。這就是爲什麼綁定新創建的VAO將總是禁用所有屬性。 – 2013-07-23 22:14:45

4

VAO是一個對象,表示OpenGL流水線的頂點提取階段,用於向頂點着色器提供輸入。

您可以創建這樣

GLuint vao; 
glCreateVertexArrays(1, &vao); 
glBindVertexArray(vao); 

首先,讓我們的頂點數組對象」做了一個簡單的例子。在着色器代碼

layout (location = 0) in vec4 offset; // input vertex attribute 

爲了填補這個屬性考慮這樣的輸入參數,我們可以使用

glVertexAttrib4fv(0, attrib); // updates the value of input attribute 0 

雖然頂點數組對象存儲這些靜態的屬性值 你,它可以做很多更多。

創建頂點數組對象後,我們可以開始填充其狀態。我們將要求OpenGL使用存儲在我們提供的緩衝區對象中的數據自動填充它。每個頂點屬性都可以從綁定到幾個頂點緩衝區綁定之一的緩衝區中獲取數據。爲此,我們使用glVertexArrayAttribBinding(GLuint vao, GLuint attribindex, GLuint bindingindex)。我們還使用glVertexArrayVertexBuffer()函數將緩衝區綁定到其中一個頂點緩衝區綁定。我們使用glVertexArrayAttribFormat()函數來描述數據的佈局和格式,最後我們通過調用glEnableVertexAttribArray()來啓用屬性的自動填充。

啓用頂點屬性,OpenGL的將反饋數據,根據您所提供 glVertexArrayVertexBuffer()glVertexArrayAttribFormat()格式和位置信息的頂點着色器。當 該屬性被禁用時,頂點着色器將被提供您提供的調用glVertexAttrib*()的靜態信息。

// First, bind a vertex buffer to the VAO 
glVertexArrayVertexBuffer(vao, 0, buffer, 0, sizeof(vmath::vec4)); 

// Now, describe the data to OpenGL, tell it where it is, and turn on automatic 
// vertex fetching for the specified attribute 
glVertexArrayAttribFormat(vao, 0, 4, GL_FLOAT, GL_FALSE, 0); 

glEnableVertexArrayAttrib(vao, 0); 

和代碼在着色器

layout (location = 0) in vec4 position; 

所有你需要打電話glDeleteVertexArrays(1, &vao)後。


您可以閱讀OpenGL SuperBible以更好地理解它。

+2

很高興看到有人推廣使用DSA風格的OpenGL。 – 2016-01-10 21:53:04