如何在 SDL 中缩放至分辨率?

Posted

技术标签:

【中文标题】如何在 SDL 中缩放至分辨率?【英文标题】:How to scale to resolution in SDL? 【发布时间】:2012-06-15 02:39:54 【问题描述】:

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

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

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

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

【问题讨论】:

您在使用 opengl 时是否在动态绘制、转换和缩放?? 也可以问问gamedev论坛的人,他们应该可以帮助你的。 是的,这就是为什么它如此低效的原因。但目前我找不到任何其他可行的方法。好的会做的。 为什么每次绘制都要缩放。只需缩放内存中加载的纹理存储,然后从内存中删除大纹理。用户在运行游戏时不太可能改变他们运行的规模。这会增加加载时间,但它比每次渲染都动态执行要高效得多。您应该能够使用当前在飞行时使用的相同方法来缩小纹理。 因为我每次缩放的纹理实际上是游戏的展示。所以我必须在每一帧都转换它,因为它每次都有新的表面绘制。如果有办法将 sdl 表面绘制到 opengl 纹理,那么我只需要加载和缩放纹理一次。 【参考方案1】:

这是低效的,因为 OpenGL 不是按照这种方式设计的。当前设计的主要性能问题:

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

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

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

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

希望这会有所帮助。

【讨论】:

SDL 2.0 现已推出,它使用“水下”的 3d 加速。那么也许这可能有助于您的表现?

以上是关于如何在 SDL 中缩放至分辨率?的主要内容,如果未能解决你的问题,请参考以下文章

Windows:缩放设置及DPI缩放详解

Windows:缩放设置及DPI缩放详解

svg整体缩放至指定大小

SDL 改变视口的渲染大小,独立于窗口

在 Expression Blend Sketchflow 项目中,如何将每个屏幕缩放到浏览器分辨率?

如何根据屏幕分辨率缩放 libgdx 中的精灵?