StarArawn / bevy_ecs_tilemap

A tilemap rendering crate for bevy which is more ECS friendly.
MIT License
905 stars 195 forks source link

Add possibility to use one or more TextureAtlases as a tilemap texture. #316

Open st0rmbtw opened 1 year ago

st0rmbtw commented 1 year ago

Add possibility to use one or more texture atlases as a tilemap texture.

A possible solution is to add an option in TilemapTexture with the name like TextureAtlases that will take a vector of texture atlas handles.

Something like this:

let tiles: Vec<Handle<TextureAtlas>> = vec![
    tile_assets.stone.clone(),
    tile_assets.grass.clone(),
    tile_assets.dirt.clone()
];

...
texture: TilemapTexture::TextureAtlases(tiles)
...

Also, I think it would be nice to have a convenient way to select textures. Currently, we can select textures by global index that is not very convenient with many texture atlases in the future. I think it would be nice to select a texture atlas by index, and then select a texture by relative index to this atlas.

Like this:

...
texture: TileTexture(0, 12) // The first argument is the texture atlas index, and the second argument is the relative tile texture index
...
StarArawn commented 1 year ago

Solutions for doing this (Atlas feature):

Multiple Bindings Solution:

  1. Each texture atlas would need it's own separate shader binding.
  2. Considering the above limitation properly accessing X atlas would be challenging and require branching in the shader decreasing performance.
  3. TileTexture would need to be updated to include a u16 handle to the correct texture atlas.

Multiple Chunk Solution:

  1. Chunk mesher would detect differences in textures and create a chunk per tilemap.
  2. Slower performance as draw calls would increase for each atlas texture.
  3. TileTexture would need to be updated to include a u16 handle to the correct texture atlas.

Solutions for doing this (Array Texture):

Multiple Chunk Solution:

Array packing Solution (Ideal? No performance loss):

  1. TextureArrayCache would be updated to pack multiple atlases into a single array texture.
  2. TileTexture would need to be updated to include a u16 handle to the correct texture atlas.
  3. Chunk mesher would translate texture_atlas_index and texture_index into a single texture_index.
  4. Would hit array texture limits(2048 or 4096) faster.
frederickjjoubert commented 1 year ago

I would also really appreciate this enhancement; I am working with lots of tiles across multiple tilemaps, and having to add them all into one file and keep track of the index of each tile in this massive file has become a very big pain point.

Vixeliz commented 1 year ago

In the meantime till this is implemented wouldn’t it be possible to dynamically build a texture atlas at run time? Could probably make a function then that assigns each texture pushed into that texture atlas mapped from name to id.

frederickjjoubert commented 1 year ago

In the meantime till this is implemented wouldn’t it be possible to dynamically build a texture atlas at run time? Could probably make a function then that assigns each texture pushed into that texture atlas mapped from name to id.

An example of how to do that would be greatly appreciated.

Vixeliz commented 1 year ago

In the meantime till this is implemented wouldn’t it be possible to dynamically build a texture atlas at run time? Could probably make a function then that assigns each texture pushed into that texture atlas mapped from name to id.

An example of how to do that would be greatly appreciated.

Check out bevy’s dynamic tileset builder or if you’re interested in a library to help with some tileset stuff check out the awesome bevy_tileset library. It generates a texture atlas and lets you define animated, autotiling, and standard tiles through Ron files