2

我正在拼命地让 Vsync 在我的 OpenGL 应用程序中工作。这是重要的统计数据:

我正在使用 Windows,使用 C++ OpenGL 进行编码,并且我正在将 FreeGLUT 用于我的 OpenGL 上下文(双缓冲)。我知道要让交换缓冲区在 Windows 中等待垂直同步,您需要调用 wglSwapIntervalEXT()。

我的代码确实调用了这个(如下所示),但我仍然在垂直撕裂。我设法阻止它的唯一方法是调用 glFinish() ,这当然会带来显着的性能损失。

我的 main() 函数的相关部分如下所示:

//Initiating glut window
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize (initial_window_width, initial_window_height);
glutInitWindowPosition (100, 100);
int glut_window_hWnd = glutCreateWindow(window_title.c_str()); 

//Setting up swap intervals
PFNWGLSWAPINTERVALEXTPROC       wglSwapIntervalEXT = NULL;
PFNWGLGETSWAPINTERVALEXTPROC    wglGetSwapIntervalEXT = NULL;

if (WGLExtensionSupported("WGL_EXT_swap_control"))
{
// Extension is supported, init pointers.
wglSwapIntervalEXT = PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT");

// this is another function from WGL_EXT_swap_control extension
wglGetSwapIntervalEXT = (PFNWGLGETSWAPINTERVALEXTPROC)wglGetProcAddress("wglGetSwapIntervalEXT");
}

wglSwapIntervalEXT (1)

init ();

glutMainLoop();    ///Starting the glut loop
return(0);

需要指出的是,wglInitSwapControlARB 函数的返回值是 true,所以扩展是受支持的。

4

3 回答 3

7

好的 - 在我在这里获得的巨大帮助以及我自己的研究和搞砸时间之间,我发现了一些东西,包括一个适合我的解决方案(以防其他人遇到这个问题)。

首先,我使用的是 freeGLUT,我将我的代码转换为 GLFW,结果是一样的,所以这不是 API 问题,不要像我一样浪费你的时间!

至少在我的程序中,使用 wglSwapIntervalEXT(1) 不会停止垂直撕裂,这就是导致解决它如此令人头疼的原因。

当我的 NVIDIA 驱动程序设置为 VSYNC = ON 时,我仍然在流泪(因为这相当于 SwapInterval(1) 没有帮助) - 但它设置正确,驱动程序正在做我应该做的事情我只是没有'不知道,因为我还在流泪。

所以我将我的 NVIDIA 驱动程序设置为 VSYNC = 'Application preference' 并使用 wglSwapIntervalEXT(60) 而不是我一直使用的 1,并发现这实际上是有效的,因为它给了我大约 1Hz 的刷新率。

我不知道为什么 wglSwapIntervalEXT(1) 不垂直同步我的屏幕,但是 wglSwapIntervalEXT(2) 具有预期的效果,但显然我现在正在渲染效率低下的所有其他帧。

我发现禁用 VSYNC 的 glFinish 对撕裂没有帮助,但启用它确实可以(如果有人能解释为什么那会很棒)。

所以总而言之,设置 wglSwapIntervalEXT(1) 并启用 glFinish() 我不再有撕裂,但我仍然不明白为什么。

这是我的应用程序中的一些性能统计数据(故意加载以使 FPS 低于 60):

  • wglSwapIntervalEXT(0) = 撕裂 = 58 FPS
  • wglSwapIntervalEXT(1) = 撕裂 = 58 FPS
  • wglSwapIntervalEXT(2) = 无撕裂 = 30 FPS
  • wglSwapIntervalEXT(1) + glFinish = 无撕裂 = 52 FPS

我希望这对将来的某人有所帮助。感谢你的帮助。

于 2014-01-22T12:04:04.700 回答
0

我也遇到了 vsync 和 freeglut 的问题。以前我使用过 glut,并且我能够选择性地为多个 GLUT 窗口启用 vsync。

现在有了 freeglut,wglSwapIntervalEXT() 似乎没有效果。生效的是 NVIDIA 控制面板中的全局 vsync 选项。如果我在那里启用 vsync,我的两个 freeglut 窗口中都有 vsync,如果我禁用我没有。我为我的应用程序(在 nvidia 控制面板中)专门设置了什么并不重要。这也证实了我观察到的:

if(wglSwapIntervalEXT(0)) 
printf("VSYNC set\n");
int swap=wglGetSwapIntervalEXT();
printf("Control window vsync: %i\n",swap);

swap 的值始终是在 NVIDIA 控制面板中设置的值。用 wglSwapIntervalEXT() 设置什么并不重要。

否则,您可以在这里阅读 GLFinish() 的优点: http ://www.opengl.org/wiki/Swap_Interval

我使用它是因为我需要知道我的显示器何时更新,因此我可以在此之后同步执行任务(用相机捕捉某些东西)。

于 2014-03-04T14:45:31.477 回答
-1

这里问题中所述,不存在“真正的”垂直同步。使用 GLFinish 是正确的方法。这将导致您的卡在继续并渲染下一帧之前完成对已发送的所有内容的处理。

您应该跟踪您的 FPS 和渲染帧的时间,您可能会发现 GLFinish 只是暴露了代码中的另一个瓶颈。

于 2014-01-21T16:24:59.450 回答