Как включить вертикальную синхронизацию в 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) до минимума:
Установите интервал обмена для каждого элемента отображения:
glXSwapIntervalEXT(dpy, drawable, interval)
Получить текущий интервал обмена:
glXQueryDrawable(dpy, drawable, GLX_SWAP_INTERVAL_EXT, &interval)
Получить максимальный интервал обмена:
glXQueryDrawable(dpy, drawable, GLX_MAX_SWAP_INTERVAL_EXT, &maxInterval)
Отключить Vsync: установить
interval
до 0
Установите интервал обмена для контекста:
glXSwapIntervalMESA(interval)
Получить текущий интервал обмена:
glXGetSwapIntervalMESA()
Получить максимальный интервал обмена: не поддерживается
Отключить Vsync: установить
interval
до 0
Установить интервал обмена:
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);
}.
Смотрите ответ здесь .