linux中的C++ GLFW3全屏拉伸问题

Posted

技术标签:

【中文标题】linux中的C++ GLFW3全屏拉伸问题【英文标题】:C++ GLFW3 fullscreen stretch issue in linux 【发布时间】:2013-12-14 06:31:59 【问题描述】:

我正在使用 GLFW3 将我的一个游戏从 Windows 移植到 Linux 以创建窗口。当我在 Windows 中运行代码时(使用 GLFW3 和 opengl),代码运行得非常好,但是当我在 ubuntu 12.10 中编译和运行它时,在全屏模式下(在窗口模式下运行良好)出现问题,其中右侧部分(大约 25 %) 的帧被拉伸并离开屏幕。 以下是我创建 GLFW 窗口的方式:

window = glfwCreateWindow(1024, 768, "Chaos Shell", glfwGetPrimaryMonitor(), NULL);

这是我的opengl初始化代码:

glViewport(0, 0, 1024, 768);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-512.0f, 512.0f, -384.0f, 384.0f, 0.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

以上代码应以 1024 x 768 分辨率以全屏模式加载游戏。 当我运行它时,glfwCreateWindow 将屏幕分辨率从我当前的屏幕分辨率(1366 x 768)更改为 1024 x 768,但帧的右侧部分会离开屏幕。如果我手动将分辨率更改为 1024 x 768 然后运行游戏,一切看起来都很好。 此外,无论我当前的屏幕分辨率是多少,在 Windows 中运行相同的代码都不会显示任何问题。它只是将分辨率更改为 1024 x 768,然后一切看起来都很完美。 如果有人能找到为什么它在 ubuntu 中表现得很奇怪,那么我将非常感激......

【问题讨论】:

您是从源代码构建 GLFW3 还是使用发行版包? @genpfault 我是从源代码构建的。我可以从中获得的最新消息:glfw.org/download.html 【参考方案1】:

您可能遇到了窗口管理器的问题。简而言之,窗口管理器没有注意到分辨率的变化,并且由于全屏标志将窗口扩展为旧分辨率。

或者您根本没有获得 1024×768,因为您的屏幕不支持它,而是获得了更小的 16:9 分辨率。所以不要使用硬编码值来设置视口。

老实说:您根本不应该更改屏幕分辨率!几乎没有人再使用 CRT 显示器了。对于使用离散像素的显示器(LCD、AMOLED、DLP 投影仪、LCoS 投影仪),以除原始分辨率之外的任何其他方式运行它们几乎没有意义。所以只需创建一个全屏窗口,而不需要让系统改变分辨率。

在设置视口时,从 GLFW 查询实际窗口大小,而不是依赖硬编码值(这实际上也可以通过更改分辨率来解决您的问题)。

如果您想在渲染时减少 GPU 的负载:使用 FBO 渲染到所需分辨率的纹理,并在最后一步将该纹理绘制为全屏四边形,以将其拉伸至显示尺寸。它看起来比大多数屏幕缩放器生成的要好,并且您的游戏不会与系统的其余部分混淆。

因评论而更新

由于游戏无法应对非 4:3 分辨率而设置屏幕分辨率是非常糟糕的风格。大型游戏工作室需要很长时间才能采用宽屏。这是不可接受的,因为它很容易修复。

不要通过强迫用户做一些他可能不想要的东西来掩盖错误。如果用户有一个漂亮的显示器,就给他实际使用它的机会!

您的问题不在于显示分辨率。这是硬编码的视口和投影设置。你需要解决这个问题。

要解决“游戏在不同分辨率下看起来很糟糕”的问题,您需要设置视口和投影以响应窗口的大小。像这样:

int window_width, window_height;
glfwGetWindowSize(window, &window_width, &window_height);

if( 0 == window_width
 || 0 == window_height) 
    /* window has no area, so there's nothing to draw to */
    return;


float const window_aspect = (float)window_width / (float)window_height;

/* we want to draw with a total of 768 units vertically as if we
 * were drawing to a screen 768 pixels in height. */
float const projection_scale = 768./2;

glViewport(0, 0, window_width, window_height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho( -aspect * projection_scale,
          aspect * projection_scale,
         -projection_scale, 
          projection_scale,
          0.0f,
          1.0f );

【讨论】:

游戏在任何其他分辨率下运行时看起来都很糟糕,这就是为什么我想强制以 1024x768 运行。我的显示器确实支持 1024x768 分辨率,我很确定 GLFW 确实改变了分辨率。我认为您对窗口管理器的怀疑是正确的,因为如果我在运行游戏时打开其他程序,其他程序也会被拉出屏幕。如果显示器支持,我可能想以 1024x768 运行游戏,如果不支持,那么只有我会允许原生分辨率,因为就像我说的,游戏在其他分辨率下看起来不太好...... 我认为你的游戏看起来很糟糕,因为你不尊重窗口的外观。您已将 1024×768 硬编码到 glViewport 的调用和投影设置中,从而导致难看的拉伸外观(就像如果您绘制一个球体,它会被压扁)。这最终是您的视口和投影设置中的一个问题,这是需要修复的问题。更改显示分辨率不是可持续的解决方案。 @PradipnaNepal:请参阅我的答案更新,了解 real 解决您的问题。不要改变显示分辨率,修复你的投影设置。 我认为你是对的。我只会让玩家以玩家的原始分辨率运行游戏。感谢您的回复... 稍微修正一下:窗口指针需要作为第一个参数传递给glfwGetWindowSize

以上是关于linux中的C++ GLFW3全屏拉伸问题的主要内容,如果未能解决你的问题,请参考以下文章

SDL 中的真正全屏

在android中将相机预览拉伸到全屏

全屏视频查看而不拉伸视频

颤振将列拉伸到全屏高度

Android音视频开发之如何全屏显示视频且不拉伸?

Android音视频开发之如何全屏显示视频且不拉伸?