# Faster way to draw dynamic meshes in OpenGL ES

I'm writing a 3D game which is going to inlcude some dynamic meshes.

For now, my code looks like this :

private float[] mVertices;
private FloatBuffer mVertexBuffer;

public void onDrawFrame(GL10 gl) {
// first clear the screen of any previous drawing
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

// initialize the matrix
gl.glMatrixMode(GL10.GL_MODELVIEW);

// update the vertex data
for (int vtx = 0; vtx < mVtxCount; ++vtx){
// fill in the x, y and z components of the vertex position
mVertices[vtx * 3] = x;
mVertices[(vtx * 3) + 1] = y;
mVertices[(vtx * 3) + 2] = z;
}

// update the vertex buffer
mVertexBuffer.clear();
mVertexBuffer.put(mVertices);
mVertexBuffer.position(0);

// render the vertex buffer
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer);
gl.glDrawElements(GL10.GL_LINES, mIndices.length,
GL10.GL_UNSIGNED_BYTE, mIndexBuffer);
}


Here is an easy sample as the index buffer does not change so I only update the vertex position, normal and texture coordinates.

Of course I understand dynamic mesh will always be slower to render than static mesh, but I wonder if the method I use is good or if there is a faster / better way to do this .

I think before you go pointing fingers, you make sure that this is in fact the problem. It might very well be, but before you invest a lot of time an effort in the number solutions below, try profiling your code. You should be looking for large CPU usage areas. If improving that improves performance, then awesome, mission accomplished. Some devices ship without FPUs, so the performance with floats are very poor.

You might try different graphics rendering modes to make sure that you are in fact limited by vertex transfer rates, i.e. using the same number of vertices in a static mesh is dramatically faster. If it isn't, then your model(s) are too detailed and filling a buffer faster won't fix anything -- your GPU simply can't handle the geometry + any other stuff you have enabled. You can turn down/off many of the effects like fog/lighting (lighting is especially expensive if your GPU does not have TnL and your CPU does not have a FPU).

As for actual methods of improving performance that take a while to implement, you have a few options:

1. Use GL_FIXED instead of GL_FLOAT types. If your CPU does a lot of calculations for the GPU, then fixed point will likely be a fast case for it. GL_FIXED is the same size as GL_FLOAT conventionally, so this will not help if data transfer rates are the bottleneck.

2. Use GL_SHORT instead of GL_FLOAT types. This will cut transfer bandwidth in half. Since most people don't do integer coordinates for their world's smallest unit, you typically have to constrain the absolute size of your world to a size like 128x128. From there, you can use OpenGL's matrix stack to scale the coordinates. For example, I use GL_SHORT for texture coordinates where 1024 = 1.0. I then use glScale(1/1024, 1/1024, 1.0) so that when I tell OpenGL the texture coordinates (512, 1024), it will treat them as (0.5, 1.0). It might seem a bit backwards, but generally the GPU can do these transformations for essentially free, and thus all you've done is reduce the amount of data to represent the same position.

3. Check if "vertex buffer objects" extension is supported and use them if they are. There are a lot of tutorials available for a wide variety of languages on how to use them. Essentially, the optimization is that you can have the GPU transfer/draw from one buffer while the CPU writes to another. Because of this "double buffered" approach, less time in spent waiting in the CPU, which can make the graphics appear to render faster. Some implementations have high-speed memory for vertex data and can map these areas into your program. In that way, you can potentially do zero-copy filling of buffers. Consider what OpenGL does normally: You fill an array with floats, you call glDraw[Arrays/Elements], then by the time it returns, you can delete the whole array. That means either a) the GPU must draw it right there and now, or b) the driver must copy the vertex data for later use. Either way is generally sub-optimal, because you don't have a way of saying to the driver "I'm just going to refill this same array with the same size next time, and I won't be changing it immediately so you don't need to copy it." Using vertex buffer objects, you can do this.

4. Check platform notes. Some platforms actually have "fast paths", things that their driver specifically or can optimize. Others might prefer vertex data in a certain format, or elements on a certain alignment, or vertices multiples of a certain size, etc.