diff --git a/modules/BgfxRenderer/Passes/SpritePass.cpp b/modules/BgfxRenderer/Passes/SpritePass.cpp index 2e96c40..c58bbaf 100644 --- a/modules/BgfxRenderer/Passes/SpritePass.cpp +++ b/modules/BgfxRenderer/Passes/SpritePass.cpp @@ -101,32 +101,40 @@ void SpritePass::execute(const FramePacket& frame, rhi::IRHIDevice& device, rhi: state.depthWrite = false; cmd.setState(state); - // Build sorted indices by textureId for batching + // Build sorted indices by layer (primary) and textureId (secondary) for batching m_sortedIndices.clear(); m_sortedIndices.reserve(frame.spriteCount); for (size_t i = 0; i < frame.spriteCount; ++i) { m_sortedIndices.push_back(static_cast(i)); } - // Sort by textureId (stable sort to preserve layer order within same texture) - std::stable_sort(m_sortedIndices.begin(), m_sortedIndices.end(), + // Sort by layer first (ascending: layer 0 = background, rendered first) + // Then by textureId to batch sprites on the same layer + std::sort(m_sortedIndices.begin(), m_sortedIndices.end(), [&frame](uint32_t a, uint32_t b) { - return frame.sprites[a].textureId < frame.sprites[b].textureId; + const SpriteInstance& sa = frame.sprites[a]; + const SpriteInstance& sb = frame.sprites[b]; + if (sa.layer != sb.layer) { + return sa.layer < sb.layer; + } + return sa.textureId < sb.textureId; }); - // Process sprites in batches by texture + // Process sprites in batches by layer and texture + // Flush batch when layer OR texture changes to maintain correct draw order std::vector batchData; batchData.reserve(MAX_SPRITES_PER_BATCH); uint16_t currentTextureId = UINT16_MAX; + float currentLayer = -1e9f; // Use a value that won't match any real layer rhi::TextureHandle currentTexture; for (uint32_t idx : m_sortedIndices) { const SpriteInstance& sprite = frame.sprites[idx]; uint16_t texId = static_cast(sprite.textureId); - // Check if texture changed - if (texId != currentTextureId) { + // Check if texture OR layer changed (must flush to maintain layer order) + if (texId != currentTextureId || sprite.layer != currentLayer) { // Flush previous batch if (!batchData.empty()) { device.updateBuffer(m_instanceBuffer, batchData.data(), @@ -135,8 +143,9 @@ void SpritePass::execute(const FramePacket& frame, rhi::IRHIDevice& device, rhi: batchData.clear(); } - // Update current texture + // Update current state currentTextureId = texId; + currentLayer = sprite.layer; if (texId == 0 || !m_resourceCache) { // Use default/active texture for textureId=0 currentTexture = m_activeTexture.isValid() ? m_activeTexture : m_defaultTexture;