Leaving VBOs empty?

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

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 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 on other sites

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 on other sites
Quote:
 Original post by karwostsAre 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 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.

1. 1
2. 2
3. 3
Rutin
18
4. 4
JoeJ
14
5. 5

• 14
• 9
• 23
• 9
• 32
• Forum Statistics

• Total Topics
632625
• Total Posts
3007508
• Who's Online (See full list)

There are no registered users currently online

×