Jump to content
  • Advertisement
Sign in to follow this  
ileonte

OpenGL Glvertexattribpointer(): Understanding The 'Stride' Parameter

This topic is 2722 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

The glVertexAttribPointer() manual page has this to say about the 'stride' parameter:
Specifies the byte offset between consecutive generic vertex attributes. If 'stride' is 0, the generic vertex attributes are understood to be tightly packed in the array. The initial value is 0.[/quote]
This leads me to believe that 'stride' measures the 'space' between the END of the attribute for a given vertex and the START of the attribute for the next vertex in a VBO. However from testing I cannot confirm this. Consider the following code:
static float VDATA[2][6][3] = {
{
{ 10.25, 20.00, 20.00 },
{ 10.25, -19.75, 20.00 },
{ 50.25, 20.00, 20.00 },
{ 10.25, -19.75, 20.00 },
{ 50.25, -19.75, 20.00 },
{ 50.25, 20.00, 20.00 }
},
{
{ -50.75, 20.00, 20.00 },
{ -50.75, -19.75, 20.00 },
{ -10.75, 20.00, 20.00 },
{ -50.75, -19.75, 20.00 },
{ -10.75, -19.75, 20.00 },
{ -10.75, 20.00, 20.00 }
}
};
static uint32_t ELEM[12] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };

static bool initialized = false;

static void engineRender( void )
{
GLint idx = 0;

if ( !initialized ) {
initialized = true;

/* VBO */
glGenBuffers( 1, &state->vbo );
glBindBuffer( GL_ARRAY_BUFFER, state->vbo );
glBufferData( GL_ARRAY_BUFFER,
4 * 9 * sizeof( float ), /* 4(triangles) * 9(floats per triangle, 3 for each vertex) */
&VDATA[0][0][0], /* both quads */
GL_STATIC_DRAW );

glGenBuffers( 1, &state->ebo );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, state->ebo );
glBufferData( GL_ELEMENT_ARRAY_BUFFER,
4 * 3 * sizeof( uint32_t ), /* 4(triangles) * 3(indices per triangle) */
ELEM,
GL_STATIC_DRAW );
}

glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

/*
* First draw - left side, blue squares
*/
engineLookAt( 0.0, 0.0, 5.0, /* camera position */
0.0, 0.0, 0.0, /* camera target location */
0.0, 1.0, 0.0 /* UP vector */
);

state->color[0] = 0.0; state->color[1] = 0.0; state->color[2] = 1.0;

engineTranslate( -1.5, 0.0, 0.0 );
engineScale( 0.02, 0.02, 0.02 );

glUseProgram( state->prog->prog_name );
idx = glGetUniformLocation( state->prog->prog_name, "matWorldview" );
glUniformMatrix4fv( idx, 1, GL_FALSE, state->world );
idx = glGetUniformLocation( state->prog->prog_name, "matProjection" );
glUniformMatrix4fv( idx, 1, GL_FALSE, state->proj );
idx = glGetUniformLocation( state->prog->prog_name, "vecColor" );
glUniform3fv( idx, 1, state->color );

glBindBuffer( GL_ARRAY_BUFFER, state->vbo );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, state->ebo );
idx = glGetAttribLocation( state->prog->prog_name, "attrPosition" );
glEnableVertexAttribArray( idx );
glVertexAttribPointer( idx,
3,
GL_FLOAT,
GL_FALSE,
0,
( GLvoid * )0 );
glDrawElements( state->draw_mode, 12, GL_UNSIGNED_INT, 0 );
glDisableVertexAttribArray( idx );

/*
* Second draw - right side, red squares
*/
engineLookAt( 0.0, 0.0, 5.0, /* camera position */
0.0, 0.0, 0.0, /* camera target location */
0.0, 1.0, 0.0 /* UP vector */
);

state->color[0] = 1.0; state->color[1] = 0.0; state->color[2] = 0.0;

engineTranslate( 1.5, 0.0, 0.0 );
engineScale( 0.02, 0.02, 0.02 );

glUseProgram( state->prog->prog_name );
idx = glGetUniformLocation( state->prog->prog_name, "matWorldview" );
glUniformMatrix4fv( idx, 1, GL_FALSE, state->world );
idx = glGetUniformLocation( state->prog->prog_name, "matProjection" );
glUniformMatrix4fv( idx, 1, GL_FALSE, state->proj );
idx = glGetUniformLocation( state->prog->prog_name, "vecColor" );
glUniform3fv( idx, 1, state->color );

glBindBuffer( GL_ARRAY_BUFFER, state->vbo );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, state->ebo );
idx = glGetAttribLocation( state->prog->prog_name, "attrPosition" );
glEnableVertexAttribArray( idx );
glVertexAttribPointer( idx,
3,
GL_FLOAT,
GL_FALSE,
3 * sizeof( float ),
( GLvoid * )0 );
glDrawElements( state->draw_mode, 12, GL_UNSIGNED_INT, 0 );
glDisableVertexAttribArray( idx );

SDL_GL_SwapBuffers();
}

Only one attribute per vertex is defined: the position (3 floats). The same geometry (the exact same VBO to be precise) is drawn twice, with different arguments given to the 'stride' argument of glVertexAttribPointer:
glVertexAttribPointer( idx, 3, GL_FLOAT, GL_FALSE, 0, ( GLvoid * )0 );
and
glVertexAttribPointer( idx, 3, GL_FLOAT, GL_FALSE, 3 * sizeof( float ), ( GLvoid * )0 );
respectively. The attributes are tightly packed in the array yet the vertex attribute pointers act as if they are equivalent.

My question is: why ?

Share this post


Link to post
Share on other sites
Advertisement
The stride defines the bytes between the start of one vertex and the start of another. Zero is a special case number for when you are lazy and don't feel like calculating the byte offset yourself. You are correct that you will get the same result when using 0 and 3*sizeof(float) in your case.

When you say '0' all it means is "figure out the width of this vertex and use that for the stride, because the data is tightly packed".

Share this post


Link to post
Share on other sites
I was afraid of that. I was actually hoping for end-to-start measurements and the possibility to specify negative values for 'stride'. Anyway, thank you for your quick reply.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!