2016-10-06 4 views
0

Ich arbeite derzeit an einer OpenGl 3.3-Anwendung, die VAOs (eins pro Mesh) verwendet. Wenn ich meine VAOs separat erstelle und initialisiere, führt jeder Aufruf von glDrawElements dazu, dass das Programm sofort ohne Fehlermeldung beendet wird. Wenn ich sie jedoch zusammen erstelle und initialisiere, ist der gleiche glDrawElements Aufruf erfolgreich.Warum kann ich OpenGl VAO nicht separat erstellen und initialisieren?


Separate Initialisierung Code:

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); 
} 

Zusammengestellt Initialisierung Code:

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); 
} 

HINWEIS: Ich verwende Ubuntu 16.04 LTS, um mit g ++ 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1 ~ 16.04.2), glew 1.13 und SDL2 2.0.0 zu kompilieren. Ich möchte eine separate Initialisierung durchführen, um zu ermöglichen, dass die Maschendaten periodisch aktualisiert werden, ohne einen neuen VAO usw. zu erzeugen, da ich mir vorstelle, dass eine endliche Anzahl von diesen auf jeder realen GPU gehandhabt werden kann.

+1

'glVertexAttribPointer' verwendet den aktuell gebundenen Puffer, um die Attributzeiger zu setzen, daher müssen Sie den Puffer binden, bevor Sie' glVertexAttribPointer' aufrufen. – tkausl

+0

@tkausl Danke, das funktioniert. Vielleicht ist es sinnvoll, es als Antwort zu geben, damit ich es annehmen kann? – john01dav

Antwort

4

Bevor VAOs erfunden wurden, wurde (fast) alles im globalen OpenGL-Zustand gespeichert. Dies änderte sich bei VAO leicht, da sie ihren eigenen Zustand haben.

Sie verwenden glVertexAttribPointer, um die Zeiger auf Attribute in Puffern einzurichten. Der VAO-Status enthält jedoch nicht nur die Werte, die Sie an die Funktion übergeben, sondern auch den Puffer, auf den sie verweisen zu GL_ARRAY_BUFFER, wenn Sie die Funktion aufgerufen haben. Dies ermöglicht so etwas wie dieser (Pseudo-Code):

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

mit dieser, Sie Attribute aus zwei verschiedenen Puffern verwenden würden. Sie könnten dann die Puffer lösen und * über sie vergessen, Sie müssen sie nicht zum Zeichnen binden.

TLDR: Um Ihr Problem zu beheben, müssen Sie den zu verwendenden Puffer an GL_ARRAY_BUFFER binden, bevor Sie glVertexAttribPointer anrufen. Sie müssen den Puffer nicht jedes Mal zum Zeichnen binden, da VAO nicht den aktuell gebundenen Puffer-Array-Puffer für Zeichnung verwendet, sondern den, der gebunden wurde, als der Attributzeiger gesetzt wurde.

*: Um sie zu ändern oder zu löschen, brauchen Sie offensichtlich noch ihren Namen, also "vergessen" Sie sie nicht im strengen Sinne des Wortes.

+2

Auch nachdem VAOs erstellt wurden, gibt es implizit einen globalen Vertexstatus. Es sind Core-Profile, die diese Unterscheidung zeichnen. Wo auch immer VAOs unterstützt werden, können Sie sich vorstellen, dass ein Standard-VAO (Name = ** 0 **) anfänglich wie für Texturen gebunden ist;) –

Verwandte Themen