這是VAO的正確用法嗎?
否。
glVertexAttribPointer
uses the buffer object that was bound to GL_ARRAY_BUFFER
at the moment the function was called。所以,你不能做到這一點:
glVertexAttribPointer(...);
glBindBuffer(GL_ARRAY_BUFFER, bufferObject);
glDrawArrays(...);
這將不使用bufferObject
;當最初調用glVertexAttribPointer
時,它將使用與GL_ARRAY_BUFFER
綁定的任何內容。
VAO捕獲此狀態。因此,VAO將針對每個頂點屬性存儲被調用時綁定到GL_ARRAY_BUFFER
的任何緩衝區對象。這允許你做這樣的事情:
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, buffer1);
glVertexAttribPointer(0, ...);
glVertexAttribPointer(1, ...);
glBindBuffer(GL_ARRAY_BUFFER, buffer2);
glVertexAttribPointer(2, ...);
屬性0和1將來自buffer1
和屬性2將來自buffer2
。 VAO現在可以捕獲所有狀態。要渲染,你只是這樣做:
glBindVertexArray(VAO);
glDraw*();
總之,如果你想要更改屬性的存儲來自於OpenGL,則還必須更改它的格式。即使格式相同,您也必須再次撥打glVertexAttribPointer
。
:此討論假定您使用新ARB_vertex_attrib_binding是不。或者,正如其他人所知,「Exactly how Direct3D does vertex attribute binding.」如果您恰好使用提供此擴展的實現,則可以有效地執行您正在討論的內容,因爲屬性格式不與緩衝對象的存儲綁定。另外,glVertexAttribPointer
的折磨邏輯消失了。
一般來說,我們在OpenGL世界中解決這個問題的方法是將盡可能多的東西放在同一個緩衝區對象中。如果不這樣做,只需爲每個對象使用一個VAO。
感謝這個偉大的答案。那麼'glBufferData'步驟在哪裏起作用?在使用'glVertexAttribPointer'之前,你不必先緩衝數據嗎?對不起,我對OpenGL很陌生 –