Add support for Array Textures

Issue #1111 resolved
Alex Szpakowski
created an issue

Array Textures are kind of like regular 2D texture atlases / sprite sheets, but they have a few differences:

  • Each "layer" or "slice" in an Array Texture uses the texture wrap mode at its edges. This means the extremely common texture atlas issue of "gaps in tiles" doesn't exist when using an Array Texture, because the issue is caused by the GPU getting some pixel data from past-the-edge of the Quad in the texture atlas.

  • Each layer/slice in an Array Texture has its own mipmap levels. With texture atlases, different sprites inside an atlas can bleed together once you start using mipmapping, but this isn't a problem with Array Textures.

  • Every layer/slice in an Array Texture has the same dimensions. This means you'd still have to use Quads (and possibly texture atlases inside each slice) with an Array Texture if you wanted to have several different sprites of varying sizes with one.

  • You can typically have a lot more layers in an Array Texture than you would normally be able to fit in a texture atlas.

  • They use 3D texture coordinates instead of 2D coordinates – the third coordinate indicates the slice/layer of the Array Texture. LÖVE's Quad, SpriteBatch, and ParticleSystem APIs would probably have to be modified to be able to specify the Array Texture layer/slice.

  • They use a different sampler type (sampler2DArray instead of sampler2D) in GLSL. In desktop OpenGL, they either require GLSL 1.40 or the GL_EXT_texture_array extension. In OpenGL ES, they require GLSL ES 3.00 – which is a problem because LÖVE only supports GLSL ES 1.00 and GLSL 1.20, currently.

  • Graphics cards that don't support OpenGL 3 or OpenGL ES 3 don't support Array Textures. On desktop OpenGL 2, LÖVE could fall back to using 3D textures internally (although mipmaps wouldn't be able to be supported). On OpenGL ES 2, LÖVE would probably have to fall back to a regular texture atlas internally.

textures.jpg

Comments (18)

  1. Landon Manning

    Would it be completely out of the question to bump LOVE's desktop GL requirement to OpenGL 3.3 in the next release? I don't exactly expect a 0.11.0 release any time soon, so perhaps by the time that happens the mobile market will be breaching the ES 3.0 majority?

  2. Alex Szpakowski reporter

    perhaps by the time that happens the mobile market will be breaching the ES 3.0 majority?

    There might be a GLES 3.0 majority, but there'd need to be far more than a majority to consider dropping GLES 2.0 support in my opinion. Currently it's at about 45-55% (depending on demographics): http://hwstats.unity3d.com/mobile/gpu.html

    Since I probably wouldn't be dropping GLES 2.0 support, there'd be no reason to drop desktop GL2 support as it's basically a superset of ES 2.0.

  3. Alex Szpakowski reporter

    There's different Canvas formats and MRT / multi-canvas rendering, which LÖVE already exposes if the system is GLES3-capable.

    Mesh geometry instancing is one feature not in LÖVE yet. And there's Uniform Buffer Objects but they are mainly only useful if you have various different shaders that should share the same uniform data. GLSL ES 3.00 (the GLES 3 shading language) also has a few features like integer bitwise operations. 3D textures are also in GLES3, which might be useful for a color grading lookup table.

  4. Landon Manning

    Mesh instancing and UBOs would definitely be nice.

    There is a significant portion of people who don't upgrade their phones every year or two (waddup), and tablets probably get upgraded even less. I doubt those people would be terribly interested in playing the latest 2D games so maybe 90% is a tad high of a threshold when considering several fairly useful features that could be exposed to developers. 75% is probably too low, though.

  5. Alex Szpakowski reporter

    Just a note in case I forget again: several compressed texture file formats (DDS, KTX, etc.) can natively store texture arrays. LÖVE will have to be updated to recognize this.

  6. Alex Szpakowski reporter

    Also, rendering to a specific layer of an Array Texture might be useful. The current inheritance / hierarchy of Texture -> [Image, Canvas] will probably need some work or redoing.

    Related: having mipmap support for Canvases (including rendering to a specific mipmap layer, and autogenerating mipmaps) could be useful as well.

  7. Jason McKesson

    It should be noted that using array textures, where each array layer is a separate sprite, is very wasteful and can run into hardware limitations easily.

    Consider 32x32 sprites. A 4096x4096 texture can store 16K 32x32 sprites. If you use a 1-pixel gutter between them (to avoid bleeding when rotating), then it can store over 15,000 sprites.

    Using this as a guide, we can see that the maximum number of array layers supported by any hardware is 16K. And that's only with a few oddball implementations. The standard AMD limit for modern hardware is 8K, and the standard NVIDIA limit is only 2K. OpenGL's base minimum from GL 4.5 is 2K, as is ES 3.0's minimum is only 256.

    Array textures are a good thing for sprite sheets, and I support their implementation. But they shouldn't be used in a one-sprite-per-layer kind of way. They should instead be used as a way to allow the use of the same sprite sheet for more groups of sprites. That way, you're not changing textures for each different kind of sprite. Or indeed, you may never be changing textures.

  8. Alex Szpakowski reporter

    each array layer is a separate sprite, is very wasteful

    There's no waste, you just have to be aware of limits.

    Array textures are a good thing for sprite sheets, and I support their implementation. But they shouldn't be used in a one-sprite-per-layer kind of way.

    The average LOVE game uses far fewer than 2k sprites, and likely far fewer than 256. 32x32 is also pretty small for a sprite size - as the size increases, fewer sprites can be put into a texture atlas whereas a constant number can be put into an Array image. For most LOVE games, just using array images (assuming the GL version / hardware supports them) will be completely fine, and users can use texture atlases on top of that or just by themselves if they want.

  9. Jason McKesson

    I guess it's ultimately a matter of how you expose array textures to the user. Would Quads be able to select a sprite from a particular array layer of a texture? Will SpriteBatch be updated to support selecting a region of an array layer?

    Or will array textures be its own sort of thing, separate from existing functionality and only drawable on a per-layer basis?

    Because the initial description of the feature leans heavily towards the latter. I'm basically saying that the feature should not be exposed in a way that limits it to drawing an entire layer.

  10. Alex Szpakowski reporter

    I guess it's ultimately a matter of how you expose array textures to the user. Would Quads be able to select a sprite from a particular array layer of a texture? Will SpriteBatch be updated to support selecting a region of an array layer?

    That's the plan, yes.

  11. Alex Szpakowski reporter

    Array textures can be easily drawn without a shader (resolves issue #1111).

    Added love.graphics.drawLayer(texture, layerindex, …). ‘texture’ must be an array texture. Added SpriteBatch:add/setLayer.

    Added Quad:get/setLayer. This applies to array textures that are drawn without specifying an explicit layer index in the draw call.

    Added love.graphics.newQuad variants which have layer arguments.

    → <<cset 7927fc9b473d>>

  12. Log in to comment