Skip to main content
GameDev.net gamedev.net
🔒 Locked

vbo stride question

Started by nitzan Nov 4, 2003 at 12:32 AM 12 replies 3.4k views
Original Post
nitzan
nitzan
Why is the stride for glVertexPointer, glTexCoordPointer and glNormalPointer set to 0 in the SGI and Nehe examples ? I am packing all 3 into my data and I set the stride to (sizeof(GLfloat)*8) (3 for vertex, 3 for normal and 2 for texcoords). This (I think) is what causes it to crash once in a while. When my level loads everything is drawn fine. If I set the stride to zero, my geometry looks completely screwed up. What should the stride be set to and why ? Thanks, Nitzan
vincoof
vincoof
It depends on how is packed your data.

If you have all your vertex data in one array (array : read as malloc''ed pointer), all your normals in another array, etc. Then your stride is 0. For instance if vertex, normals, etc are stored like that :
[vertex0][vertex1][vertex2]...
[normal0][normal1][normal2]...
[texcoord0][texcoord1][texcoord2]...


If your vertex, normal, etc is packed like that :
[vertex0][normal0][texcoord0][vertex1][normal1][texcoord1][vertex2][normal2][texcoord2]...
Then you should set a non-null stride, which corresponds to the offset needed to switch from one element to the next. (this stride is counted as bytes btw)
nitzan
nitzan
So if my data is packed as follows:

[vertex][vertex][vertex][normal][normal][normal[tex][tex]

Is my stride 8 for all of them ? Or is it 5 for glVertexPointer, 5 for glNormalPointer and 6 for glTexCoordPointer ?

My other (new) questions are...
#1 is the stride given in bytes or bits ?
#2 when calling glBufferDataARB(), do I pass the size of the data in bytes or bits ?
#3 for glDrawElements, do I pass the size of the data in bytes or bits ?

Thanks!

Nitzan Wilnai
stefu
stefu

class vec3 { float x,y,z; }
class vec2 { float x,y; }

class vertex
{
vec3 coord, normal;
vec2 texcoord;
};
vertex vertexarray[1000]; // stride is sizeof(vertex)=8*4=32;


OR

vec3 coord_array[1000]; // stride is sizeof(vec3) or 0

vec3 normal_array[1000]; // stride is sizeof(vec3) or 0

vec2 texcoord_array[1000]; // stride is sizeof(vec2) or 0

stefu
stefu
bytes always, no bits!
Sneftel
Sneftel
There tends to be a bit of confusion regarding VBO stride, mostly because of its special meaning for 0.

"Stride" in this context means the distance between the beginning of a value in memory, and the beginning of the next value in memory. It is not the distance between the end of one and the beginning of the next. So in a VBO that is an array of a structure, the stride for each element of that structure will be the sizeof the structure as a whole. Keep in mind that struct padding can affect this.


How appropriate. You fight like a cow.
nitzan
nitzan
Ok great,

And stride is in bytes right ?

So now is the size for glBufferDataARB() and glDrawElements in bytes or bits ?

Thanks,

Nitzan
stefu
stefu
bytes, god damn, bytes!!!
nitzan
nitzan
Wait, by bytes you mean bits right ?

Just kidding! Sorry Stefu, I didnt notice your earlier post.

Thanks guys,

It works great on one machine, I will try on a couple of other ones soon.

Nitzan
nitzan
nitzan
Well, it still doesnt work on my main machine (GF3 TI200 and 52.16 drivers).

Can anyone tell me if anything is wrong with this code ?

I edited and cleaned up and fixed the code a bit so its easier to read. I am guessing that one of my sizes is incorrect as the code works fine in debug mode but crashes in release. It actually displays the level in the first frame but crashes on the second one.




// create model


// 12 triangles


// vertices


glGenBuffersARB(1, &vertexObject);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexObject);

// 432 = sizeof(GLfloat) * 12 triangles * 3 vertices * 3 values

glBufferDataARB(GL_ARRAY_BUFFER_ARB, 432, NULL, GL_STATIC_DRAW_ARB);
vertex_data=(float *)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
// pack vertex data

glUnmapBufferARB(GL_ARRAY_BUFFER_ARB)

// normals


glGenBuffersARB(1, &normalObject);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, normalObject);

// 432 = sizeof(GLfloat) * 12 triangles * 3 vertices * 3 values

glBufferDataARB(GL_ARRAY_BUFFER_ARB, 432, NULL, GL_STATIC_DRAW_ARB);
normal_data=(float *)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
// pack normal data

glUnmapBufferARB(GL_ARRAY_BUFFER_ARB)


// textures


glGenBuffersARB(1, &textureObject);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, textureObject);

// 288 = sizeof(GLfloat) * 12 triangles * 3 vertices * 2 values

glBufferDataARB(GL_ARRAY_BUFFER_ARB, 288, NULL, GL_STATIC_DRAW_ARB);
texcoord_data=(float *)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
// pack texture data

glUnmapBufferARB(GL_ARRAY_BUFFER_ARB)



// draw model


glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexObject);
glVertexPointer(3, GL_FLOAT, 0, 0);

glBindBufferARB(GL_ARRAY_BUFFER_ARB, normalObject);
glNormalPointer(GL_FLOAT, 0, 0);

glBindBufferARB(GL_ARRAY_BUFFER_ARB, textureObject);
glTexCoordPointer(2, GL_FLOAT, 0, 0);

// 36 indices, one for each vertices

glDrawRangeElements(GL_TRIANGLES, 0, 36, 36, GL_UNSIGNED_SHORT, indices);



// draw shadows


// draw shadow (carmack's reverse, closed part)

// 4 visible triangles, 8 drawn (4 on top and 4 on bottom)


glGenBuffersARB(1, &dynamic_tightshadow_vertexObject);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, dynamic_tightshadow_vertexObject);

// 288 = sizeof(GLfloat) * 8 triangles * 3 vertices * 3 values

glBufferDataARB(GL_ARRAY_BUFFER_ARB, 288, NULL, GL_DYNAMIC_DRAW_ARB);
data=(float *)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
// pack shadow data

glUnmapBufferARB(GL_ARRAY_BUFFER_ARB)

glBindBufferARB(GL_ARRAY_BUFFER_ARB, dynamic_tightshadow_vertexObject[which]);

// Vertex positions are at offset 0

glVertexPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(0));

// 24 indices

glDrawRangeElements(GL_TRIANGLES, 0, 24, 24, GL_UNSIGNED_SHORT, dynamic_tightshadow_indices);


// draw shadow (carmack's reverse, side part)

// 4 visible triangles, 12 drawn (12 triangles to completely wrap the 4)


glGenBuffersARB(1, &dynamic_sideshadow_vertexObject);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, dynamic_sideshadow_vertexObject);

// 432 = sizeof(GLfloat) * 12 triangles * 3 vertices * 3 values

glBufferDataARB(GL_ARRAY_BUFFER_ARB, 432, NULL, GL_DYNAMIC_DRAW_ARB);
data=(float *)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
// pack shadow data

glUnmapBufferARB(GL_ARRAY_BUFFER_ARB)

glBindBufferARB(GL_ARRAY_BUFFER_ARB, dynamic_sideshadow_vertexObject);

// Vertex positions are at offset 0

glVertexPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(0));

// 36 indices

glDrawRangeElements(GL_TRIANGLES, 0, 36, 36, GL_UNSIGNED_SHORT, dynamic_sideshadow_indices);



Thanks,

Nitzan


Edited: I mistakenly wrote the wrong number of indices for the model. Its 36, not 12 (yes I know I can reduce it to 8 but I am doing this for simplicity's sake). Also added the glUnmapBufferARB() calls.


[edited by - nitzan on November 5, 2003 2:44:36 PM]
vincoof
vincoof
When you get a pointer with glMapBufferARB you can''t hold the pointer forever. You have to release the memory by calling glUnmapBufferARB, and check the return which his very important.

There''s an example int the specification I think. Check the OpenGL Extension Registry.

As a side note, I don''t think that 288 stands for "sizeof(GLfloat) * 8 triangles * 3 vertices * 3 values".
Rather I''d say it''s "sizeof(GLfloat) * 12 triangles * 3 vertices * 2 values".
You don''t need to pre-compute the values yourself, it leads to confusion.
I mean, you can simply write :
glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(GLfloat)*12*3*2, NULL, GL_STATIC_DRAW_ARB);

Any decent compiler will compute the value at compile-time and there will be absolutely not penalty at all at run-time.
nitzan
nitzan
I am calling glUnMapBufferARB() in my actual code.

This is not my actual code, I just simpilified my code and showed what values it would call IF I were to render a cube with carmacks''s reverse shadows.

I just want someone to check my values since my bug seems to be size related.

Thanks,

Nitzan
vincoof
vincoof
What''s the point of :

glBindBufferARB(GL_ARRAY_BUFFER_ARB, dynamic_tightshadow_vertexObject[which]);

It is syntaxically not correct. Is it a typo of your simplified version, or is it exactly like that in your code ?

> I just want someone to check my values since
> my bug seems to be size related.

Have you checked the return of glUnmapBufferARB ? If you''re out of memory, this will more than likely be told here.

Also, how do you fill your buffers ? I was told some time ago that memcpy has to be banned. Let''s hope you don''t use it.
nitzan
nitzan
glBindBufferARB(GL_ARRAY_BUFFER_ARB, dynamic_tightshadow_vertexObject[which]);
is a mistake. there should be no [which] there.

I just figured out that I was not disabling GL_TEXTURE_COORD_ARRAY and GL_NORMAL_ARRAY before drawing my shadows. I changed my code so it disabled them and re-enables them after shadows and everything seems to work great.

I am not using memcpy by the way. I am linearly filling up the memory I allocated. Now that I think of it, memcpy might be a good idea...

Nitzan

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.