Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I am trying to write efficient code to render a tile based map in android. I load for each tile the corresponding bitmap (just one time) and then create the according tiles. I have designed a class to do this:

public class VertexQuad {

private float[] mCoordArr;
private float[] mColArr;
private float[] mTexCoordArr;
private int mTextureName;
private static short mCounter = 0;
private short mIndex;

As you can see, each tile has it's x,y location, a color array, texture coordinates and a texture name. Now, I want to render all my created tiles.

To reduce the openGL api calls (I read somewhere that the state changes are costly and therefore I want to keep them to a minimum), I first want to hand ALL the coordinate-arrays, color-arrays and texture-coordinates over to OpenGL. After that I run two for loops. The first one iterates over the textures and binds the texture. The second for loop iterates over all Tiles and puts all tiles with the corresponding texture into an IndexBuffer. After the second for loop has finished, I call

gl.gl_drawElements()

whith the corresponding index buffer, to draw all tiles with the texture associated. For the next texture I do the same again.

Now I run into some problems: Allocating and filling the FloatBuffers at the start of each rendering cycle costs very much time. I just run a test, where i wanted to put 400 coordinates into a FloatBuffer which took me about 200ms.

My questions now are:

  • Is there a better way, handling the coordinate and color structures?
  • How is this correctly done, this is obviously not the optimal way? ;)

thanks in advance, regards Markus

share|improve this question
    
OpenGL ES 1.x or OpenGL ES 2.x? –  Ellis Feb 26 '11 at 14:50
    
OpenGL ES1 1.x - sorry i forgot to mention that –  Maecky Feb 26 '11 at 15:01
    
200ms for 400 sets of floating point coordinates seems like an incredibly long time. What do your data structures look like? What do the inner loops performing the copy look like? Are you using any of the glGet* API calls? –  moonshadow Feb 28 '11 at 21:27

3 Answers 3

I know this post is somewhat old but I've recently had to tackle this situation myself and came up with what I see as a pretty efficient solution.

I wrote a tumblr post about how I managed to do this. I'm sure it's not the best way but it ended up being lightning fast.

It's similar to your approach except all tiles are split into rows which are calculated and filled with vertices at the beginning of the world. In the end, only a handful of drawcalls are done to the visible rows and from each row only a handful of vertices are used based on the viewport position.

Feel free to check out the more thorough explanation: http://mortalparody.tumblr.com/post/4725205385/tilemapping-on-android-in-opengl-es

share|improve this answer

In OpenGL ES 1.x, you can use several methods:

  • glDrawArrays
  • glDrawElements: TRIANGLES or TRIANGLES_STRIP (denormalized triangles)
  • VBO
  • glDrawTexfOES (you need to verify that you have this extension)

glDrawTexfOES is the faster method to draw efficiently quads but it is not available on old phones. VBO is efficient for static quads. If you use VBO with FloatBuffers, there is a bug on Android 2.2 and 2.1 devices which causes slowness. Use the libgdx.so, to transfert data into VBO for performance. If you use NDK, there is no performance issues.

Your question is not OpenGL ES related but OpenGL Java Wrapping issue.

Ps: in efficient opengl es 1.x engines, you have a tool to batch drawcalls. It is recommanded to limit your drawcalls to 50.

Ps 2: the FloatBuffers is very slow on android devices < 2.3. The libgdx has rewritten this part to speed its engines. You should look this issue.

share|improve this answer
    
thanks for your answer, i knew this already - the problem is, that filling the buffer in each cycle needs so much time ;( –  Maecky Feb 26 '11 at 15:02
    
You can use libgdx to resolve this issue. –  Ellis Feb 26 '11 at 15:12
    
TRIANGLES_STRIP (denormalized triangles) ??? What do you mean by that Ellis? I heard about Degenerated Triangles in regard to Trinagles_strip. Any thing like denormalized triangles too? –  Ayyappa Jul 25 '11 at 9:56

You don't refill buffers every frame unless it's totally necessary, because this has a great performance penalty (copying data from CPU to GPU is no trivial task).

Create a VBO for each texture type, and fill it once (on map load, or whenever you want) with the data of those tiles. Then, iterate your tile texture array, set the active texture and then draw the corresponding VBO.

Keep in mind that this solution is very inflexible (in case your map changes dinamically), but for static tile maps is the best solution.

share|improve this answer
    
Yeah, that's my problem - i want to scroll the map and therefore i run into the described problems. I haven't figured out yet, how to efficiently solve the problem. –  Maecky Feb 26 '11 at 21:18
    
Divide your map in square sections, and try to fit a quadtree in there. –  r2d2rigo Feb 26 '11 at 22:47

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.