如何在SDL中扩展到分辨率?

Dav*_*xon 10 c++ opengl sdl

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

问题是我无法找到一种有效的方法来实现这一点.我首先使用SDL_gfx库预先缩放所有图像,但这不起作用,因为它会产生大量的逐个错误,一个像素丢失的地方.并且由于动画播放时我的动画包含在一个图像中,因此动画会在每帧上下移动.

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

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

ima*_*ett 10

这是低效的,因为OpenGL不是为那种方式工作而设计的.当前设计的主要性能问题:

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

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

现在,它带来了一个主要缺点,你必须用OpenGL绘图命令重新编码所有东西(这是工作,但不是太难,特别是从长远来看).除此之外,您可以尝试以下想法来提高速度:

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

希望这可以帮助.