2016-10-06 45 views
0

我目前正在使用VAO(每個網格一個)的OpenGl 3.3應用程序。當我單獨創建並初始化我的VAO時,任何對glDrawElements的調用都會導致程序立即退出,而不會出現任何錯誤消息。但是,當我一起創建並初始化它們時,完全相同的glDrawElements調用會成功。爲什麼我無法單獨創建和初始化OpenGl VAO?


獨立初始化代碼:

Chunk::Chunk(){ 
    glGenVertexArrays(1, &m_vaoId); 
    glBindVertexArray(m_vaoId); 

    glGenBuffers(1, &m_vboId); 
    glGenBuffers(1, &m_eboId); 

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), (GLvoid*)(0)); 
    glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), (GLvoid*)(1*sizeof(GLfloat))); 
    glEnableVertexAttribArray(0); 
    glEnableVertexAttribArray(1); 
} 


void Chunk::refreshMesh(){ 
    /*build data into vector<GLfloat> verticies and vector<GLuint> indices...*/ 

    //send data to GPU 
    glBindVertexArray(m_vaoId); 

    glBindBuffer(GL_ARRAY_BUFFER, m_vboId); 
    glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(GLfloat), vertices.data(), GL_STATIC_DRAW); 

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_eboId); 
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(GLfloat), indices.data(), GL_STATIC_DRAW); 
} 

編譯初始化代碼:

void Chunk::refreshMesh(){ 
    /*build data into vector<GLfloat> verticies and vector<GLuint> indices...*/ 

    //send data to GPU 
    glGenVertexArrays(1, &m_vaoId); 
    glBindVertexArray(m_vaoId); 

    glGenBuffers(1, &m_vboId); 
    glBindBuffer(GL_ARRAY_BUFFER, m_vboId); 
    glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(GLfloat), vertices.data(), GL_STATIC_DRAW); 

    glGenBuffers(1, &m_eboId); 
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_eboId); 
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(GLfloat), indices.data(), GL_STATIC_DRAW); 

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), (GLvoid*)(0)); 
    glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), (GLvoid*)(1*sizeof(GLfloat))); 
    glEnableVertexAttribArray(0); 
    glEnableVertexAttribArray(1); 
} 

注:我使用Ubuntu 16.04 LTS編譯g ++ 5.4.0 20160609(Ubuntu 5.4.0-6ubuntu1〜16.04.2),glew 1.13和SDL2 2.0.0。我想做單獨的初始化,以允許定期更新網格數據而不創建新的VAO等,因爲我想可以在任何真實的GPU上處理有限數量的這些數據。

+1

'glVertexAttribPointer'使用當前綁定的緩衝區來設置attrib指針,因此您需要在調用'glVertexAttribPointer'之前綁定緩衝區。 – tkausl

+0

@tkausl謝謝,這是有效的。也許把它作爲答案是有道理的,以便我可以接受它? – john01dav

回答

4

在發明VAO之前,(幾乎)所有內容都保存在全局OpenGL狀態中。這與VAO略有改變,因爲他們有自己的國家。

您正在使用glVertexAttribPointer來設置指向緩衝區中屬性的指針,但是,VAO狀態不僅包含您傳遞給函數的值,還包含它們指向的緩衝區,它是綁定的緩衝區當您調用該函數時調用GL_ARRAY_BUFFER。這允許像這樣(僞代碼):

glBindBuffer(GL_ARRAY_BUFFER, a); 
glVertexAttribPointer(...); 
glBindBuffer(GL_ARRAY_BUFFER, b); 
glVertexAttribPointer(...); 

與此,你會使用來自兩個不同的緩衝區的屬性。然後,您可以解除綁定緩衝區並忘記*關於它們,您不需要綁定它們進行繪製。

TLDR:要解決您的問題,您需要將打算使用的緩衝區綁定到GL_ARRAY_BUFFER,然後再致電glVertexAttribPointer。因爲VAO 不是使用當前綁定的緩衝區陣列緩衝區用於繪製,但是在設置屬性指針時綁定的那個不需要綁定緩衝區。

*:要更改或刪除它們,您顯然仍然需要它們的名稱,因此請勿嚴格意義上的「忘記」它們。

+2

即使在創建VAO之後,也存在隱式的全局頂點狀態。在支持VAO的其他任何地方,它都是核心配置文件,可以想象有一個初始綁定的默認VAO(name = ** 0 **),就像存在紋理一樣;) –

相關問題