我正在使用win32和opengl,我在窗口坐标的glOrtho处设置了一个投影窗口。我启用了双缓冲,并使用glGet进行了测试。我的程序似乎总是撕掉我试图在其上绘制的任何原语,如果它不断翻译的话。
这是我的OpenGL初始化函数:
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glViewport(0, 0, 640, 480);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 640, 0, 480, 0, 100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDrawBuffer(GL_BACK);
glLoadIdentity();
这是我的渲染函数,gMouseX和gMouseY是鼠标的坐标:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glTranslatef(gMouseX, gMouseY, 0.0f);
glColor3f(0.5f, 0.5f, 0.5f);
glBegin(GL_TRIANGLES);
glVertex2f(0.0f, 128.0f);
glVertex2f(128.0f, 0.0f);
glVertex2f(0.0f, 0.0f);
glEnd();
SwapBuffers(hDC);
无论渲染功能运行的频率如何,都会出现相同的撕裂问题。我有什么问题或错过了吗?
答案 0 :(得分:7)
如果你只是渲染一个或两个trianges,你将会有一个疯狂的高帧速率(可能是成千上万的FPS),这意味着它是像地狱一样的SwapBuffering,这意味着你可能总是在交换期间交换屏幕刷新(即使启用双缓冲)。一旦你的场景进入更多内容并且帧速率降到更逼真的值,它应该停止撕裂。或者,查看启用V-Sync,例如在Windows上使用wglSwapIntervalEXT
。
答案 1 :(得分:3)
此问题不必严格连接到VSync,因为互联网上的所有人都试图建议。在我的情况下,问题是由窗口初始化的方式引起的。我注意到,摆脱dwStyle = WS_POPUP解决了问题,但只是部分因为窗口不是全屏模式。最终对我有用的是在创建窗口后使用 SetWindowLong(hwnd,GWL_STYLE,0); 。它基本上清除了窗口样式。所以我初始化窗口的代码看起来像这样:
dwStyle=WS_POPUP; //Windows Style
ShowCursor(FALSE); //Hide Mouse Pointer
//Create the Window
hwnd= CreateWindowEx(NULL,
"GLClass",
appName,
dwStyle,
0, 0,
(long)windowWidth,
(long)windowHeight,
NULL,
NULL,
hInstance,
NULL);
SetWindowLong(hwnd, GWL_STYLE, 0);
经过这次修改后,我所有的撕裂问题和无法使用PrintScreen的问题都得到了解决。我不需要在任何地方触摸VSync。
答案 2 :(得分:2)
定义win32应用程序窗口样式时,请不要包含 WS_POPUP
在调试全屏会引入屏幕撕裂的问题之后,我发现全屏样式,在删除WS_POPUP之后,它似乎已经停止单手撕裂,而不必强制渲染循环达到刷新率。我想,WS_POPUP因存在问题而闻名。它还会阻止任何全屏截图完成白色。
答案 3 :(得分:0)
由于未将更新与显示器的垂直消隐间隔同步而导致撕裂。它在OpenGL中有点硬件依赖(我认为,不是专家),首先要寻找glXWaitVideoSyncSGI。谷歌搜索“opengl sync to vblank”也得到了回报。
答案 4 :(得分:0)
尝试设置上限/限制帧速率或者可能产生它(如果你没有vsync):
这是伪代码:
let tick equals new_tick
if tick is less than last_tick do
yield
done
calculate last_tick
尝试睡眠功能并将其设置为1,以便产生:
Sleep(1);
还记得限制或限制帧速率是不可取的,因为某些功能真的意味着减少帧计算。