Sign in to follow this  

Leaving VBOs empty?

This topic is 2537 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi all,

I've encountered an unusual issue with VBOs. I generate two VBOs to use as model caches. It sometimes happens that one VBO is filled with a model and then displayed while the other remains entirely empty. Sometimes, this causes drawing to fail silently.

Specifically, if I have two VBOs with IDs 1 and 2 (1 being the first one generated), both having memory reserved with glBufferData() (but no actual information transferred), and I then bind VBO 1, upload data, and try to display, it fails.

But if I upload to VBO 2, the last VBO generated, while leaving VBO 1 empty, it works okay.

Here is how I generate my VBOs:


// Create static VBO
glGenBuffers(1, &(cache->vboID)); // generate a buffer ID
glBindBuffer(GL_ARRAY_BUFFER, cache->vboID); // bind buffer (make it active), indicate it will hold vertices
glBufferData(GL_ARRAY_BUFFER, maxVerts*VBO_VERTEX_SIZE*sizeof(GLfloat), 0, GL_STATIC_DRAW);

// Set up vertex pointers
glVertexPointer(3, GL_FLOAT, VBO_VERTEX_SIZE*sizeof(GLfloat), (GLvoid *) (VBO_VERTEX_OFFSET_X*sizeof(GLfloat)));
glTexCoordPointer(2, GL_FLOAT, VBO_VERTEX_SIZE*sizeof(GLfloat), (GLvoid *) (VBO_VERTEX_OFFSET_TX*sizeof(GLfloat)));



That code is called twice. I have two "cache" structures. Two different VBO IDs are successfully generated.

Next, I cache and render:


// Determine whether model is in polygon RAM or VROM
if (modelAddr < 0x100000)
cache = &polyCache;
else
cache = &vromCache;
//cache = &vromCache;
//printf("%d, cache->numModels=%d, cache->vertIdx=%d, cache->maxVerts=%d, cache->maxIdx=%d\n", cache->vboID, cache->numModels, cache->vertIdx, cache->maxVerts, cache->maxIdx);

// Bind the appropriate VBO (make it active)
glBindBuffer(GL_ARRAY_BUFFER, cache->vboID);

// Look up the model in the LUT. If not cached, cache it first before drawing.
lutIdx = modelAddr&0xFFFFFF;
if (cache->lut[lutIdx] < 0)
CacheModel(cache,lutIdx,modelAddr);
model = cache->lut[lutIdx];

// Draw it!
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
//printf("Drawing %d: %d, %d verts\t%d\n", model, cache->models[model].index, cache->models[model].numVerts);
glDrawArrays(GL_TRIANGLES, cache->models[model].index, cache->models[model].numVerts);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);



Now here is where things get interesting. Note that depending on modelAddr, either polyCache or vromCache will be selected. polyCache is created first (VBO ID = 1), vromCache second. If I just want to cache and render one model out of polygon RAM, this code will fail. If I force it to use vromCache, it works fine.

If I try to render more complex scenes with a mix of both, it seems to work okay.

What gives?

Share this post


Link to post
Share on other sites
Are you assuming that glVertexPointer is stored per buffer? I can't quite tell from your code, but I'm fairly sure this isn't the case.

Therefore if you do this:

glBindBuffer(1);
glVertexPointer(...);

glBindBuffer(2);
glVertexPointer(...);

glBindBuffer(1); //<-- this does nothing! DrawArrays doesn't draw
//from the bound buffer, but rather the buffer
//that was bound when you last called vertex pointer.

glDrawArrays(...);


And you assume this is drawing from buffer #1, than you're not going to get what you expect.

Share this post


Link to post
Share on other sites
Some more information:

If I prevent the vboCache from being created altogether, the code will work straight out of the polyCache. I thought a clever fix might be:


glBufferData(GL_ARRAY_BUFFER, maxVerts*VBO_VERTEX_SIZE*sizeof(GLfloat), 0, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, cache->maxIdx*sizeof(GLfloat), cache->verts);



This basically uploads garbage data that is never used. Oddly, it doesn't fix things. I'm having a hard time pinning down exactly what the difference between vromCache and polyCache is. They're identical structures! I'm being very careful about selecting the VBO with glBindBuffer() before performing operating on it.

Share this post


Link to post
Share on other sites
Quote:
Original post by karwosts
Are you assuming that glVertexPointer is stored per buffer? I can't quite tell from your code, but I'm fairly sure this isn't the case.

Therefore if you do this:
*** Source Snippet Removed ***
And you assume this is drawing from buffer #1, than you're not going to get what you expect.


Ahh... I didn't realize this. I thought the pointers were set up for the currently bound VBO. Isn't this a bit inconsistent on the part of OpenGL?

EDIT: I tried adding this before drawing/caching:


// Bind the appropriate VBO and make it active by setting up the pointers
glBindBuffer(GL_ARRAY_BUFFER, cache->vboID);
glVertexPointer(3, GL_FLOAT, VBO_VERTEX_SIZE*sizeof(GLfloat), (GLvoid *) (VBO_VERTEX_OFFSET_X*sizeof(GLfloat)));
glTexCoordPointer(2, GL_FLOAT, VBO_VERTEX_SIZE*sizeof(GLfloat), (GLvoid *) (VBO_VERTEX_OFFSET_TX*sizeof(GLfloat)));



It still doesn't work. Does this mean that once I set up pointers, I can no longer switch VBOs?

EDIT 2: Nevermind. It works beautifully!

Thanks :)

Share this post


Link to post
Share on other sites
It's actually like this so you can draw from multiple VBO's at the same time.

You could have one VBO that held vertex positions, and another that stored texture coordinates. Then you set the vertexpointer into one buffer, and texcoordpointer into the other buffer, and you can draw like that.

That wouldn't be an option if you can only draw from the bound buffer.

Share this post


Link to post
Share on other sites

This topic is 2537 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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