如何在opengl中启用垂直同步?

has*_*sen 36 opengl vertical-sync vsync

你如何启用垂直同步?

它简单glEnable(GL_VSYNC)吗?(虽然在glEnable接受的选项中没有GL_VSYNC或类似的东西).

或者在opengl中没有标准的方法吗?

eug*_*nsk 42

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

如果您在Windows上工作,则必须使用扩展来使用 wglSwapIntervalExt功能.它在wgle​​xt.h中定义.您还需要下载glext.h文件.在wgle​​xt文件中,声明了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;
}
Run Code Online (Sandbox Code Playgroud)

要初始化函数指针,您需要:

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");
}
Run Code Online (Sandbox Code Playgroud)

然后你可以使用这些指针作为任何其他指向函数的指针.要启用vync,您可以呼叫wglSwapIntervalEXT(1),禁用它wglSwapIntervalEXT(0).

要获得当前的交换间隔,您需要调用wglGetSwapIntervalEXT().

  • 我还使用了wglGetProcAddress而不是LogGetProcAddress (4认同)
  • 在你的第一个代码片段中,如果(strstr(_wglGetExtensionsString(),extension_name)== NULL)应该读取(strstr(_wglGetExtensionsStringEXT(),extension_name)== NULL) - 但是谢谢,这对我有帮助! (3认同)
  • 这不是OpenGL的扩展,而是WGL(OpenGL的Microsoft Windows窗口系统API)的扩展.缓冲区交换本质上是一种窗口系统特定操作.就GL来说,它只是绘制到前/后左/右缓冲区或一些任意FBO.窗口系统是唯一具有足够的底层主机系统知识的东西,用于将绘制缓冲区的呈现与某些事件同步(在这种情况下是监视器的垂直回扫). (3认同)

Rus*_*lan 6

eugensk00答案中描述了WGL案例。

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

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

对于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


Pud*_*dle 5

((BOOL(WINAPI*)(int))wglGetProcAddress("wglSwapIntervalEXT"))(1);
Run Code Online (Sandbox Code Playgroud)

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

“wglSwapIntervalEXT(1) 用于启用垂直同步;wglSwapIntervalEXT(0) 用于禁用垂直同步。”

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


或者:(wgl 函数 typedef 位于 中#include <GL/wglext.h>

((PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT"))(1);
Run Code Online (Sandbox Code Playgroud)
PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT");
wglSwapIntervalEXT(1);
Run Code Online (Sandbox Code Playgroud)