OpenGL 2D 双缓冲缩放

Posted

技术标签:

【中文标题】OpenGL 2D 双缓冲缩放【英文标题】:OpenGL 2D doublebuffer scaling 【发布时间】:2014-02-08 12:16:54 【问题描述】:

我将 OpenGL 用于基于 2D 的游戏,该游戏的分辨率为 640x480 像素。因此,我像这样设置我的 OpenGL 双缓冲区:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 640, 480, 0, 0, 1);
glDisable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

这很好用,我可以使用硬件加速的 GL 纹理绘制所有精灵和背景滚动条。现在我也想支持其他窗口大小,即用户应该能够在 800x600、1024x768 等下运行游戏。所以所有图形都应该缩放到新的分辨率。当然,我可以通过在将纹理绘制为四边形时简单地对所有顶点应用缩放因子来做到这一点。但我不认为我能够以这种方式实现像素完美定位....但是像素完美定位对于2D游戏当然非常重要!

因此,我想问一下是否有可能使用静态 640x480 双缓冲区,仅在将其绘制到屏幕之前对其进行缩放,即像这样:

1) 无论实际输出窗口大小是多少,我的双缓冲区始终为 640x480 像素。

2) 调用 glfwSwapBuffers() 后,640x480 双缓冲区应缩放到可以小于或大于 640x480 的实际窗口大小。

这有可能吗?我认为这对我的游戏来说是最简单的解决方案,因为手动缩放所有顶点可能会给我在像素完美定位方面带来一些问题,不是吗?

谢谢!

【问题讨论】:

【参考方案1】:

我这样设置我的 OpenGL 双缓冲区:

我想你不知道“双缓冲”是什么意思。这意味着您在一个不可见的缓冲区上执行绘图,然后在绘图完成后向用户显示,以便用户看不到绘图过程。

您拥有的代码 sn-p 是投影设置。并且以像素为单位对尺寸进行硬编码是错误的。

但是像素完美的定位对于 2D 游戏当然是非常重要的!

不,不是真的。而不是“像素”单位(除了纹理图像索引和视口之外,在 OpenGL 中并不真正存在),您应该使用类似世界单位的东西。例如在像 SMW 这样的简单的跳跃和奔跑平台游戏中

你可以说,每个方块都是一个单位高。 Yosi 精灵高 2 个单位,马里奥 1.5 等等。

重要的是,您可以保持精灵渲染尺寸独立于屏幕分辨率。这对于所有不同的屏幕分辨率和宽高比来说尤其重要。不要强迫用户采用您认为合适的分辨率。人们拥有大屏幕电脑,并且想使用它们。

您的精灵的外观在很大程度上取决于您使用的纹理图像和过滤方法。如果您想获得像素化的外观,只需将纹理图像设置为低分辨率并使用 GL_NEAREST 放大滤镜,其余的由 OpenGL 完成(但是您应该提供缩小的 mipmap 并使用 GL_LINEAR_MIPMAP_LINEAR 进行缩小,这样看起来就不会很糟糕了小分辨率)。

因此,我想问一下是否有可能使用静态 640x480 双缓冲区,使其仅在被绘制到屏幕之前进行缩放,即像这样:

是的,您可以为此使用帧缓冲区对象。创建一组渲染尺寸(如 640×480)的纹理(颜色和深度模板),然后在完成后将颜色纹理绘制到主帧缓冲区上的视口填充四边形。

【讨论】:

谢谢,使用帧缓冲区绘制纹理,然后使用缩放四边形绘制该纹理正是我想要的。在 glOrtho2D() 中硬编码像素尺寸的想法直接来自 MSDN,请参见此处:msdn.microsoft.com/en-us/library/windows/desktop/… @Andreas:实际上这些“正确性提示”来自“官方 OpenGL 编程指南”(又名红皮书),但现在已经过时了一段时间。无论如何,这些建议仅适用于您需要像素完美对齐的情况。但是您不需要像素完美对齐来完成您想做的事情(屏幕空间过滤、后期处理或绘制用户界面等事情需要像素完美对齐)。【参考方案2】:

和以前一样,以 640x480 渲染,但使用屏幕外纹理。然后使用此纹理渲染一个屏幕大小(800x600、1024x768...)的四边形。

【讨论】:

以上是关于OpenGL 2D 双缓冲缩放的主要内容,如果未能解决你的问题,请参考以下文章

opengl 单缓冲与双缓冲

OpenGL中实现双缓冲技术

消费者生产者模型中的双缓冲 OpenGL 对象

OpenGL的消隐与双缓冲

opengl如何在MFC中设置双缓冲

单缓冲和双缓冲 有啥区别