fix: GPUDriven batch 实例连续性——多实体共享 mesh 时实例数组错乱

实例数组按实体序收集([实体A的mesh][实体B的mesh]),而 GPU 端
batch 语义要求同一 mesh 的实例连续(firstInstance 基址 +
gl_InstanceIndex 直查 SSBO)。多实体共享 Model 后 mesh i 的各实例
分散在数组各处,batch.first+i 落到别的 mesh 的变换上——第二颗
背包的几何全画到第一颗的相邻 mesh 位置(碎裂/缺失/近看缺块)。

修:剔除期实例先归入各自 batch(ViewScratch 持有 per-batch 实例
列表),拼接时按 batch 扁平化为连续区间,batch.first = 扁平化基址。
单实体路径行为不变(每 mesh 单实例天然连续),容量跨帧复用。
This commit is contained in:
2026-09-24 16:23:47 +08:00
parent 25a365fce7
commit fa9681aa41
2 changed files with 29 additions and 18 deletions
@@ -68,16 +68,19 @@ namespace Engine {
// ---- 剔除中间量(每帧 clear 复用,拼接进 m_Frame 后保留容量)----
struct ViewScratch {
CullResult result;
std::vector<glm::mat4> worlds;
std::vector<glm::mat4> prevWorlds;
// 每 batch 自己的实例列表(按 mesh 分组)。GPU 端 batch 语义 =
// firstInstance + 连续区间,实体序收集不满足(多实体共享 mesh
// 时实例分散各处),扁平化成连续数组推迟到 appendView
std::vector<std::vector<glm::mat4>> batchWorlds;
std::vector<std::vector<glm::mat4>> batchPrevWorlds;
std::unordered_map<Mesh*, u32> lookup;
void Clear()
{
result.batches.clear();
result.instanceCount = 0;
worlds.clear();
prevWorlds.clear();
batchWorlds.clear();
batchPrevWorlds.clear();
lookup.clear();
}
};