我有一个没有过剩的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)
答案 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?