0

In my application, I'm having to draw multiple elements with OpenGL, some are Triangles and others are Line Strips. I'm putting my vertices into multiple float[] and my indices into multiple short[] whenever I am to draw a new shape. I also have to create a new FloatBuffer, ShortBuffer and ByteBuffer for each new array in order to make it work.

How could I more efficiently draw the multiple elements? I was thinking of putting all of the vertices into a single float[] and creating a new short[] for each element to remove excess arrays, but is it possible to use one FloatBuffer, ShortBuffer and put all of the arrays into a single ByteBuffer such as this:

float[] vertices = { -3, -3, -3, 2, 3, 0, 2, -1, 0, 0, 5, 2, 3, 1 };
short[] indItemA = { 0, 1, 2, 0, 2, 3 };
short[] indItemB = { 4, 5, 6 };

FloatBuffer fBuff;
ShortBuffer sBuff;

ByteBuffer bBuff = ByteBuffer.allocateDirect(vertices.length * 4);
fbBuff.order(ByteOrder.nativeOrder());

fBuff = bBuff.asFloatBuffer();
fBuff.put(vertices);
fBuff.position(0);

sBuff = bBuff.asShortBuffer();
sBuff.put(indItemA);
sBuff.position(0);

sBuff.put(indItemB);
sBuff.position(0);

1 Answer 1

1

glBufferData sends the data from the buffer to the graphics card's memory. You can do whatever you want with the ByteBuffer after that call and it wont effect the data already sent.

Therefore if your aim is to reduce the number of ByteBuffers you create, you could just create one large ByteBuffer that is used for everything. Just reset the pointer of the buffer, write the data, send it to the graphics card and repeat.

// Do this once
ByteBuffer bBuff = ByteBuffer.allocateDirect( someBigNumber );
bBuff.order(ByteOrder.nativeOrder());
FloatBuffer fBuff = bBuff.asFloatBuffer();
ShortBuffer sBuff = bBuff.asFloatBuffer();

// Do this for each shape
fBuff.position(0);
fBuff.put(vertices);
fBuff.position(0);

glBindBuffer( GL_ARRAY_BUFFER, vertexbuffer );
glBufferData( GL_ARRAY_BUFFER, vertices.length * 4, fBuff, GL_STATIC_DRAW );

sBuff.position( 0 );
sBuff.put( indices );
sBuff.position( 0 );

glBindBuffer( GL_ARRAY_BUFFER, indexbuffer );
glBufferData( GL_ARRAY_BUFFER, indices.length * 2, sBuff, GL_STATIC_DRAW );

If your vertex and index data is static, you could just put the vertex data for every shape into one buffer object and all the index data into another then use the offset parameter of glVertexPointer and glIndexPointer to specify where in the buffer object the data begins.

It sounds like you generate custom shapes at runtime though, so you could just re-use the ByteBuffer and store each shape in a separate buffer object like the sample above.

Sign up to request clarification or add additional context in comments.

4 Comments

It works perfectly! I had to add in GLES11. before each of the glBindBuffer and glBufferData and the calls to GL_ARRAY_BUFFER and GL_STATIC_DRAW but other than that, everything works exactly as I wanted it to. Just curious though, is this the most efficient way to preserve memory and CPU/GPU usage?
The "most efficient" way to do something depends greatly on what are trying to do. For example, if you were creating a ByteBuffer every frame to upload data to the graphics card then this is going to be more efficient. The only way to truly know though is to do benchmarks with different methods for your specific purpose.
My purpose is to draw a large array or vertices and indices initially, but won't change at all throughout the life of the activity.
Okay so just load all of your vertex and index data into large buffer objects at the start of the application. DO NOT upload this data every time you want to draw a shape. Instead, you use the offset parameter of glVertexPointer to specify where in the buffer your shape data is. This method is very efficient.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.