43

如何启用垂直同步?

是不是很简单glEnable(GL_VSYNC)?(尽管在 glEnable 接受的选项中没有 GL_VSYNC 或类似的东西)。

或者在opengl中没有标准的方法来做到这一点?

4

4 回答 4

45

在 Windows 上有 OpenGL 扩展方法wglSwapIntervalEXT。来自 b2b3 http://www.gamedev.net/community/forums/topic.asp?topic_id=360862的帖子:

如果您在 Windows 上工作,则必须使用扩展才能使用 wglSwapIntervalExt功能。它在 wgext.h 中定义。您还需要下载 glext.h 文件。在 wgext 文件中声明了 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().

于 2009-02-26T05:33:28.753 回答
6

WGL案例在eugensk00 的答案中进行了描述。

对于CGL (MacOSX),请参阅另一个 SO question 的答案。

对于EGL,有eglSwapInterval()函数,但显然(参见thisthis)它不能保证无撕裂的结果——只能等待给定的时间段(可能只是由于驱动程序损坏)。

对于GLX(带有 X11 等的 Linux),至少有 3 个类似的扩展,具有不同程度的功能。OpenGL wiki 当前只列出了一个,Mesa <= 10.5.9(可能更高)不支持。这是从功能最完整的扩展(在 OpenGL wiki 中列出)到最少的列表:

  1. GLX_EXT_swap_control

    • 设置每个可绘制每个显示的交换间隔:glXSwapIntervalEXT(dpy, drawable, interval)

    • 获取当前交换间隔:glXQueryDrawable(dpy, drawable, GLX_SWAP_INTERVAL_EXT, &interval)

    • 获取最大交换间隔:glXQueryDrawable(dpy, drawable, GLX_MAX_SWAP_INTERVAL_EXT, &maxInterval)

    • 禁用垂直同步:设置interval为 0

  2. GLX_MESA_swap_control

    • 设置每个上下文的交换间隔:glXSwapIntervalMESA(interval)

    • 获取当前交换间隔:glXGetSwapIntervalMESA()

    • 获取最大交换间隔:不支持

    • 禁用垂直同步:设置interval为 0

  3. GLX_SGI_swap_control

    • 设置交换间隔:glXSwapIntervalSGI(interval)

    • 获取当前交换间隔:不支持

    • 获取最大交换间隔:不支持

    • 禁用垂直同步:不支持interval==0错误)

对于自适应 Vsync,请参阅OpenGL wiki

于 2016-08-12T09:43:06.560 回答
5
((BOOL(WINAPI*)(int))wglGetProcAddress("wglSwapIntervalEXT"))(1);

https://www.khronos.org/opengl/wiki/Swap_Interval

“wglSwapIntervalEXT(1) 用于启用 vsync;wglSwapIntervalEXT(0) 用于禁用 vsync。”

“交换间隔 1 告诉 GPU 在交换前后缓冲区之前等待一个 v-blank。交换间隔 0 指定 GPU 永远不应等待 v-blank”


或者:(wgl 函数类型定义在#include <GL/wglext.h>

((PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT"))(1);
PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT");
wglSwapIntervalEXT(1);
于 2019-03-22T23:52:51.637 回答
0

对于eugensk 的答案中描述的 WGL 案例。

如果遇到 nullptr 错误,请确保您wglGetProcAddress在 OpenGL 上下文中运行 { } 部分代码。

即在代码{ glfwMakeContextCurrent(window);}之后。

在这里查看答案。

于 2022-01-30T09:12:40.313 回答