OpenGL以全屏原始分辨率撕裂

时间:2015-05-17 23:12:08

标签: c++ windows opengl fullscreen tearing

我有一个没有过剩的win32 api的OpenGL应用程序......我遇到了全屏幕撕裂的问题。 基本上我将WS_POPUP设置为我的显示器的窗口样式和分辨率作为窗口大小。 我正在运行AMD radeon HD 7770,我看到可怕的撕裂! 当我放置WS_POPUPWINDOW样式而不是WS_POPUP时,撕裂消失了,但是我的场景周围有不必要的边框。 我注意到的另一件事是,当分辨率不是原生时,撕裂会消失。 因此,当我将my_screen_resolution + 1作为大小参数传递时,撕裂就消失了。

RESx = 1920;
RESy = 1080;
hwnd = CreateWindowEx(NULL, NAME, NAME, WS_POPUP, 0, 0, RESx, RESy, NULL, NULL, hInstance, NULL);
SetWindowPos(hwnd, 0, -1, -1, RESx + 1, RESy + 1, 0); // With this function call, the tearing disappears!

我可以做些什么来摆脱撕裂,而不必运行非原生分辨率?

编辑:(提示:这不是V-sync)

2 个答案:

答案 0 :(得分:2)

  

我可以做些什么来摆脱撕裂,而不必以非原生分辨率运行?

     

编辑:(提示:这不是V-sync)

是的,它是V-Sync。

制作全屏窗口时,它将绕过DWM合成器。

如果窗口未覆盖整个屏幕,则其内容将通过DWM合成器。 DWM合成器本身就是窗口内容的副本,只要有东西指示,它就完成了绘图(从WM_PAINT处理程序返回,调用了EndPaint或SwapBuffers)。组合物本身就是V-synced。

  

感谢您的建议,但我希望避免在没有vsync的情况下进行撕裂。使用vsync,我的输入延迟很糟糕。

然后你在输入处理中做错了。很可能您的事件循环一次只处理一个输入事件然后重绘。如果是这种情况并且你的场景复杂度上升,那么你就会遇到延迟,这与你的场景的绘图复杂性成正比。你不希望这种情况发生。

您应该做的是累积重绘之间堆积的所有输入事件,并将它们合并为一个新的绘图状态。理想情况下,收集输入事件直到场景设置为绘制以反映最近的状态。如果你想得到你的想象,我会添加一个卡尔曼滤波器来预测帧被显示给用户时的输入状态,并用它来绘制场景。

答案 1 :(得分:1)

要删除OpenGL撕裂,您应该“启用”vsync。请点击此链接了解详情:how to enable vertical sync in opengl?