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 7 of 7

Thread: Is there a simple multiple VBO example?

  1. #1
    Junior Member Newbie
    Join Date
    Jun 2013
    Posts
    8

    Is there a simple multiple VBO example?

    Is there a simple multiple VBO/IBO example...
    say that just draws 2 different triangles .. where each is a separate VBO/IBO.

    I obviously want to code a more complicated example but my current one only displays the last one so obviously I'm doing something wrong.

    I figured a watered down example would illustrate the issue.

  2. #2
    Junior Member Newbie
    Join Date
    Jun 2013
    Posts
    8
    Here is what I am currently trying...


    Variable initialization:
    Code :
    GLuint vertexbuffer;
    GLuint uvbuffer;
    GLuint normalbuffer;
    GLuint colorbuffer;
    GLuint elementbuffer;
    GLuint VertexArrayID;
     
    std::vector<unsigned short> indices;
    std::vector<glm::vec3> indexed_vertices;
    std::vector<glm::vec2> indexed_uvs;
    std::vector<glm::vec3> indexed_normals;
    std::vector<glm::vec4> indexed_colors;
     
     
    GLuint vertexbuffer2;
    GLuint uvbuffer2;
    GLuint normalbuffer2;
    GLuint colorbuffer2;
    GLuint elementbuffer2;
    GLuint VertexArrayID2;
     
    std::vector<unsigned short> indices2;
    std::vector<glm::vec3> indexed_vertices2;
    std::vector<glm::vec2> indexed_uvs2;
    std::vector<glm::vec3> indexed_normals2;
    std::vector<glm::vec4> indexed_colors2;
     
    struct PackedVertex{
    	glm::vec3 position;
    	glm::vec2 uv;
    	glm::vec3 normal;
    	glm::vec4 color;
    	bool operator<(const PackedVertex that) const{
    		return memcmp((void*)this, (void*)&that, sizeof(PackedVertex))>0;
    	};
    };
     
    std::vector<glm::vec3>  in_vertices;
    std::vector<glm::vec2>  in_uvs;
    std::vector<glm::vec3>  in_normals;
    std::vector<glm::vec4>  in_colors;
     
    in_vertices.push_back(glm::vec3(0,0,0));
    in_vertices.push_back(glm::vec3(1,0,0));
    in_uvs.push_back(glm::vec2(0,0));
    in_uvs.push_back(glm::vec2(0,0));
     
    in_normals.push_back(glm::vec3(0,1,0));
    in_normals.push_back(glm::vec3(0,1,0));
    in_colors.push_back(glm::vec4(1,1,1,1));
    in_colors.push_back(glm::vec4(1,0,0,1));
     
     
    std::vector<glm::vec3>  in_vertices2;
    std::vector<glm::vec2>  in_uvs2;
    std::vector<glm::vec3>  in_normals2;
    std::vector<glm::vec4>  in_colors2;
     
     
    in_vertices2.push_back(glm::vec3(0,1.3,0));
    in_vertices2.push_back(glm::vec3(1,1.3,0));
     
    in_uvs2.push_back(glm::vec2(0,0));
    in_uvs2.push_back(glm::vec2(0,0));
     
    in_normals2.push_back(glm::vec3(0,1,0));
    in_normals.push_back(glm::vec3(0,1,0));
     
    in_colors2.push_back(glm::vec4(0,0,1,1));
    in_colors2.push_back(glm::vec4(0,0,1,1));

    Code :
    void InitializeVertexBuffer(GLuint &theBuffer, GLenum target,  GLenum usage, const void* data,  int size)
    {
    	glGenBuffers(1, &theBuffer);
    	glBindBuffer(target, theBuffer);
    	glBufferData(target, size, data, usage);
    	glBindBuffer(target, 0);
    }

    Setting up IBO/VAO/VBO
    Code :
    // For each input vertex
    for ( unsigned int i=0; i<2; i++ ){
     
    	// Try to find a similar vertex in out_XXXX
    	unsigned short index;
    	bool found = getSimilarVertexIndex(in_vertices[i], in_uvs[i], in_normals[i],     indexed_vertices, indexed_uvs, indexed_normals, index);
     
    	if ( found ){ // A similar vertex is already in the VBO, use it instead !
    		indices.push_back( index );
    	}else{ // If not, it needs to be added in the output data.
    		indexed_vertices.push_back( in_vertices[i]);
    		indexed_uvs     .push_back( in_uvs[i]);
    		indexed_normals .push_back( in_normals[i]);
    		indexed_colors .push_back( in_colors[i]);
    		indices .push_back( (unsigned short)indexed_vertices.size() - 1 );
    	}
    }
     
     
     
    	size_t colorDataOffset = 0;
    InitializeVertexBuffer(vertexbuffer, GL_ARRAY_BUFFER, GL_STATIC_DRAW, &indexed_vertices[0], indexed_vertices.size() * sizeof(glm::vec3)  );
    InitializeVertexBuffer(uvbuffer, GL_ARRAY_BUFFER, GL_STATIC_DRAW, &indexed_vertices[0], indexed_vertices.size() * sizeof(glm::vec2)  );
    InitializeVertexBuffer(normalbuffer, GL_ARRAY_BUFFER, GL_STATIC_DRAW, &indexed_normals[0], indexed_normals.size() * sizeof(glm::vec3)  );
    InitializeVertexBuffer(colorbuffer, GL_ARRAY_BUFFER, GL_STATIC_DRAW, &indexed_colors[0], indexed_colors.size() * sizeof(glm::vec4)  );
    InitializeVertexBuffer(elementbuffer, GL_ARRAY_BUFFER, GL_STATIC_DRAW, &indices[0], indices.size() * sizeof(unsigned short)  );
     
    //Generate VAO
    glGenVertexArrays(1, &VertexArrayID);
    glBindVertexArray(VertexArrayID);
     
    // 1rst attribute buffer : vertices
    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0 );
     
    // 2nd attribute buffer : normals
    glEnableVertexAttribArray(1);
    glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)0 );
     
    // 3nd attribute buffer : UVs
    glEnableVertexAttribArray(2);
    glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, (void*)0 );
     
    // 4th attribute buffer : colors
    glEnableVertexAttribArray(3);
    glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
    glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, 0, (void*)0 );
     
    // Index buffer
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);	
     
     
    //****Second one*****//
     
    		// For each input vertex
    	for ( unsigned int i=0; i<2; i++ ){
     
    		// Try to find a similar vertex in out_XXXX
    		unsigned short index;
    		bool found = getSimilarVertexIndex(in_vertices2[i], in_uvs2[i], in_normals2[i],     indexed_vertices2, indexed_uvs2, indexed_normals2, index);
     
    		if ( found ){ // A similar vertex is already in the VBO, use it instead !
    			indices2.push_back( index );
    		}else{ // If not, it needs to be added in the output data.
    			indexed_vertices2.push_back( in_vertices2[i]);
    			indexed_uvs2     .push_back( in_uvs2[i]);
    			indexed_normals2 .push_back( in_normals[i]);
    			indexed_colors2 .push_back( in_colors2[i]);
    			indices2.push_back( (unsigned short)indexed_vertices2.size() - 1 );
    		}
    	}
     
    size_t colorDataOffset = 0;
    InitializeVertexBuffer(vertexbuffer2, GL_ARRAY_BUFFER, GL_STATIC_DRAW, &indexed_vertices2[0], indexed_vertices2.size() * sizeof(glm::vec3)   );
    InitializeVertexBuffer(uvbuffer2, GL_ARRAY_BUFFER, GL_STATIC_DRAW, &indexed_vertices2[0], indexed_vertices2.size() * sizeof(glm::vec2)  );
    InitializeVertexBuffer(normalbuffer2, GL_ARRAY_BUFFER, GL_STATIC_DRAW, &indexed_normals2[0], indexed_normals2.size() * sizeof(glm::vec3)  );
    InitializeVertexBuffer(colorbuffer2, GL_ARRAY_BUFFER, GL_STATIC_DRAW, &indexed_colors2[0], indexed_colors2.size() * sizeof(glm::vec4)  );
    InitializeVertexBuffer(elementbuffer2, GL_ARRAY_BUFFER, GL_STATIC_DRAW, &indices2[0], indices2.size() * sizeof(unsigned short)  );
     
    //Generate VAO
    glGenVertexArrays(1, &VertexArrayID2);
    glBindVertexArray(VertexArrayID2);
     
     
    	// 1rst attribute buffer : vertices
    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer2);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0  );
     
    // 2nd attribute buffer : normals
    glEnableVertexAttribArray(1);
    glBindBuffer(GL_ARRAY_BUFFER, normalbuffer2);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)0 );
     
    // 3nd attribute buffer : UVs
    glEnableVertexAttribArray(2);
    glBindBuffer(GL_ARRAY_BUFFER, uvbuffer2);
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, (void*)0 );
     
    // 4th attribute buffer : colors
    glEnableVertexAttribArray(3);
    glBindBuffer(GL_ARRAY_BUFFER, colorbuffer2);
    glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, 0, (void*)0 );
     
    // Index buffer
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer2);

    Now Drawing
    Code :
    do{
    glUseProgram(programID);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
    // Draw the primatives !
    glDrawElements(GL_POINTS, 2, GL_UNSIGNED_SHORT, (void*)0);
     
     
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer2);
    glDrawElements(GL_LINES, 2, GL_UNSIGNED_SHORT, (void*)0);
     
    glUseProgram(0); 
    glfwSwapBuffers();
    ..}

    So when I init the 2nd VBO it over and I only get 2 blue dots and not 2 dots and a line

  3. #3
    Junior Member Newbie
    Join Date
    Jun 2013
    Posts
    3
    That happens because you have to redefine the vertex attribute arrays. You have to draw your elementbuffer directly after you setup your buffer's layout via glVertexAttribPointer().

    Basic example:
    Code :
    //draw the points
    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
     
    //set up other buffers that belong to your point-setup
     
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
    glDrawElements(GL_POINTS, 2, GL_UNSIGNED_SHORT, (void*)0);
     
    //draw the lines
    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer2);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
     
    //set up other buffers that belong to your line-setup
     
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer2);
    glDrawElements(GL_LINES, 2, GL_UNSIGNED_SHORT, (void*)0);

    When you do your glDrawElements() call the data is read from the addresses that you set by glVertexAttribPointer(), so you have to setup your pointers via glVertexAttribPointer() each time before you do your draw-call (unless you want to draw the same things or different things but from the same VBO's).

  4. #4
    Junior Member Newbie
    Join Date
    Jun 2013
    Posts
    8
    So does that mean I always have to interleave draw calls?

    So I cannot bind different VBOs for each attribute, and A Vertex Array Object or VAO to store the state of all the glVertexAttribPointer calls and the VBOs that were targeted when each of the glVertexAttribPointer calls were made?

    I would think I could use something to store the state of the glVertexAttribPointer(s) when I init the buffers so that I could call them later than reset them in the draw loop especially for static geometry.


    Quote Originally Posted by JohnMarkem View Post
    That happens because you have to redefine the vertex attribute arrays. You have to draw your elementbuffer directly after you setup your buffer's layout via glVertexAttribPointer().

    When you do your glDrawElements() call the data is read from the addresses that you set by glVertexAttribPointer(), so you have to setup your pointers via glVertexAttribPointer() each time before you do your draw-call (unless you want to draw the same things or different things but from the same VBO's).

  5. #5
    Junior Member Newbie
    Join Date
    Jun 2013
    Posts
    3
    Just use a few VAOs and the problem is solved

  6. #6
    Junior Member Newbie
    Join Date
    Jun 2013
    Posts
    8
    Where should I put the few VAOs... and how do I store that to work so I can use it for multiple meshes.. interleving the draw calls like that and binds in that fashion still just seems wrong in practice even if it might work.

    I would think you could set that all up in an initialization somewhere ahead of time and it would work out

  7. #7
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    3,188
    Quote Originally Posted by Limingdu View Post
    So does that mean I always have to interleave draw calls?
    No. You can choose whether to interleave or not. Further, if you don't interleave, you can choose whether to put all of the vertex attribs in separate buffers per attrib, the same buffer for all attribs, or anywhere in between.

    So I cannot bind different VBOs for each attribute,
    Sure you can.

    ...and A Vertex Array Object or VAO to store the state of all the glVertexAttribPointer calls and the VBOs that were targeted when each of the glVertexAttribPointer calls were made?
    Sure, no problem.

    See Example 5.3 here: Chapter 5. Objects in Depth


    BTW, I don't understand the comment about using a few VAOs.

Posting Permissions

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