撕裂OpenGL?

时间:2010-04-16 22:59:27

标签: c++ opengl winapi

我正在使用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);

无论渲染功能运行的频率如何,都会出现相同的撕裂问题。我有什么问题或错过了吗?

5 个答案:

答案 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);

还记得限制或限制帧速率是不可取的,因为某些功能真的意味着减少帧计算。