Rendering Multiple VBOs

Started by
5 comments, last by Arcan3Artist 13 years, 11 months ago
Hi everyone, I'm curious, let's say I've defined several VBOs like this:

    //glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffer[0]);
    //glBufferDataARB(GL_ARRAY_BUFFER_ARB, vertex_0_Size, vertex_0_Data, GL_STATIC_DRAW_ARB);	
    //glVertexPointer(3, GL_FLOAT, 0, 0);

    //glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffer[1]);
    //glBufferDataARB(GL_ARRAY_BUFFER_ARB, vertex_1_Size, vertex_1_Data, GL_STATIC_DRAW_ARB);	
    //glVertexPointer(3, GL_FLOAT, 0, 0);
 
How would I actually render these two different VBOs? At the moment, I thought I would do something like this:

    // Render vbo zero
    glEnableClientState(GL_VERTEX_ARRAY);
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffer[0]);

    glEnable(GL_TEXTURE_2D);
    glDrawArrays(GL_QUADS, vertex_0_size, 0);
    glDisable(GL_TEXTURE_2D);
	
    glDisableClientState(GL_VERTEX_ARRAY);

    // Render vbo one
    glEnableClientState(GL_VERTEX_ARRAY);
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffer[1]);

    glEnable(GL_TEXTURE_2D);
    glDrawArrays(GL_QUADS, vertex_1_size, 0);
    glDisable(GL_TEXTURE_2D);
	
    glDisableClientState(GL_VERTEX_ARRAY);
    
But this doesn't seem to be working. Am I going about this totally wrong? Thank you.
Advertisement
You need to se the glVertexPointer before calling glDrawArrays. Also, your glDrawArrays call is wrong, it's glDrawArrays, mode, first, count), so it should be glDrawArrays(GL_QUADS, 0, size)
Quote:Also, your glDrawArrays call is wrong, it's glDrawArrays, mode, first, count), so it should be glDrawArrays(GL_QUADS, 0, size)

Sorry, that was a typo.

Quote:Original post by HuntsMan
You need to se the glVertexPointer before calling glDrawArrays.


The problem is, my program crashes when I try to set the vertex pointer. And I'm not even sure if I'm using the function call correctly. Would I just play it like this?

    // Render vbo zero    glEnableClientState(GL_VERTEX_ARRAY);    glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffer[0]);    glVertexPointer(3, GL_FLOAT, 0, 0);    glEnable(GL_TEXTURE_2D);    glDrawArrays(GL_QUADS, 0, vertex_0_size);    glDisable(GL_TEXTURE_2D);    glDisableClientState(GL_VERTEX_ARRAY);


The glVertexPointer function is declared as
void glVertexPointer(	GLint  	size,  	GLenum  	type,  	GLsizei  	stride,  	const GLvoid *  	pointer);


Can I put a zero in for "pointer", or do I need to actually point to some data?

Thanks again for the help.
Ok, I seem to be making some progress. I'm getting multiple VBOs to render using the following code. Hopefully this will help other people.

Initialization:

    glGenBuffersARB(1, &texBuffer[0]);    glGenBuffersARB(1, &texBuffer[1]);    glGenBuffersARB(1, &vertexBuffer[0]);    glGenBuffersARB(1, &vertexBuffer[1]);    glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffer[0]);    glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(GLfloat) * 3 * 4 * face_group_0.size(), face_group_0_vertices, GL_STATIC_DRAW_ARB);	    //glVertexPointer(3, GL_FLOAT, 0, 0);    glBindBufferARB(GL_ARRAY_BUFFER_ARB, texBuffer[0]);    glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(GLfloat) * 2 * 4 * face_group_0.size(), face_group_0_texture, GL_STATIC_DRAW_ARB);        //glTexCoordPointer(2, GL_FLOAT, 0, 0);       glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffer[1]);    glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(GLfloat) * 3 * 4 * face_group_1.size(), face_group_1_vertices, GL_STATIC_DRAW_ARB);	    //glVertexPointer(3, GL_FLOAT, 0, 0);    glBindBufferARB(GL_ARRAY_BUFFER_ARB, texBuffer[1]);    glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(GLfloat) * 2 * 4 * face_group_1.size(), face_group_1_texture, GL_STATIC_DRAW_ARB);        //glTexCoordPointer(2, GL_FLOAT, 0, 0);   


Drawing loop:

    glBindTexture(GL_TEXTURE_2D, texture_manager->texture[0].texture);        glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffer[0]);    glEnableClientState(GL_VERTEX_ARRAY);    glVertexPointer(3, GL_FLOAT, 0, 0);    glBindBufferARB(GL_ARRAY_BUFFER_ARB, texBuffer[0]);    glEnableClientState(GL_TEXTURE_COORD_ARRAY);    glTexCoordPointer(2, GL_FLOAT, 0, 0);         glEnable(GL_TEXTURE_2D);    glDrawArrays(GL_QUADS, 0, face_group_0.size() * 4);    glDisable(GL_TEXTURE_2D);    glDisableClientState(GL_TEXTURE_COORD_ARRAY);    glDisableClientState(GL_VERTEX_ARRAY);    glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffer[1]);    glEnableClientState(GL_VERTEX_ARRAY);    glVertexPointer(3, GL_FLOAT, 0, 0);    glBindBufferARB(GL_ARRAY_BUFFER_ARB, texBuffer[1]);    glEnableClientState(GL_TEXTURE_COORD_ARRAY);    glTexCoordPointer(2, GL_FLOAT, 0, 0);         glEnable(GL_TEXTURE_2D);    glDrawArrays(GL_QUADS, 0, face_group_1.size() * 4);    glDisable(GL_TEXTURE_2D);    glDisableClientState(GL_TEXTURE_COORD_ARRAY);    glDisableClientState(GL_VERTEX_ARRAY);
Yes, zero is fine if you have a VBO bound. Did you upload the data correctly?
Yes, I believe the data was uploaded correctly. However, I kept getting a crash every time I tried to make a call to glVertexPointer inside the draw loop, so I figured I was doing something wrong.

I did a clean build, and that seemed to fix everything. Thanks.
I've been working on the similar problem on OpenGL ES. Basically it's the same, just without the ARB extension.

To create ur vertex buffer do this:

// allocate the vertex datauint vertexPosSize = sizeof(GLfloat) * 3 * numVertices;GLfloat vertexPosition = malloc(vertexPosSize);	// generate the vertex bufferglGenBuffers(1, &buffers[0]);glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);glBufferData(GL_ARRAY_BUFFER, vertexPosSize, vertexPosition, GL_DYNAMIC_DRAW);// make sure we reset back to the no set buffer //(this can cause other rendering modes to not render if not done)glBindBuffer(GL_ARRAY_BUFFER, 0);


To update the data in the buffer for Dynamic types, do this:

// update the dynamic vertex dataglBindBuffer(GL_ARRAY_BUFFER, buffers[0]);glBufferSubData(GL_ARRAY_BUFFER, 0, vertexPosSize, vertexPosition);glVertexPointer(3, GL_FLOAT, 0, 0);


Obviously if you're using a static buffer you don't need to do that.

To render, i did this. You should be able to use whatever draw method you like, as long as you enable the appropriate client state arrays and bind the buffer for use.

glEnableClientState(GL_VERTEX_ARRAY);// bind the buffer for useglBindBuffer(GL_ARRAY_BUFFER, buffers[0]);// we set the stride and vertex data to zero // because we are using the vertex bufferglVertexPointer(3, GL_FLOAT, 0, 0);// render our objectglDrawElements(GL_TRIANGLE_STRIP, currentUsedIndices - 2, GL_UNSIGNED_SHORT, (const void*)indices);glDisableClientState(GL_VERTEX_ARRAY);


That's the basic jist of how you'd do it, believe me, it was a bit of a pain trying to figure it out especially when the only problem was the lack of one little piece of information that wasn't in the red book, which would of been really handy to know.

For rendering multiple buffers, it would be simply a matter of generating those buffers, binding one buffer, drawing it, then binding the next and drawing that one. And you should be able to do with between a single glEnableClientState and and glDisableClientState. That way you minimise the amount of state change calls made.

You could also isolate the render call, to a single function which has the buffer ids set to it. That way you can isolate the problem into a single rendering function, also, save you some time rewriting a little bit of code : 3

Either way, hope it all helps!

This topic is closed to new replies.

Advertisement