feat: migrate quilter rendering to Bevy TilemapChunk
Replaces the CPU pixel-baking quilter system (QuiltCache, TerrainSprite, pixel_buffers) with Bevy's native TilemapChunk GPU-index-lookup API. Architecture: - TilemapChunk entities replace TerrainSprite entities per (chunk, z, layer) - Tileset PNG stacked vertically as texture_2d_array (11 rows: 6 floor + 5 fixture) - populate_chunk_tiles reads TileMap HashMap directly; no ECS FloorTile entities - Chunk spawn deferred to apply_terrain_blobs (after TileMap data exists) - Dirty key system triggers repopulate on occlusion/camera-z changes Bug fixes: - populate_chunk_tiles: add chunk_pos offset to world tile lookups (was always (0,0)) - spawn_tilemap_chunks: offset Transform by -TILE_SIZE/2 (tile-centre vs bottom-left) - spawn_tilemap_chunks: AlphaMode2d::Blend (was Opaque, blocking DF fade) - update_tilemap_chunk_visibility: actually mutate Visibility (was read-only) - handle_tile_occlusion_updates: mark dirty keys inline (was double-reading events) - TilemapChunkSpawner: deduplicate pending queue and guard stale registry Performance: - ~115K FloorTile ECS entities eliminated - GPU memory: O(tile_data) instead of O(CHUNK_TILES² × z_levels × pixel_bytes) - Z-scroll: only TilemapChunkTileData repopulates (no entity re-spawn) - Benchmarks via TilemapBenchmark resource (F9 to report)
This commit is contained in:
@@ -8,9 +8,9 @@ use crate::{
|
||||
config::TileRegistry,
|
||||
constants::{SEED, TILE_SIZE},
|
||||
world::{
|
||||
tiles::{ChunkData, FloorTileData, TileMap, TerrainSpriteState, CurrentWorldSpriteState},
|
||||
tiles::{ChunkData, FloorTileData, TileMap},
|
||||
ChunkForrestryEvent, ChunkTerrainEvent, FloorTilePrefab, TileOcclusionEvent, CHUNK_SIZE,
|
||||
Z_ABOVE, Z_BELOW, ChunkMap, ChunkOwner,
|
||||
Z_ABOVE, Z_BELOW, ChunkMap,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -265,7 +265,6 @@ fn generate_terrain_blob(chunk_pos: IVec2) -> TerrainBlob {
|
||||
/// Fast - just reads events and spawns tasks.
|
||||
pub fn spawn_terrain_tasks(
|
||||
mut events: MessageReader<ChunkTerrainEvent>,
|
||||
mut cwss: ResMut<CurrentWorldSpriteState>,
|
||||
blob_storage: Res<TerrainBlobStorage>,
|
||||
) {
|
||||
let start = Instant::now();
|
||||
@@ -287,7 +286,6 @@ pub fn spawn_terrain_tasks(
|
||||
}).detach();
|
||||
}
|
||||
|
||||
cwss.state = TerrainSpriteState::WaitingForRender;
|
||||
println!("{} terrain tasks spawned in {:.2?}", count, start.elapsed());
|
||||
}
|
||||
|
||||
@@ -300,6 +298,7 @@ pub fn apply_terrain_blobs(
|
||||
mut chunk_map: ResMut<ChunkMap>,
|
||||
mut forrestry_event_writer: MessageWriter<ChunkForrestryEvent>,
|
||||
mut occlusion_event_writer: MessageWriter<TileOcclusionEvent>,
|
||||
mut spawner: ResMut<crate::world::tiles::TilemapChunkSpawner>,
|
||||
) {
|
||||
let start = Instant::now();
|
||||
let mut applied_count = 0;
|
||||
@@ -317,16 +316,7 @@ pub fn apply_terrain_blobs(
|
||||
.collect();
|
||||
|
||||
tilemap.chunks.insert(blob.chunk_pos, blob.chunk_data);
|
||||
|
||||
for (_position, prefab) in blob.tile_spawns {
|
||||
let entity = prefab.spawn(&mut commands);
|
||||
commands.entity(entity).insert(ChunkOwner(blob.chunk_pos));
|
||||
chunk_map
|
||||
.chunk_entity_index
|
||||
.entry(blob.chunk_pos)
|
||||
.or_default()
|
||||
.push(entity);
|
||||
}
|
||||
spawner.queue_chunk(blob.chunk_pos);
|
||||
|
||||
for pos in new_positions {
|
||||
occlusion_event_writer.write(TileOcclusionEvent { tile_position: pos });
|
||||
|
||||
Reference in New Issue
Block a user