Correct VBO usage?

I’m trying to add VBO’s to my program to compare them against apple’s VAO stuff, but am not sure if I’m doing this right…the program is an object oriented data flow language for sound and graphics, and has a wrapper set for OpenGL, plus some specific workhorse objects: these include things like [pix_texture] for texturing and shape and [vertex_draw] for loading vertex arrays and calling glDrawArrays()…

…anyway, in the following snippet I’m trying to cache the buffers:

    if (m_vao){
	  glEnableClientState( GL_VERTEX_ARRAY );
	  if ( !m_nVBOVertices ){
		glGenBuffersARB( 1, &m_nVBOVertices );
        glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_nVBOVertices);
	    glBufferDataARB( GL_ARRAY_BUFFER_ARB, state->VertexArraySize*4*sizeof(float),
						state->VertexArray, GL_DYNAMIC_DRAW_ARB );
		glVertexPointer( 4, GL_FLOAT,0, (char*) NULL);
	  }else{
	  glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_nVBOVertices);
	  glVertexPointer( 4, GL_FLOAT,0, (char*) NULL);
	  }
     }
    
    if(m_color && (state->ColorArray != NULL || state->HaveColorArray == 0) ){
        glEnableClientState(GL_COLOR_ARRAY);
		if ( !m_nVBOColor ){
			glGenBuffersARB( 1, &m_nVBOColor );
			glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_nVBOColor);
			glBufferDataARB( GL_ARRAY_BUFFER_ARB, state->VertexArraySize*4*sizeof(float),
						state->ColorArray, GL_DYNAMIC_DRAW_ARB );
			glColorPointer(4,GL_FLOAT,0,(char*) NULL);
		}else{
			glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_nVBOColor);
			glColorPointer(4,GL_FLOAT,0,(char*) NULL);
		}
	}else{
        glDisableClientState(GL_COLOR_ARRAY);
	}
	if ( state->HaveTexCoordArray || state->TexCoordArray != NULL ){
		if ( !m_nVBOTexCoords ){
			glGenBuffersARB( 1, &m_nVBOTexCoords );
			glBindBufferARB( GL_ARRAY_BUFFER_ARB, m_nVBOTexCoords);
			glBufferDataARB( GL_ARRAY_BUFFER_ARB, state->VertexArraySize*2*sizeof(float),
						state->TexCoordArray, GL_DYNAMIC_DRAW_ARB );
			glTexCoordPointer(2, GL_FLOAT, 0, (char *) NULL);
		}else{
			glBindBufferARB( GL_ARRAY_BUFFER_ARB, m_nVBOTexCoords);
			glTexCoordPointer(2, GL_FLOAT, 0, (char *) NULL);
		}
	}

    if(state->HaveNormalArray || state->NormalArray!=NULL){
		glEnableClientState(GL_NORMAL_ARRAY);
		if ( !m_nVBONormals ){
			glGenBuffersARB( 1, &m_nVBONormals );
			glBindBufferARB( GL_ARRAY_BUFFER_ARB, m_nVBONormals );
			glBufferDataARB( GL_ARRAY_BUFFER_ARB, state->VertexArraySize*sizeof(float),
						state->NormalArray, GL_DYNAMIC_DRAW_ARB );
			glNormalPointer(GL_FLOAT,0, (char *) NULL);
		}else{
			glBindBufferARB( GL_ARRAY_BUFFER_ARB, m_nVBONormals );
			glNormalPointer(GL_FLOAT,0, (char *) NULL);
		}
    }
 
    glDrawArrays(m_drawType,0,size);
    glDisableClientState(GL_VERTEX_ARRAY);
    if(m_color)glDisableClientState(GL_COLOR_ARRAY);
    
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);

…does anything here look wildly wrong? It seems to work ok on my 10.3.5 alBook, but apparently linux users get a slowdown…

thanx
james

Unless i’ve misread your code, you are creating a VBO for each vertex data component ???

You should have
1 VBO ‘GL_ARRAY_BUFFER_ARB’ for ALL the vertex data (vertex, normals, uv, color etc…)
1 VBO ‘GL_ELEMENT_ARRAY_BUFFER_ARB’ for the the indices.

also uses GL_STATIC_DRAW_ARB instead of GL_DYNAMIC_DRAW_ARB. If you are modifying the vertices a lot, uses GL_STREAM_DRAW_ARB instead.

Finally, the latest framework doesn’t have the GL_ARB_vertex_buffer_object interface (it’s even not on the Apple web site), so beware.

The drivers export the ARB_vertex_buffer_object extension string; that (as always) is the final say on what is supported.

Yes, Apple hasn’t updated their headers yet. That’s no barrier to using this extension.

I’ve only experimented with VBO’s briefly, but from my understanding of the spec, creating separate buffers per attribute is perfectly valid. However you only want to do this in the case where you know that some attributes are static and some are dynamic, i.e. caching texture coords in VRAM while streaming positions and normals. If you’ve marked everything dynamic you’re probably better off with one large buffer.

Also in my experiments I was unable to get VBO to perform as well as VAR; the 9600 driver seemed to stall a lot mapping the buffer (more so than with double buffered VARs syncing on a fence.) This was under 10.3.4, I don’t know if it is better in 10.3.5 or how it compares with Windows/Linux.

Also, unrelated but you might try 4ub instead of floats for colors if it doesn’t totally ruin your processing logic. I get better performance with 4ub.

yes, i’ve just tried glew and it appears to works fine.

VBO works great, seems faster than the APPLE_VAR on the various tests i’ve done, although i had some trouble when using it with ARB_vertex_program - crash in glDrawRangeElements, I need to check that.

Btw, there is a bug in the latest glew code when trying to use glDrawRangeElements with GL_VERSION=1.1

I am using DYNAMIC instead of STATIC…the above seems to work ok so far, but I just wanted to make sure it was sane because I hadn’t seen other examples doing it this way…

…the program is very open-ended, so there are no guarantees that one array will exist or change anymore than another: does this mean I should go with the STREAM option?

It depends if you are updating manually the vertex data.

Typically, you should never modify more than once the vertex data (use a vertex program instead).

If the vertex is initialized once and never touched afterwards, use STATIC_DRAW_ARB.

If you have to modify the vertices quite often use STREAM_DRAW_ARB or DYNAMIC_DRAW_ARB (you need to profile, it really depends of the application). If most case STREAM_DRAW_ARB is sufficient.

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.