5
\$\begingroup\$

I'm currently working on a renderer for Tiled's .tmx maps. Among one of the features there is that layers and tilesets are independent, so that a layer can use any tile set on any tile. It's not so much of a problem, though, as my Image type is basically:

data Image = Image { imageTexture :: TextureObject
                   , imageMinTex2 :: TexCoord2
                   , imageMaxTex2 :: TexCoord2
                   } deriving (Show, Eq)

Drawing an image is therefore

  1. Bind texture
  2. Render Quad using min/max texture coords

A quite simple implementation. However, if every Tile is an Image, in my implementation, then this would mean that on every tile, a texture is bound. Often times it will be the same, and quite often just a few tiles have entirely different texture.

So how expensive is a texture binding in OpenGL? Do I have to sort the Tiles by texture or will the OpenGL drivers do that for me?

\$\endgroup\$

1 Answer 1

8
\$\begingroup\$

Guessing a bit here but from the little information you gave it sounds like you are thinking of something like the following

for each layer
    for each tile
        bind texture
        draw quad
    end
end

If that is the case this is the most inefficient way of drawing, and you will not get any good performance out of this because you end up with a draw call per tile rather than a draw call per tileset.

You should batch your draw calls, a simple implementation could be something like the following

// draw
for each layer
    for each tile
        add to render queue
    end
 end

 // flush
 sort render queue items by texture
 let buffers be index/vertex buffers on the GPU with a fixed size.

 for each item in render queue
    if item texture is not bound or buffers are full
        bind texture
        draw buffers
    end

    append item to buffers
 end
\$\endgroup\$
6
  • \$\begingroup\$ I'm not so familiar with the vertex buffers on OpenGL, are Display lists so much slower? \$\endgroup\$
    – Lanbo
    Commented Mar 24, 2013 at 12:30
  • \$\begingroup\$ Vertex buffers are exactly what the name implies. You're storing coordinate data in the GPU device memory and using indices on the client side (CPU) to tell the GPU where to draw from. Think of it like a big array. Sections 0-11 store the 3d point data for a square. 12-21 store the same for a triangle. Instead of having to push client data to the GPU in a draw call to avoid the slowness of transferring to the GPU on a per draw basis you just tell the GPU to draw the data in the vbo starting at say index 12 with a length of 9 to tell the GPU to draw the stored triangle. \$\endgroup\$
    – user6484
    Commented Mar 24, 2013 at 13:19
  • \$\begingroup\$ See also en.m.wikipedia.org/wiki/Vertex_Buffer_Object#section_1 \$\endgroup\$
    – user6484
    Commented Mar 24, 2013 at 13:24
  • \$\begingroup\$ And opengl.org/discussion_boards/showthread.php/… \$\endgroup\$
    – user6484
    Commented Mar 24, 2013 at 13:25
  • \$\begingroup\$ Display Lists haven't been a relevant part of OpenGL for many many years, immediate mode is a thing of the past. You should be looking at newer versions of the specification. Link to an AS3 based implementation of sprite batching, the API is different than GL as its an abstraction on top of it but its easy to port, not feature complete however as i wasn't quite willing to dedicate that much time to a SO answer. stackoverflow.com/questions/7758760/…. \$\endgroup\$ Commented Mar 24, 2013 at 17:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .