After experimenting some more, I found that using the hardware VBO buffers allowed me to get rid of the garbage collection. The trick is to use the GL11 extensions (which might not be supported on all hardware). Because this is a tutorial forum, I will share my code here.
Note 1: The gl11.glDrawArrays() call does not use VBO buffers, and that is why you need to convert the call to use gl11.glDrawElements.
Here is how I initialized the different buffers:
Using java Syntax Highlighting
protected void initVertexBuffers()
{
int one = 65536;
int particleScale = 2 * one;
int particleVertices[] =
{
// FRONT
-particleScale, particleScale, 0, particleScale, particleScale, 0, -particleScale, -particleScale, 0,
particleScale, -particleScale, 0
};
int aircraftScale = 32 * one;
int aircraftVertices[] =
{
// FRONT
-aircraftScale, aircraftScale, 0, aircraftScale, aircraftScale, 0, -aircraftScale, -aircraftScale, 0,
aircraftScale, -aircraftScale, 0
};
int texCoords[] =
{
// FRONT
0, one, one, one, 0, 0, one, 0
};
int normals[] =
{
0, 0, -one, 0, 0, -one, 0, 0, -one, 0, 0, -one
};
short indices[] =
{
0, 2, 1, 2, 3, 1
};
// Buffers to be passed to gl*Pointer() functions must be direct, i.e.,
// they must be placed on the native heap where the garbage collector
// cannot move them.
//
// Buffers with multi-byte data types (e.g., short, int, float) must
// have their byte order set to native order
ByteBuffer vbb = ByteBuffer.allocateDirect(particleVertices.length * 4);
vbb.order(ByteOrder.nativeOrder());
vertexBuffer = vbb.asIntBuffer();
vertexBuffer.put(particleVertices);
vertexBuffer.position(0);
// ...
ByteBuffer vbb2 = ByteBuffer.allocateDirect(aircraftVertices.length * 4);
vbb2.order(ByteOrder.nativeOrder());
vertex2Buffer = vbb2.asIntBuffer();
vertex2Buffer.put(aircraftVertices);
vertex2Buffer.position(0);
// ...
ByteBuffer tbb = ByteBuffer.allocateDirect(texCoords.length * 4);
tbb.order(ByteOrder.nativeOrder());
textureBuffer = tbb.asIntBuffer();
textureBuffer.put(texCoords);
textureBuffer.position(0);
// ...
ByteBuffer nbb = ByteBuffer.allocateDirect(normals.length * 4);
nbb.order(ByteOrder.nativeOrder());
normalBuffer = nbb.asIntBuffer();
normalBuffer.put(normals);
normalBuffer.position(0);
ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2);
ibb.order(ByteOrder.nativeOrder());
indexBuffer = ibb.asShortBuffer();
indexBuffer.put(indices);
indexBuffer.position(0);
}
Parsed in 0.040 seconds, using
GeSHi 1.0.8.4
Maybe not optimal and it also requires that your bitmaps point "down". This means that if you want to draw an aircraft going up and use no rotatation, the image should have the aircraft point down (or rotated 180 degrees)
After initializing the vertices and index, I copy them to the hardware buffers in my graphics card. They are very small, so there should be ample space to copy them.
Using java Syntax Highlighting
public void generateHardwareBuffers(GL10 gl)
{
if (particleVertBufferIndex == 0)
{
if (gl instanceof GL11)
{
GL11 gl11 = (GL11) gl;
int[] buffer = new int[1];
// Allocate and fill the vertex buffer.
gl11.glGenBuffers(1, buffer, 0);
particleVertBufferIndex = buffer[0];
gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, particleVertBufferIndex);
final int vertexSize = vertexBuffer.capacity() * 4;
gl11.glBufferData(GL11.GL_ARRAY_BUFFER, vertexSize, vertexBuffer, GL11.GL_STATIC_DRAW);
int error = gl11.glGetError();
if (error != GL10.GL_NO_ERROR)
{
Log.e("AirDefender", "Generate vertex buffer GLError: " + error);
}
// Allocate and fill the vertex buffer.
gl11.glGenBuffers(1, buffer, 0);
aircraftVertBufferIndex = buffer[0];
gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, aircraftVertBufferIndex);
final int vertex2Size = vertex2Buffer.capacity() * 4;
gl11.glBufferData(GL11.GL_ARRAY_BUFFER, vertex2Size, vertex2Buffer, GL11.GL_STATIC_DRAW);
error = gl11.glGetError();
if (error != GL10.GL_NO_ERROR)
{
Log.e("AirDefender", "Generate vertex buffer GLError: " + error);
}
// Allocate and fill the texture coordinate buffer.
gl11.glGenBuffers(1, buffer, 0);
textureCoordBufferIndex = buffer[0];
gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, textureCoordBufferIndex);
final int texCoordSize = textureBuffer.capacity() * 4;
gl11.glBufferData(GL11.GL_ARRAY_BUFFER, texCoordSize, textureBuffer, GL11.GL_STATIC_DRAW);
error = gl11.glGetError();
if (error != GL10.GL_NO_ERROR)
{
Log.e("AirDefender", "Generate texture buffer GLError: " + error);
}
// Unbind the array buffer.
gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, 0);
// Allocate and fill the index buffer.
gl11.glGenBuffers(1, buffer, 0);
indexBufferIndex = buffer[0];
gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, indexBufferIndex);
// A char is 2 bytes.
final int indexSize = indexBuffer.capacity() * 2;
gl11.glBufferData(GL11.GL_ELEMENT_ARRAY_BUFFER, indexSize, indexBuffer, GL11.GL_STATIC_DRAW);
error = gl11.glGetError();
if (error != GL10.GL_NO_ERROR)
{
Log.e("AirDefender", "Generate index buffer GLError: " + error);
}
// Unbind the element array buffer.
gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, 0);
}
}
}
Parsed in 0.041 seconds, using
GeSHi 1.0.8.4
To use the buffers simply refer to the HW buffers:
Using java Syntax Highlighting
@Override
public void draw(GL10 gl)
{
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glPushMatrix();
gl.glTranslatef(x, y, 0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureName);
gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
GL11 gl11 = (GL11) gl;
// draw using hardware buffers
gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, SimpleGLRenderer.aircraftVertBufferIndex);
gl11.glVertexPointer(3, GL10.GL_FIXED, 0, 0);
gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, SimpleGLRenderer.textureCoordBufferIndex);
gl11.glTexCoordPointer(2, GL11.GL_FIXED, 0, 0);
gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, SimpleGLRenderer.indexBufferIndex);
gl11.glDrawElements(GL11.GL_TRIANGLES, 6, GL11.GL_UNSIGNED_SHORT, 0);
gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, 0);
gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, 0);
gl.glPopMatrix();
engine.draw(gl);
}
Parsed in 0.035 seconds, using
GeSHi 1.0.8.4
After stopping the program, don't forget to release the buffers, otherwise your graphics card might run out of space (I am not sure if this is true, since I do not know if the Graphics card would replace the buffers ?)
Using java Syntax Highlighting
public void freeHardwareBuffers(GL10 gl)
{
if (particleVertBufferIndex != 0)
{
if (gl instanceof GL11)
{
GL11 gl11 = (GL11) gl;
int[] buffer = new int[1];
buffer[0] = particleVertBufferIndex;
gl11.glDeleteBuffers(1, buffer, 0);
buffer[0] = aircraftVertBufferIndex;
gl11.glDeleteBuffers(1, buffer, 0);
buffer[0] = textureCoordBufferIndex;
gl11.glDeleteBuffers(1, buffer, 0);
buffer[0] = indexBufferIndex;
gl11.glDeleteBuffers(1, buffer, 0);
}
forgetHardwareBuffers();
}
}
private void forgetHardwareBuffers()
{
particleVertBufferIndex = 0;
aircraftVertBufferIndex = 0;
textureCoordBufferIndex = 0;
indexBufferIndex = 0;
}
Parsed in 0.037 seconds, using
GeSHi 1.0.8.4
Note 2: I borrowed a lot of code from the
SpriteMethodTest program which uses different methods to show performance