10

我正在使用 SDL 和 C++ 编写 2D 平台游戏。但是,我遇到了一个涉及缩放到分辨率的巨大问题。我希望游戏在全高清下看起来不错,因此游戏的所有图像都已创建,因此游戏的自然分辨率为 1920x1080。但是,如果有人使用较小的分辨率,我希望游戏可以缩小到正确的分辨率,或者如果有人使用较大的分辨率,我希望游戏可以放大。

问题是我无法找到一种有效的方法来做到这一点。我首先使用 SDL_gfx 库来预缩放所有图像,但这不起作用,因为它会产生很多错误,一个像素丢失的地方。而且由于我的动画包含在一个图像中,当动画播放时,动画会在每一帧中略微向上或向下移动。

然后经过一番环顾后,我尝试使用 opengl 来处理缩放。目前,我的程序将所有图像绘制到 1920x1080 的 SDL_Surface。然后,它将这个表面转换为一个 opengl 纹理,将此纹理缩放到屏幕分辨率,然后绘制纹理。这在视觉上效果很好,但问题是它根本没有效率。目前我的最大 fps 为 18 :(

所以我的问题是有人知道将 SDL 显示缩放到屏幕分辨率的有效方法吗?

4

1 回答 1

10

这是低效的,因为 OpenGL 并非设计为以这种方式工作。当前设计的主要性能问题:

  • 第一个问题:您正在使用 SDL 进行软件光栅化。抱歉,但无论您如何使用此配置,这都将成为瓶颈。在 1920x1080 的分辨率下,您有 2,073,600 个像素可供着色。假设着色每个 4 通道像素需要 10 个时钟周期,那么在 2GHz 处理器上,您运行的最大速度为 96.4 fps。这听起来不错,除了你可能无法快速着色像素,而且你还没有完成人工智能、用户输入、游戏机制、声音、物理和其他所有事情,而且你可能正在绘制一些像素至少一次。SDL_gfx 可能很快,但对于大分辨率,CPU 只是从根本上过度工作。
  • 第二个问题:每一帧,您都在通过图形总线将数据复制到 GPU。这是您在图形方面可以做的最慢的事情。图像数据可能是最糟糕的因为它通常太多了。基本上,您告诉 GPU 将 200 万个像素从 RAM 复制到 VRAM 的每一帧。根据Wikipedia的说法,您可以预期,对于 2,073,600 个像素,每个 4 字节,不超过 258.9 fps,在您记住需要做的所有其他事情之前,这听起来还不错。

我的建议:将您的应用程序完全切换到 OpenGL。这消除了渲染到纹理并复制到屏幕的需要——只需直接渲染到屏幕!此外,缩放由您的视图矩阵自动处理(glOrtho/gluOrtho2D 用于 2D),因此您根本不必关心缩放问题 - 您的视口只会以相同的比例显示所有内容。 这是您问题的理想解决方案。

现在,它带来了一个主要缺点,即您必须使用 OpenGL 绘制命令重新编码所有内容(这是可行的,但不是太难,尤其是从长远来看)。除此之外,您可以尝试以下想法来提高速度:

  • 公益组织。通过使纹理加载/复制异步,像素缓冲区对象可用于解决问题二。
  • 多线程渲染。大多数 CPU 至少有两个内核,在较新的芯片上,可以为单个内核保存两个寄存器状态(超线程)。您实际上是在复制 GPU 解决渲染问题的方式(有很多线程在运行)。我不确定 SDL_gfx 的线程安全性如何,但我敢打赌可以解决一些问题,特别是如果您同时只处理图像的不同部分。
  • 确保注意绘图表面在 SDL 中的位置。它可能应该是 SDL_SWSURFACE (因为你在 CPU 上绘图)。
  • 删除垂直同步。即使您没有以 60Hz 运行,这也可以提高性能
  • 确保您正在绘制原始纹理 - 不要将其放大或缩小到新纹理。以不同的大小绘制它,让光栅化器完成工作!
  • 偶尔更新:一次只更新一半的图像。这可能会使您的“帧速率”增加一倍,并且(通常)不明显。
  • 同样,只更新图像的变化部分。

希望这可以帮助。

于 2012-06-17T07:42:08.273 回答