在OpenGL中优化2D平铺滚动

时间:2010-04-29 05:50:14

标签: opengl scroll

我正在开发2D侧面滚动游戏,我需要优化我的平铺代码以获得更好的帧速率。截至目前,我正在使用纹理图集和16x16图块,以获得480x320的屏幕分辨率。级别在两个方向上滚动,并且明显大于1个屏幕(数千个像素)。我使用glTranslate进行实际滚动。

到目前为止,我已经尝试过:

  • 使用glTriangles仅绘制屏幕上的图块,每平方图片2个(头顶太多)
  • 将整个地图绘制为显示列表(在较小的水平上很好,在大的地方放慢速度)

  • 将地图划分为显示列表的一半大小,然后剔除显示列表(对于双向滚动仍然会变慢,过度绘制效率不高)

任何建议都值得赞赏,但我特别想知道:

  • 我见过Vertex Arrays / VBO,因为它们是动态的。什么是利用这个的最佳方式?如果我只保留1个顶点屏幕加上一些过度绘制,我必须每隔几帧重新复制一次数组,以考虑相对坐标的变化(将所有内容移动并添加新的行/列)。如果我使用更多的透支,这似乎不是一个大赢家;这就像是半屏显示列表的想法。
  • 如果在像这样的一堆小瓷砖上使用glScissor会给出任何增益,无论是显示列表还是顶点数组/ VBO
  • 用大纹理构建关卡然后使用glScissor会更好吗?如果我这样做,那么失去平铺的内存节省是移动开发的一个问题(只是好奇,我目前在PC上)?提到了这种方法here

谢谢:)

1 个答案:

答案 0 :(得分:9)

以下是我对快速2D磁贴引擎进行编码的方法:

首先,我会在动态切片(字符,项目..)和静态切片(水平)之间进行清晰的分离。

静态瓷砖:

为了绘制静态的(构建整个级别的tile),我将使用一个静态缓冲区(存储在缓冲区对象中),其中包含每个tile位置(x,y,layer)和atlas纹理的索引数据(i)。由于纹理图集包含16x16像素的固定大小的图块,因此您可以轻松地在每个顶点的顶点着色器纹理坐标中进行计算。

为了绘制关卡,我将使用形成四边形的三角形条带的单个绘制调用(使用实例化),顶点数据存储在静态VBO(由4个顶点组成)和静态IBO中的索引数据(由4个索引),使用每个实例值计算顶点着色器中的顶点属性。

这会让你在GPU上完成几乎“免费”的瓷砖剔除,因为剪切硬件非常快。 即使您的关卡中有大量的牌,也就是说30 * 20(平铺/在屏幕上),约50个屏幕/等级,它会生成30,000个牌。我认为它仍然可以接受(即使在低端GPU上。顺便说一下,你是针对iPhone / Android吗?如果是OpenGL ES 1.0上没有实例/着色器,OpenGL ES 2.0没有实例支持但可以做着色器,所以你会必须在VBO / IBO中爆炸tile实例数据,并使用GL_TRIANGLES。您可以爆炸更少的数据和备用GPU内存,在着色器中计算顶点属性。)

在任何情况下,你最好不要复制纹理贴图数据并保留纹理图集和VBO和IBO。

动态图块:

我会使用动态VBO(和表示GL_TRIANGLES的静态IBO,所以0,1,2,2,1,3,0 + 4,1 + 4,2 + 4 ..,)表示拼贴位置,纹理坐标,图层,并通过glBufferSubData在屏幕上使用可见动态图块进行更新,并通过glDrawElements绘制图块。

当然这意味着您可以按照glDrawElements绘制最大数量的动态切片,因此如果达到此限制,则必须对VBO进行第二次更新/绘制。< / p>

如果您的OpenGL实现不支持VBO / IBO(如在OpenGL ES 1.0中),请使用VA。我不建议使用DL或立即模式(在OpenGL ES上不支持它)。

最后,使用glOrtho将相机移动到水平位置,放大/缩小等等。祝你好运!