OpenGL-推荐的渲染大量实体的方法,每个实体都有独特的程序纹理

OpenGL-推荐的渲染大量实体的方法,每个实体都有独特的程序纹理,opengl,graphics,2d,textures,simulation,Opengl,Graphics,2d,Textures,Simulation,考虑具有以下特性的二维模拟: 实体填充屏幕并四处移动,有时死亡并消失 每个实体都有一组独特的、按程序生成的纹理作为其“精灵”。鉴于程序性质,纹理是在运行时生成的。任何两个实体具有相同纹理的可能性极低 屏幕上一次最多可存在5000个实体(在任何给定的playthrough中可存在的实体数量没有最大值-当它们死亡时,内存被释放) 精灵应该向后拉到前面,以便前景实体与“后面”的实体重叠 sim卡与OpenGL 3.0兼容 GL_MAX_TEXTURE_大小为2048,与较旧的移动设备兼容 纹理具有透

考虑具有以下特性的二维模拟:

  • 实体填充屏幕并四处移动,有时死亡并消失
  • 每个实体都有一组独特的、按程序生成的纹理作为其“精灵”。鉴于程序性质,纹理是在运行时生成的。任何两个实体具有相同纹理的可能性极低
  • 屏幕上一次最多可存在5000个实体(在任何给定的playthrough中可存在的实体数量没有最大值-当它们死亡时,内存被释放)
  • 精灵应该向后拉到前面,以便前景实体与“后面”的实体重叠
  • sim卡与OpenGL 3.0兼容
  • GL_MAX_TEXTURE_大小为2048,与较旧的移动设备兼容
  • 纹理具有透明度,因此z缓冲区不适用于绘制顺序
如果我没有弄错的话,解决这个问题有两种方法:

  • 在运行时使用每个实体新生成的纹理动态更新纹理图集。当实体消亡时,删除其纹理,并为新纹理留出空白。这里的优点是你只需要一次抽签。缺点是纹理图集使系统无法运行。如果您有一个2048x2048 atlas,并且您的精灵是64x64,则在空间不足之前,您只能生成1024个精灵。如果出于动画目的,每个实体由5个精灵组成,则一次只能存在大约200个实体。您还必须在运行时不断更新纹理
  • 为每个敌人创建一个单独的纹理对象,并对每个敌人进行绘制调用。这里的优点是,您可以根据需要(在内存限制内)不断创建新纹理。缺点显然是潜在的大量绘制调用(仅实体就多达5000次,不包括背景纹理等)

  • 因此#1似乎完全不可能。#2是实现这一目标的唯一方法,还是我没有考虑过更好的方法?

    从你的描述中不清楚为什么#1是不可能的。这是绘制多个小精灵的常用方法。您不限于1024个精灵,因为您可以创建多个atlas。即使一次批处理200个实体,也比逐个绘制它们要好得多。
    不过,生成精灵的机制似乎很重要。如果您在每帧更新整个图集,您可能会想做其他事情。

    您可以只使用几个图集,并通过使用一个额外的顶点属性(或3D纹理坐标)来告诉着色器要使用哪个图集,从而仍然在一个调用中绘制

    有几种选择:

    • 使用阵列纹理或三维纹理
    • 将它们绑定到不同的纹理单元(从OpenGL 3.0至少可以获得16个IIRC)

    阵列纹理可能是最优雅的解决方案,它是3.0的核心。

    由于绘制顺序是从后到前的,并且来自不同地图集的实体可能到处都是,因此似乎没有明显的迹象表明多个地图集会带来任何好处,因为我会一直切换纹理以获得正确的绘制顺序。精灵是透明的,所以我不能使用z缓冲区(这是我应该提到的事实,我将编辑文章)在地图集中对图像进行分组仍然有意义。多次调用GLDrawArray而不切换纹理比每次切换纹理更好。我希望您能够按照每个atlas打包精灵,这样atlas交换机的数量就不会太多。我猜你最终可能会使用一个非常复杂的排序算法。或许还有其他解决办法。我会考虑更多。使用纹理阵列如何?对于最大256个纹理层,纹理阵列实际上可以与方法1结合使用。这仍然需要编写大量的纹理,但可能没有那么糟糕……在回答问题之前,我必须进行测试。