如何启用垂直同步?
像glEnable(GL_VSYNC)
这样的简单操作吗?(虽然在glEnable可接受的选项中没有类似GL_VSYNC的选项)。
还是说在 OpenGL 中没有标准的方法来实现垂直同步?
如何启用垂直同步?
像glEnable(GL_VSYNC)
这样的简单操作吗?(虽然在glEnable可接受的选项中没有类似GL_VSYNC的选项)。
还是说在 OpenGL 中没有标准的方法来实现垂直同步?
在Windows操作系统中,有一个OpenGL扩展方法wglSwapIntervalEXT
。根据b2b3的帖子http://www.gamedev.net/community/forums/topic.asp?topic_id=360862:
如果您正在Windows上工作,则必须使用扩展来使用
wglSwapIntervalExt
函数。 它在wglext.h中定义。 您还需要下载glext.h文件。 在wglext文件中,声明了所有与Windows特定扩展相关的入口点。 所有这样的函数都以前缀wgl开头。 要获取有关所有已发布扩展的更多信息,可以查看OpenGL扩展注册表。
wglSwapIntervalEXT
来自WGL_EXT_swap_control
扩展。它允许您指定每个缓冲区交换之前的最小帧数。通常用于垂直同步(如果将交换间隔设置为1)。可以在此处找到有关整个扩展的更多信息。 在使用此功能之前,您需要查询您的显卡是否支持WGL_EXT_swap_control
, 并使用wglGetProcAddress
函数获得该函数的指针。要测试给定扩展的支持情况,可以使用类似以下函数的函数:
#include <windows.h>
#include "wglext.h"
bool WGLExtensionSupported(const char *extension_name)
{
// this is pointer to function which returns pointer to string with list of all wgl extensions
PFNWGLGETEXTENSIONSSTRINGEXTPROC _wglGetExtensionsStringEXT = NULL;
// determine pointer to wglGetExtensionsStringEXT function
_wglGetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC) wglGetProcAddress("wglGetExtensionsStringEXT");
if (strstr(_wglGetExtensionsStringEXT(), extension_name) == NULL)
{
// string was not found
return false;
}
// extension is supported
return true;
}
要初始化函数指针,您需要:
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");
}
然后您可以像使用其他函数指针一样使用这些指针。要启用vync,您可以调用wglSwapIntervalEXT(1)
,要禁用它,您调用wglSwapIntervalEXT(0)
。wglGetSwapIntervalEXT()
。WGL案例在eugensk00的答案中有描述。
对于CGL(MacOSX),请参见这个SO问题的答案。
对于EGL,有eglSwapInterval()函数,但显然(见此处和此处)它不能保证无撕裂的结果 - 只等待给定的时间段(也许只是由于损坏的驱动程序)。
对于GLX(Linux with X11等),至少有3个类似的扩展,具有不同程度的功能。OpenGL wiki目前只列出了一个扩展名,不支持Mesa <= 10.5.9(可能更高)。以下是从最完整功能的扩展名(在OpenGL wiki中列出)到最少的列表:
设置每个绘制区域的交换间隔: glXSwapIntervalEXT(dpy, drawable, interval)
获取当前交换间隔: glXQueryDrawable(dpy, drawable, GLX_SWAP_INTERVAL_EXT, &interval)
获取最大交换间隔: glXQueryDrawable(dpy, drawable, GLX_MAX_SWAP_INTERVAL_EXT, &maxInterval)
禁用垂直同步:将interval
设置为0
设置每个上下文的交换间隔: glXSwapIntervalMESA(interval)
获取当前交换间隔: glXGetSwapIntervalMESA()
获取最大交换间隔: 不支持
禁用垂直同步:将interval
设置为0
设置交换间隔: glXSwapIntervalSGI(interval)
.
获取当前交换间隔: 不支持
获取最大交换间隔: 不支持
禁用垂直同步:不支持(interval==0
是错误的)
有关自适应垂直同步,请参见OpenGL wiki。
((BOOL(WINAPI*)(int))wglGetProcAddress("wglSwapIntervalEXT"))(1);
https://www.khronos.org/opengl/wiki/Swap_Interval
使用wglSwapIntervalEXT(1)启用垂直同步;使用wglSwapIntervalEXT(0)禁用垂直同步。
交换间隔为1告诉GPU在交换前等待 1 个垂直消隐期。交换间隔为0指定GPU不应等待垂直消隐期。
或者:#include <GL/wglext.h>
中定义了wgl函数类型。
((PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT"))(1);
PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT");
wglSwapIntervalEXT(1);
关于WGL案例的描述,请参考eugensk的回答。
如果遇到nullptr错误,请确保在OpenGL上下文中运行{wglGetProcAddress
}部分的代码。
即在代码{glfwMakeContextCurrent(window);
}之后。
请查看此处的答案。