2010-04-16 110 views
1

我使用的是win32和opengl,并且我在窗口坐标的glOrtho处设置了一个窗口。我启用了双缓冲,并使用glGet进行了测试。如果它不断翻译,我的程序似乎总是会撕掉任何我尝试绘制的原语。撕裂OpenGL?

这里是我的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

撕裂是由于未将更新与显示器的垂直消隐间隔同步所致。这在OpenGL(我认为,不是专家)方面有点依赖硬件,从寻找glXWaitVideoSyncSGI开始。谷歌搜索“opengl同步到vblank”也得到回报。

+3

glX用于Unix,OP表示他在win32上。 – slacker 2010-04-17 00:02:24

7

如果你只是渲染一两个trianges,你会有一个疯狂的高帧速率(可能是成千上万的FPS),这意味着它像SwapBuffering一样,这意味着你可能总是在交换屏幕刷新(即使双缓冲)。一旦你的场景得到更多的内容,并且帧率降到更真实的值,它应该停止撕裂。或者,查看启用V-Sync,例如在Windows上使用wglSwapIntervalEXT

+0

我忘了说framerate的上限为60 FPS(每隔16ms使用WM_TIMER),并且无论我设置了计时器,它仍然会流泪。 – kaykun 2010-04-17 00:14:35

+0

以@AshleysBrain表示启用vsync。使用计时器手动限制帧速率不会将其与屏幕刷新同步。 – jalf 2010-04-17 03:01:47

+0

在调用glGetString(GL_EXTENSIONS)之后,我发现我的系统没有启用VSync,因为字符串“WGL_EXT_swap_control”没有返回。是否真的没有其他办法可以减少撕裂,因为我可以下载的任何其他游戏都没有这个问题。 – kaykun 2010-04-17 05:04:57

2

当定义你的Win32应用程序窗口风格,不包括WS_POPUP
调试一个问题,即全屏幕将推出屏幕撕裂后,我发现了全屏样式,删除WS_POPUP后,似乎有停止撕裂而不必强制渲染循环达到刷新率。我猜,WS_POPUP是有问题的。它也会阻止任何全屏截图来完成白屏。

+0

该问题是由V-Sync造成的。你有没有证据表明WS_POPUP可以相关? – Kromster 2013-05-21 08:35:01

+0

调试完全屏幕会引入屏幕撕裂的问题后,我发现全屏的样式,在删除WS_POPUP后,它似乎已经停止撕裂,而不必强制渲染循环达到刷新率。我猜,WS_POPUP是有问题的。它也会阻止任何全屏截图来完成白屏。 – Luka 2013-05-21 08:47:40

+0

你应该将这个解释添加到你的答案中) – Kromster 2013-05-21 09:48:25

0

尝试把盖/限制中的帧速率或可能产生(如果你没有一个VSYNC):

下面是伪代码:

let tick equals new_tick 
if tick is less than last_tick do 
    yield 
done 

calculate last_tick 

尝试睡眠功能,将其设置为一个,这样的收益率:

Sleep(1); 

还记得限制或封盖帧率并不明智,因为是某些职能是真的意味着减少帧calcu办法第十四。

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。