Advertisement Jump to content
Sign in to follow this  

OpenGl ES: multiple VBO/IBO pairs

This topic is 689 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello my fellow gamedevers,


I now feel much better about my "engine" (its my first `serious` work in OpenGl, but it is still a newbie stuff of course). So after I have successfully implemented VBO packed with vertices and colors and IBO, now I want to make it more robust and scalable. 

I have a class called GlRenderBuffer which contains two buffers: 

FloatBuffer for vertex data

ShortBuffer for indices

I do also have objects I call primitives. What I actually do is drawing a floor plan. So my primitives are walls, doors, etc. Each primitive can write itself into vertices and indices buffers. 

So the design is pretty much straightforward: Load the scene from file, deserialize primitives, put them into buffers and render. 

The problem: when I use single GlRenderBuffer everything works (all primitives are drawn), but if I use several such buffers only the first one is drawn. 


GlRenderBuffer class

public class GlRenderBuffer {
    public static final int SIZE_OF_FLOAT = Float.SIZE/Byte.SIZE;
    public static final int SIZE_OF_SHORT = Short.SIZE/Byte.SIZE;

    public static final int COORDS_PER_VERTEX = 3;
    public static final int COLORS_PER_VERTEX = 4; // RGB + A
    public static final int INDICES_BUFFER_SIZE_FACTOR = 4; // we allocate indices buffer 4
    private static final int BUFFERS_COUNT = 1;
    private static final int STRIDE = (COORDS_PER_VERTEX + COLORS_PER_VERTEX) * SIZE_OF_FLOAT;

    private final FloatBuffer mVerticesBuffer;
    private final ShortBuffer mIndicesBuffer;

    private final int[] mVerticesBufferId = new int[BUFFERS_COUNT];
    private final int[] mIndicesBufferId = new int[BUFFERS_COUNT];

    public GlRenderBuffer(int verticesNum) {
        // device hardware's native byte order
        mVerticesBuffer = ByteBuffer.allocateDirect(verticesNum *
                (COORDS_PER_VERTEX + COLORS_PER_VERTEX)* SIZE_OF_FLOAT).order(ByteOrder.nativeOrder()).asFloatBuffer();

        mIndicesBuffer = ByteBuffer.allocateDirect(verticesNum *
                INDICES_BUFFER_SIZE_FACTOR * SIZE_OF_SHORT).order(ByteOrder.nativeOrder()).asShortBuffer();


    public boolean put(IFloorPlanPrimitive primitive) {
        int neededVertexDataSize = primitive.getVerticesDataSize(); // in bytes
        int neededIndexDataSize = primitive.getIndicesDataSize();   // this too

        // Ensure there is enough space for new primitive
        final boolean verticesBufferHasEnoughSpace = mVerticesBuffer.remaining() >= neededVertexDataSize / SIZE_OF_FLOAT;
        final boolean indicesBufferHasEnoughSpace = mIndicesBuffer.remaining() >= neededIndexDataSize / SIZE_OF_SHORT;
        if (!verticesBufferHasEnoughSpace || !indicesBufferHasEnoughSpace) {
            return false;

        return true;

    public void copyToGpu(FloatBuffer vertices) {
        GLES20.glGenBuffers(BUFFERS_COUNT, mVerticesBufferId, 0);

        // Copy vertices data into GPU memory
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVerticesBufferId[0]);
        // TODO: Should be vertices.limit() instead of vertices.capacity()
        GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertices.capacity() * SIZE_OF_FLOAT, vertices, GLES20.GL_DYNAMIC_DRAW);

        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);

    public void copyToGpu(ShortBuffer indices) {
        GLES20.glGenBuffers(BUFFERS_COUNT, mIndicesBufferId, 0);

        // Copy vertices data into GPU memory
        GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesBufferId[0]);
        // TODO: Should be vertices.limit() instead of vertices.capacity()
        GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, indices.capacity() * SIZE_OF_SHORT, indices, GLES20.GL_STATIC_DRAW);

        GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);

    public void updateSingleObject(IFloorPlanPrimitive primitive) {
        // offset in bytes
        int primitiveBufferOffset = primitive.getVertexBufferPosition();
        int vertexOffset = primitiveBufferOffset * SIZE_OF_FLOAT;

        int previousBufferPosition = mVerticesBuffer.position();
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVerticesBufferId[0]);
        GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER, vertexOffset, primitive.getVerticesDataSize(), mVerticesBuffer);
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);

    public void render(float[] mvpMatrix) {
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVerticesBufferId[0]);

        int positionAttributeHandle = GLES20.glGetAttribLocation(AppSettings.oglProgram, ShaderHelper.POSITION_ATTRIBUTE);
        GLES20.glVertexAttribPointer(positionAttributeHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false,
                STRIDE, 0);

        int colorAttributeHandle = GLES20.glGetAttribLocation(AppSettings.oglProgram, ShaderHelper.COLOR_ATTRIBUTE);
        GLES20.glVertexAttribPointer(colorAttributeHandle, COLORS_PER_VERTEX, GLES20.GL_FLOAT, false,

        GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesBufferId[0]);

        // get handle to shape's transformation matrix
        int mvpMatrixHandle = GLES20.glGetUniformLocation(AppSettings.oglProgram, ShaderHelper.MVP_MATRIX);
        // Pass the projection and view transformation to the shader
        GLES20.glUniformMatrix4fv(mvpMatrixHandle, 1, false, mvpMatrix, 0);

                GLES20.GL_TRIANGLES, mIndicesBuffer.position(),
                GLES20.GL_UNSIGNED_SHORT, 0);

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

    public void allocateGpuBuffers() {
        int vertexPos = mVerticesBuffer.position();
        int indexPos = mIndicesBuffer.position();

        // Reset positions of buffers for consuming in GL




    public void deallocateGpuBuffers() {
        if (mVerticesBufferId[0] > 0) {
            GLES20.glDeleteBuffers(mVerticesBufferId.length, mVerticesBufferId, 0);
            mVerticesBufferId[0] = 0;
        if (mIndicesBufferId[0] > 0) {
             GLES20.glDeleteBuffers(mIndicesBufferId.length, mIndicesBufferId, 0);
            mIndicesBufferId[0] = 0;

    public void refreshGpuBuffers() {

    public void finalize() {

    public void clear() {
        // TODO: more actions to come

This code is used in Renderer class of GlSurfaceView. Since when single buffer is used this works, I suppose GlRenderBuffer class I wrote is incorrect. If Renderer's code is also desired please let me know and I'll add it.


Thank you in advance,



Share this post

Link to post
Share on other sites

more to add glbindbuffer(GL_ARRAY_BUFFER or GL_ELEMENT_ARRAY_BUFFER


you dont unbind them somewhere or post acutal rendering code.

Edited by WiredCat

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using, you agree to our community Guidelines, Terms of Use, and Privacy Policy. is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!