Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 6 of 6

Thread: How to use multiple buffers (glGenBuffer/BindBuffer)

  1. #1
    Junior Member Newbie
    Join Date
    Jun 2012
    Location
    London, UK
    Posts
    15

    How to use multiple buffers (glGenBuffer/BindBuffer)

    Hello OpenGL experts,

    I am asking for some help to get multiple buffer objects working.

    I have an animated scene with mutliple ellipses & spheres, and it is starting to go slow if I keep sending all the vertices to OpenGL for each frame. So I want to re-use buffer data across scene objects since I have repeats of the same data & just a different model-view transform.

    The same shader is used throughout. The code works fine if I set (objectNotInCache) to always return TRUE, so the buffers get recreated each time round the loop. It also works fine if I only use one geometry & therefore keep retrieving the same one from my cache.

    I can't get this working with mutliple goemetries in the same scene. The minute I introduce a mix of geometries (i.e. use multiple buffers), I get garbage on screen - so obviously I am missing something in how to correctly set up and swap between buffers.

    Thanks in advance for any assistance. Can anyone advise what I am doing wrong?


    Code :
    [FONT=Courier New]=========
    Pseudocode
     
    Loadshader ()
     
    SetShaderUniforms(); 
     
    for (each object in scene)
    {
       SetShaderModelView(); 
     
       if (objectNotInCache)
       {
          glGenVertexArrays( 1, &vao );
          glBindVertexArray( vao );
     
          glGenBuffers (1, &bufferID)
          glBindBuffer (GL_ARRAY_BUFFER, bufferID);
     
          // Set up buffers for drawing facets. I know interleaved will be faster but want to get
          // a simpler buffer layout working first. 
          glBufferData( GL_ARRAY_BUFFER, 
                        vertexbuffersize + normalbuffersize,
                        NULL, GL_STATIC_DRAW );  
          glBufferSubData( GL_ARRAY_BUFFER, 
                           0, vertexBufferSize(), pVertices);
          glBufferSubData( GL_ARRAY_BUFFER, 
                           vertexbuffersize , normalbuffersize, pNormals); 
     
          // vPosition & vNormal are the shader variables for vertex position & normal
          // the positions are retrieved up where I load the shader. I know this is working bcs the
          // program works when I use a single buffer or use only one geometry and thus one buffer
          glEnableVertexAttribArray( vPosition );
          glEnableVertexAttribArray( vNormal );
     
          // set up the vertex arrays for drawing facets
          glVertexAttribPointer( vPosition, 4, GL_FLOAT, GL_FALSE, 0,
                                 BUFFER_OFFSET(0) );
          glVertexAttribPointer( vNormal, 3, GL_FLOAT, GL_FALSE, 0,
                                 BUFFER_OFFSET(vertexbuffersize) ); 
     
          cacheVaoAndBuffer (vao, bufferID);
       }
       else
       {
          getVaoAndBufferfromCache (&vao, &bufferID);
     
          glBindVertexArray( vao );
          glBindBuffer (GL_ARRAY_BUFFER, bufferID);
     
          // I supect I don't need the following 4 calls but ended up putting them in
          // a vain attempt to get some output. 
          glEnableVertexAttribArray( vPosition );
          glEnableVertexAttribArray( vNormal );
     
          glVertexAttribPointer( vPosition, 4, GL_FLOAT, GL_FALSE, 0,
                                 BUFFER_OFFSET(0) );
          glVertexAttribPointer( vNormal, 3, GL_FLOAT, GL_FALSE, 0,
                                 BUFFER_OFFSET(vertexbuffersize) );
     
       }
     
     
       glDrawArrays( GL_TRIANGLES, 0, vertexCount);
     
    }[/FONT]

  2. #2
    Super Moderator OpenGL Guru
    Join Date
    Feb 2000
    Location
    Montreal, Canada
    Posts
    4,264
    When you use VAO, you don't need to call bind the VBO, you don't need to enable the arrays and call glVertexAttribPointer. A VAO stores all those states.
    Also, are you using shaders?
    ------------------------------
    Sig: http://glhlib.sourceforge.net
    an open source GLU replacement library. Much more modern than GLU.
    float matrix[16], inverse_matrix[16];
    glhLoadIdentityf2(matrix);
    glhTranslatef2(matrix, 0.0, 0.0, 5.0);
    glhRotateAboutXf2(matrix, angleInRadians);
    glhScalef2(matrix, 1.0, 1.0, -1.0);
    glhQuickInvertMatrixf2(matrix, inverse_matrix);
    glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
    glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);

  3. #3
    Junior Member Newbie
    Join Date
    Jun 2012
    Location
    London, UK
    Posts
    15

    Thanks

    Quote Originally Posted by V-man View Post
    When you use VAO, you don't need to call bind the VBO, you don't need to enable the arrays and call glVertexAttribPointer. A VAO stores all those states.
    Also, are you using shaders?
    Yes, I am using shaders. I have removed the calls to Bind, enable arrays etc for the case where they should already be set up & associated with the VAO. Code works fine when I have only 1 VAO & 1 VBO, but as soon as I have more than one then I get what looks like random or arbiritrary output.

    My code inside the loop through objects in the scene looks like:

    Code :
    if (object not yet cached)
    {
             glGenVertexArrays( 1, &uVAO );
             glBindVertexArray( uVAO );
     
             glGenBuffers( 1, &uBuffer );
             glBindBuffer( GL_ARRAY_BUFFER, uBuffer );
     
             // Set up buffers for drawing facets
             glBufferData( );  
             glBufferSubData(// Vertices);
             glBufferSubData(// Normals); 
     
             SaveVaoInCache(uVao); 
     
             vPosition= glGetAttribLocation( shaderId, "vPosition" );
             glEnableVertexAttribArray( vPosition );
             vNormal = glGetAttribLocation( shaderId, "vNormal" ); 
             glEnableVertexAttribArray( vNormal );
             glVertexAttribPointer(vPosition etc );
             glVertexAttribPointer(vNormal etc ); 
    }
    else
    {
       uVAO = lookUpObjectInCache();
       glBindVertexArray( uVAO );
    }
     
    glDrawArrays( GL_TRIANGLES, 0, uVertices);

  4. #4
    Junior Member Newbie
    Join Date
    Jun 2012
    Location
    London, UK
    Posts
    15

    Resolves

    For posterity I am going to answer my own question here ...

    I never got multiple VAOs or buffers to work.

    There are other threads here that discuss performance ... so I decided to switch to one large buffer, use glBufferSubData() to hold the vertices of the various objects in the scene, and switch the offsets in glVertexAttribPointer () to match when drawing the objects. Pointers & memory layout seems easier to understand than the GL API. I still don't understand how multiple buffers/VAOs work ..

  5. #5
    Super Moderator OpenGL Guru
    Join Date
    Feb 2000
    Location
    Montreal, Canada
    Posts
    4,264
    So try to debug it. Inspect the values you get in each uVAO. Inspect the value you get for each VBO.
    What you are doing should work (all the vertices come first, then all the normals) but perhaps try to interleave them (x y z nx ny nz | x y z nx ny nz | x y ......).
    If that doesn't work. Try it without VAO (Write a GL 3.0 program).

    1 large VBO is fine if you are writing a small program. Try to keep it under 4 MB.
    ------------------------------
    Sig: http://glhlib.sourceforge.net
    an open source GLU replacement library. Much more modern than GLU.
    float matrix[16], inverse_matrix[16];
    glhLoadIdentityf2(matrix);
    glhTranslatef2(matrix, 0.0, 0.0, 5.0);
    glhRotateAboutXf2(matrix, angleInRadians);
    glhScalef2(matrix, 1.0, 1.0, -1.0);
    glhQuickInvertMatrixf2(matrix, inverse_matrix);
    glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
    glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);

  6. #6
    Junior Member Newbie
    Join Date
    Jun 2012
    Location
    London, UK
    Posts
    15

    Thanks.

    Quote Originally Posted by V-man View Post
    So try to debug it. Inspect the values you get in each uVAO. Inspect the value you get for each VBO.
    What you are doing should work (all the vertices come first, then all the normals) but perhaps try to interleave them (x y z nx ny nz | x y z nx ny nz | x y ......).
    If that doesn't work. Try it without VAO (Write a GL 3.0 program).

    1 large VBO is fine if you are writing a small program. Try to keep it under 4 MB.
    Yes, I was doing that ... it all seemed to work (I got progressive integers for the VAO & VBO ids .. just no output on the screen.

    A single buffer holding multiple objects is working fine, so I have parked this.

    Thanks anyway for your advice. I will keep an eye on the buffer size & return to this area if it goes > 4MB. I will also set the data up interleaved .. am currently adding texture coords so I will get that working with in my current order before interleaving it all (x y z nx ny nz tx ty | x y z nx ny nz tx ty | ...

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •