2016-10-09 3 views
0

Ich lerne OpenGL derzeit und versuche, die Beziehung zwischen einem VBO und einem VAO zu verstehen.VAO nicht aktualisiert, wenn glBindVertexArray

Soweit ich weiß, ist ein VBO ein Puffer von Daten und das ist alles. Um diese Daten in die OpenGL-Pipeline zu übertragen, muss ich diese VBO-Daten an einen VAO binden.

Dies kann über die Fülle von glVertexAttrib* Funktionen erreicht werden. Alternativ können Sie den VAO so einstellen, dass er automatisch Daten von einem VBO über eine Reihe von glVertexArray* Funktionen hochlädt und mit einem Anruf bei glEnableVertexArrayAttrib endet. Jetzt, wenn ich die Daten in einigen VBO ändern, alles, was ich tun muss, ist auf meinem VAO glBindVertexArray aufrufen, um die Daten von der VBO auf den VAO hochzuladen.

Richtig?

Zumindest verstehe ich so, was passiert. Aber wenn ich versuche, es im Code zu simulieren, sehe ich nicht das erwartete Ergebnis (ein Dreieck, das sich um den Bildschirm herum dreht).

Hier ist mein Code der VAO und VBO für die Erstellung von:

void startup() 
{ 
    static const GLfloat positions[] = 
    { 
     1.00f, -0.25f, 0.0f, 1.0f, 
     1.00f, -0.25f, 0.0f, 1.0f , 
     1.00f, -0.25f, 0.0f, 1.0f 
    }; 


    m_renderingProgram = compile_shaders(); 

    //Create VAO and VBO 
    glCreateVertexArrays(1, &m_VAO); 
    glCreateBuffers(1, &m_VBO); 


    //Set the VAO to automatically update it's data with VBO when it is bound 
    glNamedBufferStorage(m_VBO, sizeof(positions), positions, 0); 
    glVertexArrayVertexBuffer(m_VAO, 0, m_VBO, 0, 4); 
    glVertexArrayAttribFormat(m_VAO, 0, 3, GL_FLOAT, GL_FALSE, 0); 
    glVertexArrayAttribBinding(m_VAO, 0, 0); 
    glEnableVertexArrayAttrib(m_VAO, 0); 


    //Create a named buffer, so we can change the data within easily 
    glNamedBufferData(m_VBO, sizeof(positions), positions, GL_MAP_WRITE_BIT); 

    //Upload the data to the VAO 
    glBindVertexArray(m_VAO); 
} 

Und das ist mein Update (Funktionscode):

void render(double currentTime) 
{ 
    const GLfloat red[] = { (float)sin(currentTime) * 0.5f + 0.5f, 
            (float)cos(currentTime) * 0.5f + 0.5f, 
            (float)sin(currentTime) * 0.5f + 0.5f, 
          1.0f }; 


    const GLfloat newPosition[] = 
    { 
     sin(currentTime) * 1.00, sin(currentTime) * -0.25, 0.0, 1.0, 
     tan(currentTime) * 1.00, tan(currentTime) * -0.25, 0.0, 1.0 , 
     cos(currentTime) * 1.00, cos(currentTime) * -0.25, 0.0, 1.0 
    }; 


    const GLfloat black[] = { 0.0f, 0.0f, 0.0f, 1.0f }; 
    glViewport(sin(currentTime) * 0.4f, cos(currentTime) * 0.5f, 800, 600); 

    glClearBufferfv(GL_COLOR, 0, black); 
    //Copy the new position to the buffer 
    glNamedBufferSubData(m_VBO, 0, sizeof(newPosition), newPosition); 


    //Use the shader program program 
    glUseProgram(m_renderingProgram); 


    glVertexAttrib4fv(1, red); 
    //Update the VAO with the updated VBO 
    glBindVertexArray(m_VAO); 


    glDrawArrays(GL_TRIANGLES, 0, 3); 
} 

Was ich erwarte, ist ein Dreieck um das Morphing zu sehen Bildschirm und wechselnde Farben, aber alles, was ich sehe, ist ein statisches Dreieck, das die Farben ändert.

+0

Ja, darüber spreche ich. Keine Ahnung, warum ich VBA geschrieben habe, aber es ist sogar überall in meinem Code. – Acorn

Antwort

2

Soweit ich weiß, ein VBO ist ein Puffer von Daten und das ist alles.

Ein buffer object ist ein Puffer von Daten. Der Begriff "VBO" bezieht sich auf ein Pufferobjekt, das (derzeit) als Quelle für Vertex-Attribute verwendet wird. Buffer objects can be used for many other things, und Sie können den gleichen Puffer auf verschiedene Arten verwenden.

Um diese Daten in die OpenGL-Pipeline zu übertragen, muss ich diese VBO-Daten an einen VAO binden.

Der Fachbegriff ist das Pufferobjekt an einen VAO "anhängen". Sie "verbinden" ein Objekt mit einem anderen; Sie "binden" ein Objekt an den Kontext.

Jetzt, da wir unsere Terminologie ausgearbeitet haben, sprechen wir darüber, wo Ihr Code schief geht.

//Create a named buffer, so we can change the data within easily 
glNamedBufferData(m_VBO, sizeof(positions), positions, GL_MAP_WRITE_BIT); 

Sie können das nicht tun. Sie haben mit bereits einen Speicher für dieses Pufferobjekt erstellt. Noch wichtiger, Sie haben unveränderlichen Speicher dafür geschaffen. Dies bedeutet, dass Sie nach dem Erstellen von unveränderbarem Speicher für ein Pufferobjekt nicht mehr zurückgehen und neuen Speicher erstellen können.

Was ist in Ordnung; in der Tat ist diese Zeile völlig überflüssig, da Sie den Speicher bereits erstellt und auf ihn hochgeladen haben. Entfernen Sie einfach diese redundante Leitung.

//Copy the new position to the buffer 
glNamedBufferSubData(m_VBO, 0, sizeof(newPosition), newPosition); 

Dies ist, wo wir in ernstere Probleme beginnen zu bekommen.

See, erstellt Sie den Speicher-Puffer wie folgt aus:

glNamedBufferStorage(m_VBO, sizeof(positions), positions, 0); 

Das 0 gibt es das Flags-Feld; es spezifiziert the ways in which you can modify the contents of the storage from the CPU (unter anderem). Das bedeutet, unveränderlicher Speicher bedeutet nicht, dass Sie nicht wieder hinein kopieren können. Es bedeutet einfach, dass Sie den Speicher nicht neu zuordnen können.

Sie haben jedoch 0 übergeben. Das bedeutet, dass der von Ihnen erstellte Puffer vollständig statisch ist. Sie haben OpenGL gesagt, dass Sie nicht möchten den Inhalt des Puffers über CPU-Prozesse ändern. Was für einen statischen Puffer in Ordnung ist, aber das ist eindeutig nicht das, was Sie wollten.

Also statt 0, sollten Sie eine entsprechende Flagge übergeben haben. Das Flag, das glNamedBufferSubData zulässt, heißt GL_DYNAMIC_STORAGE_BIT.

+0

Super! Ich vermute, wenn ich GL_MAP_WRITE_BIT verwenden möchte, muss ich einen Zeiger auf die Daten über glMapNamedBuffer anfordern? – Acorn

+1

@Acorn: Es ist anders herum. Wenn Sie Ihren Datenspeicher mit 'GL_MAP_WRITE_BIT' erstellt haben, dürfen Sie den Puffer zum Schreiben mit' glMapNamedBuffer' abbilden - andernfalls schlägt das Mapping fehl. Das ist kein Unterschied zu dem mit 'glBufferData' erworbenen Speicher. Übrigens wirst du wahrscheinlich 'glMapNamedBufferRange' in Betracht ziehen - viele Zuordnungsoptionen sind nur auf diese Weise verfügbar. – thokra

Verwandte Themen