Как включить вертикальную синхронизацию в OpenGL?

Как включить вертикальную синхронизацию?

Это что-то простое, как glEnable(GL_VSYNC)? (хотя в опциях, которые принимает glEnable, нет такой вещи, как GL_VSYNC или что-то подобное).

или нет стандартного способа сделать это в opengl?

4 ответа

В 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 с X11 и т. Д.) Для этого существует как минимум 3 аналогичных расширения с различной степенью функциональности. OpenGL wiki в настоящее время перечисляет только один, который не поддерживается Mesa <= 10.5.9 (и, возможно, выше). Вот список от большинства полнофункциональных расширений (перечисленных в вики OpenGL) до минимума:

  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)

    • Отключить Vsync: установить interval до 0

  2. GLX_MESA_swap_control

    • Установите интервал обмена для контекста: glXSwapIntervalMESA(interval)

    • Получить текущий интервал обмена: glXGetSwapIntervalMESA()

    • Получить максимальный интервал обмена: не поддерживается

    • Отключить Vsync: установить interval до 0

  3. GLX_SGI_swap_control

    • Установить интервал обмена: glXSwapIntervalSGI(interval),

    • Получить текущий интервал обмена: не поддерживается

    • Получить максимальный интервал обмена: не поддерживается

    • Отключить Vsync: не поддерживается (interval==0 это ошибка)

Для адаптивного Vsync см. Вики OpenGL.

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

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

"wglSwapIntervalEXT (1) используется для включения vsync; wglSwapIntervalEXT(0) для отключения vsync."

"Интервал перестановки, равный 1, говорит графическому процессору, что нужно подождать один v-пробел перед заменой переднего и заднего буферов. Интервал перестановки, равный 0, указывает, что GPU никогда не должен ждать v-пробелов".

Для случая WGL, описанного в ответе eugensk.

Если вы столкнулись с ошибкой nullptr, убедитесь, что вы используете { wglGetProcAddress} часть кода в контексте OpenGL.

т.е. после кодов { glfwMakeContextCurrent(window);}.

Смотрите ответ здесь .

Другие вопросы по тегам