如何在SDL中进行分辨率缩放?

10

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

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

然后,在寻找一些资料后,我尝试使用opengl来处理缩放。目前,我的程序将所有图像绘制到一个大小为1920x1080的SDL_Surface中。然后将此表面转换为opengl纹理,将该纹理缩放到屏幕分辨率,然后绘制该纹理。这在视觉上很好,但问题是根本不高效。目前,我最大的fps只有18 :(

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


1
当您使用OpenGL时,您是否正在实时绘制、转换和缩放? - silent
还可以在游戏开发论坛上询问大家,他们应该能够帮助你。 - silent
是的,我就是,所以它非常低效。但目前我找不到其他可行的方法。好的,我会这样做的。 - David Saxon
3
为什么每次绘图都要按比例缩放?只需将加载的纹理进行比例缩放并存储在内存中,然后从内存中删除大型纹理即可。用户在运行游戏时不太可能改变其运行比例。这将增加加载时间,但比每次渲染时动态缩放更有效率。您应该能够使用当前正在使用的相同方法来动态地缩放纹理。 - Brendan
因为我每次缩放的纹理实际上是游戏的显示。所以我必须在每一帧中将其转换,因为每次都会有新的表面绘制到它上面。如果有一种方法可以将SDL表面绘制到OpenGL纹理上,那么我只需要加载和缩放纹理一次即可。 - David Saxon
1个回答

10

这是因为OpenGL并不是为此种方式设计的,所以效率低下。当前设计的主要性能问题包括:

  • 第一个问题:你正在使用SDL进行软件光栅化。无论你在这个配置上做什么,这都将成为瓶颈。在分辨率为1920x1080时,你有2,073,600个像素需要着色。假设每个4通道像素着色需要10个时钟周期,在一个2GHz的处理器上,你最多运行96.4帧每秒。这听起来并不糟糕,但你可能无法以那么快的速度着色像素,并且你还没有执行AI、用户输入、游戏机制、声音、物理和其他所有操作,而且你可能至少会重复一些像素的绘制。虽然SDL_gfx可能很快,但对于大分辨率来说,CPU基本上任务过载。
  • 第二个问题:每一帧,你都需要将数据从图形总线复制到GPU。这是你在图形方面可能做的最慢的事情。图像数据可能是最糟糕的,因为通常数据量非常大。基本上,每一帧,你都要告诉GPU从RAM复制超过两百万个像素到VRAM。根据维基百科的说法,对于每个有4个字节的2,073,600个像素,最多只能期望258.9帧每秒,这听起来并不糟糕,直到你记得你还需要做其他所有操作。

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

现在,它有一个主要的缺点,就是你必须使用OpenGL绘图命令重新编写所有内容(这是有些工作的,但长期来说并不太难)。除此之外,您可以尝试以下几个想法来提高速度:

  • PBOs。像素缓冲对象可用于通过使纹理加载/复制异步化来解决问题二。
  • 多线程渲染。大多数CPU至少有两个内核,并且在新款芯片上,一个单核心可以保存两个寄存器状态 (超线程)。您基本上正在复制GPU如何解决渲染问题(有许多线程在运行)。我不确定SDL_gfx是否具有线程安全性,但我相信如果您只在同时处理图像的不同部分,则可能会找到一些方法。
  • 确保注意SDL中绘制表面的位置。它应该是SDL_SWSURFACE(因为您正在使用CPU进行绘制)。
  • 去掉垂直同步(VSync)。即使您没有以60Hz运行,这也可以提高性能。
  • 确保绘制原始纹理-不要将其缩放到新的纹理大小。将其以不同大小绘制,并让栅格化器完成工作!
  • 间歇性更新:每次只更新图像的一半。这可能会将“帧速率”几乎提高一倍,并且(通常)不会被注意到。
  • 同样,仅更新图像中发生更改的部分。

希望这可以帮助您。


SDL 2.0现已发布,并且它使用了“水下”的3D加速。也许这会提高你的性能? - Stefan Hendriks

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接