PDA

View Full Version : interleaved VBOs



cyrfer
04-07-2009, 03:20 PM
Hi,
I'm sorry to ask another VBO question, but I've not found an example to do what I want. I currently have a vertex format that holds various vertex attributes in a single array. I'd like to know how to write the correct enable/disable client code, and what are the correct arguments to pass to functions like glVertexPointer and glTexCoordPointer. The pointer functions seem like the hardest part with the interleaved vertex format, so I assume that's what I'm messing up. It's funny that the same code that is messed up for interleaved arrays works fine if I only have vertex positions and no other attributes. Anyway, here is what I'm trying:

void drawVBO( const GMesh& mesh )
{
// bind VBO for the vertex array
{
size_t vert_size = CalculateVertexLength( &(mesh._vertex_decl._elements[0]), mesh._vertex_decl._elements.size() );
unsigned int accum_length = 0;
unsigned int accum_texture_unit = 0;
glBindBufferARB(GL_ARRAY_BUFFER_ARB, mesh._vbo.id); // for vertex coordinates

// call enableclientstate and vertex attribute pointer functions
for( unsigned int index_sem=0; index_sem<mesh._vertex_decl._elements.size(); ++index_sem )
{
unsigned int semantic = mesh._vertex_decl._elements[index_sem];
switch( semantic )
{
case GVES_POSITION_3:
{
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer(3, GL_FLOAT, vert_size, BUFFER_OFFSET(accum_length));
accum_length += CalculateVertexElementLength(semantic)*sizeof(floa t);
} break;

case GVES_TEXTURE_COORDINATE:
{
//glClientActiveTextureARB( GL_TEXTURE0_ARB + accum_texture_unit );
//// TODO: problem here if a crazy Mesh defines more texture units than are available
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glTexCoordPointer(2, GL_FLOAT, vert_size, BUFFER_OFFSET(accum_length));
accum_length += CalculateVertexElementLength(semantic)*sizeof(floa t);
} break;
}
}
}

// bind IBO for index array AND draw
for( unsigned int index_sub=0; index_sub<mesh._submesh_array.size(); ++index_sub)
{
GSubmesh* sub = mesh._submesh_array[index_sub];
setMaterialState( sub->_material );

glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, sub->_ibo.id); // for indices

// draw
glDrawElements( GL_TRIANGLES, sub->_index_array_length, GL_UNSIGNED_SHORT, 0);
}
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); // unbind

// call disableclientstate
for( unsigned int index_sem=0; index_sem<mesh._vertex_decl._elements.size(); ++index_sem )
{
unsigned int semantic = mesh._vertex_decl._elements[index_sem];
switch( semantic )
{
case GVES_POSITION_3:
{
glDisableClientState( GL_VERTEX_ARRAY );
} break;

case GVES_TEXTURE_COORDINATE:
{
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
} break;
}
}

glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); // unbind
}


In case its important, here's how I created the BOs:

void createVBO( GMesh& mesh )
{
size_t vert_size = CalculateVertexLength( &(mesh._vertex_decl._elements[0]), mesh._vertex_decl._elements.size() );
size_t num_verts = mesh._vertex_array_length / vert_size;

// the vertex array
{
mesh._vbo.size_bytes = num_verts * vert_size * sizeof(float); // 4 bytes for each floating point value
glGenBuffersARB( 1, &(mesh._vbo.id) );

glBindBufferARB( GL_ARRAY_BUFFER_ARB, mesh._vbo.id ); // vertex data
glBufferDataARB( GL_ARRAY_BUFFER_ARB, mesh._vbo.size_bytes, NULL, GL_STATIC_DRAW_ARB ); // static, draw only
glBufferSubDataARB( GL_ARRAY_BUFFER_ARB, 0, mesh._vbo.size_bytes, mesh._vertex_array );
}

// the index arrays
for( unsigned int index_sub=0; index_sub<mesh._submesh_array.size(); ++index_sub )
{
GSubmesh* sub = mesh._submesh_array[index_sub];

sub->_ibo.size_bytes = sub->_index_array_length * sizeof(unsigned short); // Mesh structure is currently hard coded to store using 'ushort16' (2 bytes)
glGenBuffersARB( 1, &(sub->_ibo.id) );

glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, sub->_ibo.id ); // index data
glBufferDataARB( GL_ELEMENT_ARRAY_BUFFER_ARB, sub->_ibo.size_bytes, NULL, GL_STATIC_DRAW_ARB );
glBufferSubDataARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 0, sub->_ibo.size_bytes, sub->_index_array );
}
}

cyrfer
04-09-2009, 11:52 AM
Since this post is receiving no response, maybe I used the wrong language when I said 'interleaved'. I don't know the right word, but the vertex array that I'm trying to make looks like;
px0, py0, pz0, tu0, tv0, px1, py1, pz1, tu1, tv1, px2, py2, pz2, tu2, tv2.

When the array looks like this:
px0, py0, pz0, px1, py1, pz1, px2, py2, pz2

I have no problems to see the geometry. Of course, this avoids the use of the pointer functions other than the position function in the code I showed above. So I doubt I'm using the offset parameter correctly when I try to use the texture pointer function.

Also, I just read that 3.1 deprecates these pointer functions. What should I use instead?

Many thanks.

James A.
04-09-2009, 07:31 PM
I haven't had a chance to look at your code fully, but to answer your last question I THINK you are supposed to be using the glVertexAttribPointer function to pass your data to the shaders

see here:
http://www.lighthouse3d.com/opengl/glsl/index.php?oglattribute

Although I am not 100% sure (I am currently tying to update all my old openGL code to not use the deprecated functions). Maybe one of the more experienced posters can tell me if I am wrong.

cyrfer
04-10-2009, 02:34 PM
James: Thanks for the tip about the vertexattribpointer function.

I'm trying to do what this guy is doing in his demo,
2.3. Interleaved arrays alternative (class CTest3)
http://www.ozone3d.net/tutorials/opengl_vbo_p2.php

Ilian Dinev
04-10-2009, 05:10 PM
Search for the func "ilDrawVBO".

http://www.ultranos.com/OpenIL/src/OpenIL.cpp

I keep the vertex-pointer enabled all the time, and for all other attributes I use glVertexAttribPointer(). I should actually not be using glVertexPointer(), instead replace it with glVertexAttribPointer().