Is this a good method to render sprites (textured quads) or is there a faster or better way?
Example use:
renderer.beginTextureRendering();
for(Enemy enemy : enemies)
{
renderer.renderTexture(enemy.getX(), enemy.getY(), 0.5f, 0.5f, 0, 0, 1, 1, 1, 1, 1, 1);
}
renderer.endTextureRendering(cameraTransform, gameTexture);
Some members of the Renderer class:
private int vertexBuffer;
private FloatBuffer vertexBatch;
private static final int VERTEX_BATCH_SIZE = 300;
Core render methods of Renderer class:
// Call this before rendering a few sprites.
public void beginTextureRendering()
{
vertexBatch.rewind();
}
public void renderTexture(float xPosition, float yPosition, float xSize, float ySize,
float srcXPosition, float srcYPosition, float srcXSize,
float srcYSize, float red, float green, float blue, float alpha)
{
if(vertexBatch.position() - 48 >= VERTEX_BATCH_SIZE)
{
Log.e(TAG, "Vertex batch too small !");
}
else
{
vertexBatch.put(xPosition);
vertexBatch.put(yPosition);
vertexBatch.put(srcXPosition);
vertexBatch.put(srcYPosition + srcYSize);
vertexBatch.put(red);
vertexBatch.put(green);
vertexBatch.put(blue);
vertexBatch.put(alpha);
vertexBatch.put(xPosition + xSize);
vertexBatch.put(yPosition);
vertexBatch.put(srcXPosition + srcXSize);
vertexBatch.put(srcYPosition + srcYSize);
vertexBatch.put(red);
vertexBatch.put(green);
vertexBatch.put(blue);
vertexBatch.put(alpha);
vertexBatch.put(xPosition + xSize);
vertexBatch.put(yPosition + ySize);
vertexBatch.put(srcXPosition + srcXSize);
vertexBatch.put(srcYPosition);
vertexBatch.put(red);
vertexBatch.put(green);
vertexBatch.put(blue);
vertexBatch.put(alpha);
vertexBatch.put(xPosition);
vertexBatch.put(yPosition);
vertexBatch.put(srcXPosition);
vertexBatch.put(srcYPosition + srcYSize);
vertexBatch.put(red);
vertexBatch.put(green);
vertexBatch.put(blue);
vertexBatch.put(alpha);
vertexBatch.put(xPosition + xSize);
vertexBatch.put(yPosition + ySize);
vertexBatch.put(srcXPosition + srcXSize);
vertexBatch.put(srcYPosition);
vertexBatch.put(red);
vertexBatch.put(green);
vertexBatch.put(blue);
vertexBatch.put(alpha);
vertexBatch.put(xPosition);
vertexBatch.put(yPosition + ySize);
vertexBatch.put(srcXPosition);
vertexBatch.put(srcYPosition);
vertexBatch.put(red);
vertexBatch.put(green);
vertexBatch.put(blue);
vertexBatch.put(alpha);
}
}
// Call this if you finished drawing a few sprites.
public void endTextureRendering(float[] transform, Texture texture)
{
int count = vertexBatch.position();
if(count > 0)
{
vertexBatch.rewind();
GLES20.glUseProgram(textureProgram);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBuffer);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, count * (Float.SIZE / 8), vertexBatch, GLES20.GL_STATIC_DRAW);
GLES20.glEnableVertexAttribArray(textureProgramPositionLocation);
GLES20.glVertexAttribPointer(textureProgramPositionLocation, 2, GLES20.GL_FLOAT, false, 8 * (Float.SIZE / 8), 0 * (Float.SIZE / 8));
GLES20.glEnableVertexAttribArray(textureProgramUVLocation);
GLES20.glVertexAttribPointer(textureProgramUVLocation, 2, GLES20.GL_FLOAT, false, 8 * (Float.SIZE / 8), 2 * (Float.SIZE / 8));
GLES20.glEnableVertexAttribArray(textureProgramColorLocation);
GLES20.glVertexAttribPointer(textureProgramColorLocation, 4, GLES20.GL_FLOAT, false, 8 * (Float.SIZE / 8), 4 * (Float.SIZE / 8));
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture.getHandle());
GLES20.glUniform1i(textureProgramTextureUnitLocation, 0);
GLES20.glUniformMatrix4fv(textureProgramTransformLocation, 1, false, transform, 0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, count / 8);
GLES20.glDisableVertexAttribArray(textureProgramPositionLocation);
GLES20.glDisableVertexAttribArray(textureProgramUVLocation);
GLES20.glDisableVertexAttribArray(textureProgramColorLocation);
}
}
Fragment shader:
uniform sampler2D un_TextureUnit;
varying vec2 fr_UV;
varying vec4 fr_Color;
void main()
{
gl_FragColor = vec4(texture2D(un_TextureUnit, fr_UV)) * fr_Color;
}
Vertex shader:
uniform mat4 un_Transform;
attribute vec2 ve_Position;
attribute vec2 ve_UV;
attribute vec4 ve_Color;
varying vec2 fr_UV;
varying vec4 fr_Color;
void main()
{
fr_UV = ve_UV;
fr_Color = ve_Color;
gl_Position = un_Transform * vec4(ve_Position.xy, 0, 1);
}