我正在渲染一片草地。每个草叶 xz 位置都存储在实例化的顶点缓冲区中。
我使用halton序列生成这个位置,因此该缓冲区内的位置是“随机的”。后来,我决定使用块作为 Z 曲线来生成它们,以提高数据局部性并准备实施截锥体剔除。 即使尚未实施视锥体剔除,性能也会有所提高,但仅限于查看特定方向时(而相反方向实际上会变得更糟)。
为了确保我不会发疯,我回到了使用 Halton 序列生成点并对它们进行排序的旧分支。这是结果:
排序方式 | 看看-x | 看x | 看-z | 看z |
---|---|---|---|---|
无 | ~25 FPS | ~25 FPS | ~25 FPS | ~25 FPS |
|
~15 FPS | ~30 FPS | ~20 FPS | ~20 FPS |
|
~30 FPS | ~15 FPS | ~20 FPS | ~20 FPS |
|
~20 FPS | ~20 FPS | ~15 FPS | ~30 FPS |
|
~20 FPS | ~20 FPS | ~30 FPS | ~15 FPS |
它在英特尔显卡(mesa)上运行。还值得一提的是我正在使用 Vulkan 内存分配器。
回到 Z 曲线实现并添加平截头体剔除,以便仅将平截头体内的叶片位置写入缓冲区,但没有任何改变。此外,调整刀片“解决”了问题,回到稳定(但较低)的 FPS。
我还想澄清,我没有根据视图矩阵的值进行任何条件工作(除非启用截头体剔除),而只是进行通常的矩阵/向量乘法。
什么可能导致这一切?
这是早期深度测试(以及其他此类测试,例如 hier-z)的标准怪癖。如果您从前到后绘制,以便首先绘制距离相机最近的草,那么可以证明后面的叶片被遮挡并可以尽早扔掉。
大多数 GPU 也有一些隐藏表面去除的标准形式,不依赖于前后渲染,但这些方案都有其怪癖,并且不如早期深度测试可靠。
我建议对草批次进行粗略排序,而不是对单个刀片进行排序 - 这种排序不会占用 CPU 资源。然而,你不太可能需要完全利用每一帧,除非你的相机在跳来跳去,这会有所帮助。