考虑具有以下属性的2D模拟:
- 实体填充屏幕并四处移动,有时会死亡并消失
- 每个实体都有一组独特的、按程序生成的纹理作为其"精灵"。鉴于程序性,纹理是在运行时生成的。任何两个实体具有相同纹理的几率都极低
- 屏幕上最多同时存在5000个实体(在任何给定的播放过程中,实体的数量都没有上限——当它们死亡时,内存就会释放)
- 精灵应该前后绘制,以便前景实体与它们"后面"的实体重叠
- sim与OpenGL 3.0兼容
- GL_MAX_TEXTURE_SIZE为2048,与较旧的移动设备兼容
- 纹理具有透明度,因此z缓冲区不适用于绘制顺序
如果我没有错的话,有两种解决这个问题的通用方法:
- 在运行时使用每个实体新生成的纹理动态更新纹理图谱。当一个实体死亡时,移除它的纹理也为新的留下空白。这里的优势是你只需要一个平局电话。缺点是纹理图谱使系统无法运行。如果您有2048x2048图集,并且您的精灵是64x64,则在空间不足之前只能生成1024个精灵。如果每个实体由5个用于动画目的的精灵组成,那么在任何时候都只能存在大约200个实体。您还必须在运行时不断更新纹理
- 为每个敌人创建一个单独的纹理对象,并为每个敌人进行绘制调用。这里的优点是,您可以根据需要(在内存限制内)不断创建新纹理。缺点显然是潜在的大量绘制调用(仅实体就多达5000次,不包括背景纹理等)
所以#1似乎完全不可能。#2是实现这一目标的唯一方法,还是有我没有考虑过的更好的方法?
您只需使用多个图集,并且仍然可以通过具有额外的顶点属性(或3D纹理坐标)在单个调用中绘制,该属性告诉着色器要使用哪个图集。
有几个选项:
- 使用阵列纹理或3D纹理
- 将它们绑定到不同的纹理单元(从OpenGL 3.0中可以获得至少16个IIRC)
Array Textures可能是最优雅的解决方案,它是3.0中的核心。
从您的描述中不清楚为什么#1是不可能的。这是绘制多个小精灵的常用方法。您不限于1024个精灵,因为您可以创建多个图集。即使一次批处理200个实体,也比逐个绘制要好得多。不过,生成精灵的机制似乎很重要。如果你每帧都更新整个图集,你可能会想做其他事情。