1
votes

I'm using the glDrawElements call with VBOs to render my scene. The scene is a cloth with vertices and texture coordinates - in this example, I'm rendering a flag.

With my scene, the vertices are dynamic which means I need to write to a VBO every frame. Much of my processing is done on the GPU using CUDA, so I'm constantly mapping CPU memory to GPU memory. The texture coordinates, on the other hand, are static. In order to render with glDrawElements (as I understand it), I should interleave the texture coordinates in the vertices VBO and then simply call glTexCoordPointer() and glEnableClientState(). This is not optimal because then I'd need to draw all the texture coordinates with me when I do CPU<-->GPU memory mapping.

Is there a way to arrange my vbo such that I can update the vertex data in the vbo without touching the texture data in the vbo? Below is my code for rendering - I have three arrays currently filled: an index array, a vertex array, and a texture array.

In the code below, the indexVbo has been mapped to the index array and vbo has been mapped to the vertex array. I now need to incorporate textures. Any insight or suggestions would be much appreciated.

glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, flagTexId);

glPushMatrix();
    glColor3f(1.0, 1.0, 1.0);

    glVertexPointer(4, GL_FLOAT, 0, 0);
    glTexCoordPointer(2, GL_FLOAT, 0, 0);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVbo);
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    // Render flag mesh
    glDrawElements(GL_TRIANGLES, numTriangles * 3, GL_UNSIGNED_INT, 0);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    glDisableClientState(GL_VERTEX_ARRAY); 
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glPopMatrix(); 

glDisable(GL_TEXTURE_2D);
1

1 Answers

3
votes

You can keep separate VBOs for both vertex attributes. That way, you can even mark the tex-coord one as static, and the other one as dynamic.

Whether this is actually faster depends on many factors: driver, memory setup, etc. The benefits of having some part of the data in static memory might outweight the benefits of having the whole vertex on a cache line (when you interleave). But then again, it might not. Benchmark on your target system(s) to be sure.

IMO, a good argument for splitting the attributes into different VBOs is that it is the most "natural" representation of your data. But I guess that depends on personal taste and whether you let that influence your programming :-)

By the way, it seems like you have a small bug: you need to bind the correct VBO before a gl*Pointer call (also, your offsets and strides are not correct if you're using a single VBO for your vertices). That's also how you bind separate VBOs: just select the right one before the gl*Pointer call:

glBindBuffer(GL_ARRAY_BUFFER, vbo_vertex);
glVertexPointer(4, GL_FLOAT, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, vbo_texcoord);
glTexCoordPointer(2, GL_FLOAT, 0, 0);