在 OpenGL 中使用 glut 时出现垂直同步问题

问题描述 投票:0回答:4

我正在拼命努力让 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,因此支持扩展。

c++ windows opengl freeglut vsync
4个回答
8
投票

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

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

至少在我的程序中,使用 wglSwapIntervalEXT(1) 并不能阻止垂直撕裂,这就是导致它如此令人头痛的原因。

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

因此,我将 NVIDIA 驱动程序设置为 VSYNC =“应用程序首选项”,并使用 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

我希望这对将来的人有帮助。感谢您的帮助。


0
投票

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

现在使用 freeglut,wglSwapIntervalEXT() 似乎没有效果。 起作用的是NVIDIA控制面板中的全局垂直同步选项。如果我在那里启用垂直同步,我的两个 freeglut 窗口中都会有垂直同步,如果我禁用垂直同步,则没有。我为我的应用程序专门设置的内容(在 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

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


0
投票

我知道这个问题已经很老了,但无论如何我都会回答,更多的是为了在我再次遇到这个问题时提醒自己。 当为“呈现”上下文(负责调用

SwapBuffers
)设置像素格式时,您必须使用
WGL_DOUBLE_BUFFER_ARB
作为属性。否则
SwapBuffers
只会将当前后台缓冲区复制到窗口缓冲区并忽略交换间隔(因为没有发生交换)


-1
投票

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

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

© www.soinside.com 2019 - 2024. All rights reserved.