VBO related crash

I was having some strange problems, so I decided to make a small test and I experienced crashes.

It turns out that if I call it like this

glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
glVertexPointer(3, GL_FLOAT, 0, 0);

it runs OK, but if I call it like this

glVertexPointer(3, GL_FLOAT, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);

(where previously no VBO was bound, as in glBindBuffer(GL_ARRAY_BUFFER, 0); ) then it crashes.

Is that normal?

Yes, this is expected.

Unless a buffer is bound (or if buffer #0 is bound), all glPointer calls expect a pointer, not an offset. At the moment you call a glPointer call, it either stores a VBO+offset, or an actual system memory pointer. This lets you use multiple VBO’s for different attributes of the same object.

Meaning what exactly?

If I construct a VBO, can I call gl*Pointer and this becomes part of the VBO?

Then I can do

loop()
{
glBindBuffer(…, VBO[i++]);//For vertex
//no need to call any gl*Pointer
glBindBuffer(…, VBO[i++]);//For normal


glDrawElement or whatever
}

I thought the gl*Pointer functions were global.

I’m still experiencing some other problem but I’ll try to solve it myself.

[This message has been edited by V-man (edited 01-13-2004).]

I thought the gl*Pointer functions were global.

Think of it this way.

When you call glBindBuffer, you are telling OpenGL that all of the following gl*Pointer calls are going to use that VBO. This means that when you call:

glBindBuffer(1);
glVertexPointer(, 0);

The implementation stores, “Vertex Pointer uses VBO 1 at offset 0.” If you then do:

glBindBuffer(5);

This will not make the vertex pointer change to using VBO 5. It will still use VBO 1.

If you have not bound a buffer, and you call a gl*Pointer call, it records that this pointer is a real pointer to system memory, not an offset. So, if no buffer is bound and you do this:

glVertexPointer(<stuff>, 0)

Then the implementation records that the vertex pointer is using regular vertex arrays (not VBOs) and comes from memory location NULL. Clearly, this is going to cause a crash at some point.

So, if I have 2 VBOs, one that contains positions and one with normals, I do this to use them:

glBindBuffer(iPosBuffer);
glVertexPointer(, 0);
glBindBuffer(iNormBuffer);
glNormalPointer(, 0);

Remembering that the glVertexPointer call is not affected by the later call to glBindBuffer.

In short, you must bind the correct buffer before calling gl*Pointer calls.

OK, I went back to this problem.
After much testing, I found that this works.


//Conventional arrays
glBindBuffer(GL_ARRAY_BUFFER, VBO[2]);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, VertexSize, VBO_VertexAddress);
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, VertexSize, VBO_NormalAddress);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, VertexSize, VBO_TexCoordsAddress);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, VBO[3]);
glDrawRangeElements(GL_TRIANGLES, 0, EndVertexDRE, TotalIndex, GL_UNSIGNED_SHORT, 0);


but this doesn’t

glBindBuffer(GL_ARRAY_BUFFER, VBO[2]);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, VertexSize, VBO_VertexAddress);
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, VertexSize, VBO_NormalAddress);
glEnableVertexAttribArray(8);
glVertexAttribPointer(8, 2, GL_FLOAT, GL_FALSE, VertexSize, VBO_TexCoordsAddress);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, VBO[3]);
glDrawRangeElements(GL_TRIANGLES, 0, EndVertexDRE, TotalIndex, GL_UNSIGNED_SHORT, 0);

The above 2 codes render the exact same object, using the exact same VBO. The only diff is that conventional vs generic attributes. I check if I’m loading the functions pointers OK and that is fine.

By “not working”, I mean that it is running, but normal and tex coords are screwed up, but the geometry (vertices) seem fine.

Extra info: I tried both interleaved arrays and non-interleaved but this doesn’t make a difference (I think)

Any ideas?

Are you setting the clamping correctly? Should be set to [0…1] for colors, [-1…1] for tex-coords?

Also, shouldn’t you still use a ‘0’ for the pointer? So this…

glBindBuffer(GL_ARRAY_BUFFER, VBO[2]);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, VertexSize, VBO_VertexAddress);

becomes this instead:

glBindBuffer(GL_ARRAY_BUFFER, VBO[2]);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, VertexSize, 0);

Who says that tex coords need to be in the range [-1…1]?

Well, no-one. Did it work? But I thought it might clamp if you didn’t set the right mode.

There isn’t any issue with clamping. Values are passed through as is for tex coords.

Even If I get rid of texturing, the normals are still wrong. The geometry is rendered ok, but it looks like the last normal vector remains.

So I have no idea.
I will create a small test and upload it then and maybe check with someone.