I have a game where each "tile" of the terrain is a triangle (Settlers 2). Those are placed next to each other and in way creating an infinite world (right/bottom jumps back to left/top). There is a 3D component (each triangle point has a height) but that gets translated into an Y-position offset, so everything can be considered 2D.

Everything (texture coords, screen coords, color (white<->black, FoW)) is put into VBOs already and usually does not change (FoW may disappear which updates the color VBO, but rarely)

When drawing I iterate over the visible tiles (currently in view) and collect "runs" of tiles with the same texture. After that I do:

  • Bind current texture
  • Draw current run (offset into VBOs + num of same textured tiles)
  • Repeat until all runs are drawn

To reduce the number of texture switches I wanted to create a texture atlas. But the problem: Some textures are animated (texture animation so all tiles use the same frame of the animation at any given time) and those animations may be different.

To give some numbers:

  • ~30 textures, pretty small (~30-60px each)
  • 8 are animated, rest static
  • animation length is 4-8 frames
  • animation frame time is constant

How would I best go with those animations?

  • Put all static textures into 1 texture, animated ones into separate ones?
  • Unroll animations so I have ~8 textures (possibly 24 if I have 8 frame and 6 frame animations) where each texture is 1 frame (so static textures are copied into those unmodified)
  • Repeat all textures into 1 texture and do some U-coordinate shifting in a shader (not used ATM, but will add soon) -> again possible waste
  • Some shader magic?

Using OpenGL 2.1, C++.

Visualization of 3 textures: Triangles cut out from squares in any position (in fact only 6 are possible: Top to bottom, top to middle, top to middle rotated by 135° and their mirrored counterparts). Shown is 1 of 2 triangles per square, the other one is mirrored horizontally. All tiles may have different sizes

enter image description here


1 Answer 1


I'd recommend doing this in your shader.

  1. Arrange your atlas so that subsequent frames of each animation are arranged consecutively in a row. No duplication of non-animated tiles required.

  2. Use 3D UVW coordinates for each tile vertex. The first two values point to the corners of the start frame of the animation in the atlas (the only frame, for non-animated tiles) and the third coordinate is the length of the animation (1 for non-animated tiles)

  3. Pass a uniform to your shader representing the current frame number (increasing from 0 to a common multiple of all your animation lengths before wrapping back around)

  4. In your vertex shader, take this frame number modulo your animation length read from the UVW coordinates. Use this result to offset the horizontal coordinate by that many tile steps, and pass the resulting 2D UV coordinates down the pipe to your fragment shader.

  • \$\begingroup\$ "by that many tile steps": My tiles are triangles. In practice I have a square each and 2 triangles cut from that (some rotated, all not using the whole square) which means I probably need an additional number per texture for the "tile step"/width. Or abuse the W coordinate (pack 2 uint16 into a uint32, but UVW are floats...) \$\endgroup\$
    – Flamefire
    Dec 9, 2018 at 16:22
  • \$\begingroup\$ Nah, just use sequential squares for triangles belonging to the same sequence. The other triangle in each square can be a frame from another animated sequence, or a non-animated tile. \$\endgroup\$
    – DMGregory
    Dec 9, 2018 at 16:25
  • \$\begingroup\$ I don't understand your comment. My squares are different sizes, so my tile step/width is different per texture (I added an image above showing 1 of 2 triangles) \$\endgroup\$
    – Flamefire
    Dec 9, 2018 at 17:33
  • 1
    \$\begingroup\$ Why do you use tiles of different resolutions? Standardizing this will make a lot of your work simpler. \$\endgroup\$
    – DMGregory
    Dec 9, 2018 at 17:35
  • \$\begingroup\$ The game is a mod using the original textures. There are 3(4) different sizes: settlers2.net/2015/09/tex5-lbm-greenland-debug-texture We don't use any image library (e.g. for resizing/rotating) and I hesitate to add one just for this. \$\endgroup\$
    – Flamefire
    Dec 9, 2018 at 17:40

You must log in to answer this question.

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