【问题标题】:Optimized 2D Tile Scrolling in OpenGLOpenGL 中优化的 2D 平铺滚动
【发布时间】:2010-04-29 05:50:13
【问题描述】:

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

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

  • 使用 glTriangles 仅绘制屏幕上的图块,每平方图块 2 个(开销太大)
  • 将整个地图绘制为显示列表(在小级别上很棒,在大级别上会变慢)

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

感谢任何建议,但我特别想知道:

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

谢谢:)

【问题讨论】:

  • 你考虑过使用GL_QUAD吗?此外,您可以将您的世界划分为块,每个块为 16x16 块。您只需要绘制您正在看到的那个,以及最多 3 个其他块。您可能希望始终在 RAM 中保留 9 个块。
  • 即使使用第一个选项,您每帧仅绘制大约 1200 个纹理映射三角形,所以我有点惊讶您遇到帧速率问题。你确定瓶颈不在 CPU 上吗?

标签: opengl scroll


【解决方案1】:

以下是我编写快速 2D 瓦片引擎的方法:

首先,我将在动态图块(字符、项目..)和静态图块(关卡)之间进行清晰的分离。

静态图块:

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

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

这将使您在 GPU 上完成几乎“免费”的切片剔除,因为剪切硬件非常快。 即使你的关卡中有大量的图块,比如说 30*20(图块/在一个屏幕中),大约 50 个屏幕/关卡,它会产生 30,000 个图块。我认为它仍然是可以接受的(即使在低端 GPU 上。顺便说一句,你的目标是 iPhone/Android 吗?如果是,实例化/着色器在 OpenGL ES 1.0 上不可用,并且 OpenGL ES 2.0 没有实例化支持但可以做着色器,所以你会必须在 VBO/IBO 中分解切片实例数据,并使用GL_TRIANGLES。您可以分解更少的数据并节省 GPU 内存,在着色器中计算顶点属性)。

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

动态图块:

我会使用一个动态 VBO(和一个静态 IBO 代表 GL_TRIANGLES 所以 0,1,2, 2,1,3, 0+4,1+4,2+4..,)代表瓷砖位置,纹理坐标、图层并通过glBufferSubData 在屏幕中使用可见的动态图块对其进行更新,并通过glDrawElements 绘制这些图块。

当然,这意味着您拥有每个 glDrawElements 可以绘制的最大动态图块数量,因此如果您遇到此限制,您将不得不对 VBO 进行第二次更新/绘制。

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

最后,使用glOrtho 在关卡中移动相机、放大/缩小等。祝你好运!

【讨论】:

  • 我将如何实例化数据,我想我误解了 VBO 流程?我使用glBufferData(GL_ARRAY_BUFFER, texsz, texdata, GL_STATIC_DRAW) 后跟glTexCoordPointer (2, GL_FLOAT, 0, texdata) 从纹理图集创建了一个VBO,然后尝试制作一个几何顶点数组/VBO 加上一个映射到纹理图集VBO 的IBO 数组。但是,当我尝试绘制时,什么也没有出现(在 geom VBO 上尝试了 glDrawArraysglDrawElements 变体)。生成/绑定缓冲区并设置顶点指针,我是否缺少某些步骤?感谢您迄今为止的帮助。
  • 是的,你误解了 VBO 的用法。 VBO 用于存储顶点数据(或完全类型化数据的一维集合。如果这样做,则在创建期间不要使用 GL_ARRAY_BUFFER_ARB 来提示驱动程序使用它来存储顶点)。您一次只能绑定一个 VBO。因此,您必须将 texdata 放入常规的 OpenGL 2D 纹理中。然后将所有图块顶点和索引数据放入 VBO/IBO 并使用 glDrawElements 绘制它们。我所描述的是没有实例化/着色器。我的建议:首先让它以最简单的方式工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-28
  • 1970-01-01
  • 2011-12-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多