Sign in to follow this  
Optimus Prime

Rendering Multiple VBOs

Recommended Posts

Optimus Prime    122
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.

Share this post


Link to post
Share on other sites
HuntsMan    368
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)

Share this post


Link to post
Share on other sites
Optimus Prime    122
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.

Share this post


Link to post
Share on other sites
Optimus Prime    122
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);

Share this post


Link to post
Share on other sites
Optimus Prime    122
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.

Share this post


Link to post
Share on other sites
Arcan3Artist    140
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 data
uint vertexPosSize = sizeof(GLfloat) * 3 * numVertices;
GLfloat vertexPosition = malloc(vertexPosSize);

// generate the vertex buffer
glGenBuffers(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 data
glBindBuffer(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 use
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);

// we set the stride and vertex data to zero
// because we are using the vertex buffer
glVertexPointer(3, GL_FLOAT, 0, 0);

// render our object
glDrawElements(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!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this