c++ - 如何缩放到 SDL 中的分辨率?

标签 c++ opengl sdl

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

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

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

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

最佳答案

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

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

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

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

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

希望这对您有所帮助。

关于c++ - 如何缩放到 SDL 中的分辨率?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11043969/

相关文章:

c++ - std::size_t 或 std::vector<Foo>::size_type?

C++ 跨边界使用 std::vector

java - 如何在 LibGDX 中正确旋转和移动 3D 透视相机

c++ - Linux 中的 SDL 库

c++ - sleep 或等待不会停止整个程序?

c++ - 如何将 SDL_renderer 转换为 SDL_window?

c++ - 有人可以彻底解释这个 IsItPrime 函数吗?

c++ - 包含函数作为成员的结构数组 C++

c++ - 并行运行 CUDA 和 OpenGL,无需使用互操作性

macos - 强制 SCNView 使用 OpenGL