feat(BgfxRenderer): Add layer sorting for correct sprite Z-order
Sprites are now sorted by layer (ascending) then by textureId for batching. Batches are flushed when layer OR texture changes to maintain correct draw order. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
613283d75c
commit
5795bbb37e
@ -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<uint32_t>(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<SpriteInstance> 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<uint16_t>(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;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user