VAO和EBO解綁定的坑?
最近遇到了一個VAO和EBO的坑。
glBindVertexArray(VAO) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); ... glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);glBindVertexArray(0);
... glBindVertexArray(VAO); glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);//crash如上代碼所示,我在unbind VAO之前 unbind了EBO,然後在glDrawElements處就會出現crash,必須先unbind VAO再unbind EBO,上面代碼才能如期運行。但是我有一個疑問的是對於VBO,我在unbind VAO之前先unbind了VBO就不會出現crash,想請教大家為什麼會出現這樣的狀態,是VAO和EBO之間的坑嗎,還是我沒理解對?glBindVertexArray(VAO) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBindBuffer(GL_ARRAY_BUFFER, VBO); ... glBindBuffer(GL_ARRAY_BUFFER, 0);glBindVertexArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); ... glBindVertexArray(VAO); glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);//dont crash對於上述所說,我的理解是EBO是存在VAO裡面的,因此在unbind VAO之前unbind了EBO相當於VAO此時不在保存這個EBO了;而VBO不是保存在VAO之中的,因此不會出現這個問題。但是在unbind VAO之前unbind了VBO不相當於切斷了VAO和VBO之間的聯繫了嗎,為什麼後面draw call時VAO還能正確的讀到頂點數據?
著作權歸作者所有。
商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。作者:Vinjn張靜鏈接:如何正確理解 opengl 的 vao ? - Vinjn張靜的回答來源:知乎
VAO 記錄的是- vertex attribute 的格式,由 glVertexAttribPointer 設置。
- vertex attribute 對應的 VBO 的名字, 由一對 glBindBuffer 和 glVertexAttribPointer 設置。
- #當前#綁定的 GL_ELEMENT_ARRAY_BUFFER 的名字,由 glBindBuffer 設置。
VAO 中並不保存#當前#綁定的 GL_ARRAY_BUFFER,VBO 和 vertex attribute 的綁定是在 glVertexAttribPointer 中完成的。
完整信息參考 Vertex Specification如何正確理解 opengl 的 vao ? - Vinjn張靜的回答明明是你自己把index buffer綁成0的:
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindVertexArray(0);不要自己發明一個名字叫EBO,沒有這個詞。
再補充一點,index buffer和vao的關係,確實有坑。在intel卡上,index buffer不能放入vao,而nv/amd卡上可以。EBO是你自己取得名字么
至於為什麼是錯的
是因為 一個VAO 保存一組VertexAttributeState和一個ElementArrayBufferObject也就是一組頂點屬性和緩衝區的bind關係和一個索引數組你bindVAO的時候 unbind了索引數組
你那個VAO就沒有bind索引數組了你drawElements自然是錯的
具體理解 請看下面的一個偽實現代碼
struct VertexAttributeState
{
bool bIsEnabled = false;
int iSize = 4; //This is the number of elements in each attrib, 1-4.
unsigned int iStride = 0;
VertexAttribType eType = GL_FLOAT;
bool bIsNormalized = false;
bool bIsIntegral = false;
void * pPtrOrBufferObjectOffset = 0;
BufferObject * pBufferObj = 0;
};
struct VertexArrayObjectState
{
BufferObject *pElementArrayBufferObject = NULL;
VertexAttributeState attributes[MAX_VERTEX_ATTRIB];
}
static VertexArrayObjectState *pContextVAOState = new VertexArrayObjectState();
static BufferObject *pCurrentArrayBuffer = NULL;
void glBindBuffer(enum target, uint buffer)
{
BufferObject *pBuffer = ConvNameToBufferObj(buffer);
switch(target)
{
case GL_ARRAY_BUFFER:
pCurrentArrayBuffer = pBuffer;
break;
case GL_ELEMENT_ARRAY_BUFFER:
pContextVAOState-&>pElementArrayBufferObject = pBuffer;
break;
...
}
}
void glEnableVertexAttribArray(uint index)
{
pContextVAOState-&>attributes[index].bIsEnabled = true;
}
void glDisableVertexAttribArray(uint index)
{
pContextVAOState-&>attributes[index].bIsEnabled = false;
}
void glVertexAttribPointer(uint index, int size, enum type, boolean normalized, sizei stride, const void *pointer)
{
VertexAttributeState currAttrib = pContextVAOState-&>attributes[index];
currAttrib.iSize = size;
currAttrib.eType = type;
currAttrib.iStride = stride;
currAttrib.bIsNormalized = normalized;
currAttrib.bIsIntegral = true;
currAttrib.pPtrOrBufferObjectOffset = pointer;
currAttrib.pBufferObj = pCurrentArrayBuffer;
}
推薦閱讀:
※現代OpenGL是怎麼繪製曲面的?
※Shader 在現在圖形管線中可以負責多少部分?
※震驚!時間之神又給了這個古老的API+了0.1
※初學者學習opengl是用紅寶書好還是藍寶書好?
※3d引擎開發需要那些技能儲備?