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

发布于 2024-07-14 14:16:36 字数 149 浏览 9 评论 0原文

如何启用垂直同步?

它是像 glEnable(GL_VSYNC) 这样简单的东西吗? (尽管 glEnable 接受的选项中没有 GL_VSYNC 或类似的东西)。

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

How do you enable vertical sync?

Is it something simple like glEnable(GL_VSYNC)? (though there's no such thing as GL_VSYNC or anything like it in the options that glEnable accepts).

or is there no standard way to do this in opengl?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

屋顶上的小猫咪 2024-07-21 14:16:36

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

如果您在 Windows 上工作,则必须使用扩展才能使用
wglSwapIntervalExt 函数。 这是
在 wgext.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()

On Windows there is OpenGL extension method wglSwapIntervalEXT.
From the post by b2b3 http://www.gamedev.net/community/forums/topic.asp?topic_id=360862:

If you are working on Windows you have to use extensions to use
wglSwapIntervalExt function. It is
defined in wglext.h. You will also want to
download glext.h file.
In wglext file all entry points for Windows specific extensions are
declared. All such functions start
with prefix wgl.
To get more info about all published extensions you can look into
OpenGL Extension Registry.

wglSwapIntervalEXT is from WGL_EXT_swap_control extension. It
lets you specify minimum number of
frames before each buffer swap.
Usually it is used for vertical
synchronization (if you set swap
interval to 1). More info about whole
extension can be found here.
Before using this function you need query whether you card has
support for WGL_EXT_swap_control and
then obtain pointer to the function
using wglGetProcAddress function.

To test for support of given extension you can use function like this:

#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;
}

To initialize your function pointers you need to:

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");
}

Then you can use these pointers as any other pointer to function. To enable vync you can call wglSwapIntervalEXT(1), to disable it you call wglSwapIntervalEXT(0).

To get current swap interval you need to call wglGetSwapIntervalEXT().

他夏了夏天 2024-07-21 14:16:36

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

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

    • 禁用垂直同步:将间隔设置为 0

  2. GLX_MESA_swap_control

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

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

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

    • 禁用垂直同步:将间隔设置为 0

  3. GLX_SGI_swap_control

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

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

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

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

有关自适应垂直同步,请参阅OpenGL 维基

WGL case is described in the answer by eugensk00.

For CGL (MacOSX) see this answer to another SO question.

For EGL there's eglSwapInterval() function, but apparently (see this and this) it doesn't guarantee tearing-free result — only waits given period (maybe it's just due to broken drivers).

For GLX (Linux with X11 etc.) there are at least 3 similar extensions for this, with varying degree of functionality. OpenGL wiki currently lists only one, which is unsupported by Mesa <= 10.5.9 (and maybe higher). Here's a list from most feature-complete extension (listed in OpenGL wiki) to the least:

  1. GLX_EXT_swap_control

    • Set swap interval per-drawable per-display: glXSwapIntervalEXT(dpy, drawable, interval)

    • Get current swap interval: glXQueryDrawable(dpy, drawable, GLX_SWAP_INTERVAL_EXT, &interval)

    • Get maximum swap interval: glXQueryDrawable(dpy, drawable, GLX_MAX_SWAP_INTERVAL_EXT, &maxInterval)

    • Disable Vsync: set interval to 0

  2. GLX_MESA_swap_control

    • Set swap interval per-context: glXSwapIntervalMESA(interval)

    • Get current swap interval: glXGetSwapIntervalMESA()

    • Get maximum swap interval: unsupported

    • Disable Vsync: set interval to 0

  3. GLX_SGI_swap_control

    • Set swap interval: glXSwapIntervalSGI(interval).

    • Get current swap interval: unsupported

    • Get maximum swap interval: unsupported

    • Disable Vsync: unsupported (interval==0 is an error)

For adaptive Vsync see OpenGL wiki.

恋竹姑娘 2024-07-21 14:16:36
((BOOL(WINAPI*)(int))wglGetProcAddress("wglSwapIntervalEXT"))(1);

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

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

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


或者:(wgl 函数 typedef 位于 <代码>#include)

((PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT"))(1);
PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT");
wglSwapIntervalEXT(1);
((BOOL(WINAPI*)(int))wglGetProcAddress("wglSwapIntervalEXT"))(1);

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

"wglSwapIntervalEXT(1) is used to enable vsync; wglSwapIntervalEXT(0) to disable vsync."

"A swap interval of 1 tells the GPU to wait for one v-blank before swapping the front and back buffers. A swap interval of 0 specifies that the GPU should never wait for v-blanks"


Alternatively: (wgl function typedefs are in #include <GL/wglext.h>)

((PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT"))(1);
PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT");
wglSwapIntervalEXT(1);
芯好空 2024-07-21 14:16:36

对于 eugensk 的回答中描述的 WGL 情况。

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

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

请参阅此处的答案

For WGL case described in the answer by eugensk.

If you run into a nullptr error, make sure you are running {wglGetProcAddress} part code in an OpenGL Context.

i.e. after codes {glfwMakeContextCurrent(window);}.

See answer here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文