ПрограммированиеПодсказкиГрафика

Создание контекста OpenGL 3.0

Автор:

Здесь покажу как создать контекст OpenGL 3.0, кодом и комментариями.

Допустим, к этому моменту у нас уже есть созданное окно со своим контекстом hDC. Для создания контекста OpenGL 3.0 необходимо получить функцию расширения, которую можно получить только имея существующий OpenGL контекст, поэтому необходимо создать временный контекст старым способом:

HGLRC hTempRC = wglCreateContext(hDC);
if (!hTempRC)
{
  LOG_ERROR("Creating temporary render context fail (%d)\n", GetLastError());
  return false;
}
if (!wglMakeCurrent(hDC, hTempRC))
{
  LOG_ERROR("Selecting temporary render context fail (%d)\n", GetLastError());
  wglDeleteContext(hTempRC);
  return false;
}

Далее необходимо определить параметры для вызова функции создания контекста OpenGL 3.0:

typedef HGLRC (APIENTRYP PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC,HGLRC, const int *);

PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL;

int attributes[] =
{
  WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
  WGL_CONTEXT_MINOR_VERSION_ARB, 0,
  WGL_CONTEXT_FLAGS_ARB,         WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
  0
};

Загрузим требуемую функцию расширения:

wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)
  wglGetProcAddress("wglCreateContextAttribsARB");

if (NULL == wglCreateContextAttribsARB)
{
  LOG_ERROR("Load wglCreateContextAttribsARB fail\n");
  wglDeleteContext(hTempRC);
  return false;
}

Теперь создаем искомый контекст:

HGLRC hRC = wglCreateContextAttribsARB(hDC, 0, attributes);
if (!hRC)
{
  LOG_ERROR("Creating render context fail (%d)\n", GetLastError());
  wglDeleteContext(hTempRC);
  return false;
}
if (!wglMakeCurrent(hDC, hRC))
{
  LOG_ERROR("Selecting render context fail (%d)\n", GetLastError());
  wglDeleteContext(hTempRC);
  wglDeleteContext(hRC);
  return false;
}

wglDeleteContext(hTempRC);

Все, теперь у нас на руках hRC — полноценный контекст OpenGL 3.0. Далее загружайте все необходимые расширения и начинайте работу.

PS. Можно еще узнать немного полезной информации:

LOG_MSG("OpenGL 3.0 render context information:\n");

LOG_MSG("Renderer     : %s\n", (const char*)glGetString(GL_RENDERER));

LOG_MSG("Vendor       : %s\n", (const char*)glGetString(GL_VENDOR));

LOG_MSG("Version      : %s\n", (const char*)glGetString(GL_VERSION));

LOG_MSG("GLSL version : %s\n", (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION));

LOG_MSG("\n");

Следует отметить, что функция glGetString с аргументом GL_EXTENSIONS в контексте OpenGL 3.0 не работает.
Её вызов может привести к падению приложения.

Чтобы узнать о доступных расширениях, теперь следует использовать следующие команды:
glGetIntegerv с аргументом GL_NUM_EXTENSIONS - вернёт количество расширений доступных в созданном контексте;
glGetStringi с аргументом GL_EXTENSIONS - вернёт указатель на строку с расширением под указанным номером.

Например:

  int  num;
  glGetIntegerv(GL_NUM_EXTENSIONS, &num);
  for(int i = 0; i < num; i++)  (const char*)glGetStringi(GL_EXTENSIONS, i);

Можно также вести диагностику версии созданного контекста через следующие вызовы:

  int  major,  minor;
  glGetIntegerv(GL_MAJOR_VERSION, &major);
  glGetIntegerv(GL_MINOR_VERSION, &minor);

Не рекомендуется создавать FORWARD_COMPATIBLE_CONTEXT, чтобы получить прирост производительности.
Разработчики драйверов утверждают, что разницы по сравнению с регулярным контекстом не будет.

PPS. Если вам нужен контекст OpenGL 3.1, 3.2, 3.x то, соответственно, замените в attributes
WGL_CONTEXT_MINOR_VERSION_ARB на 1, 2, x.

Источники:
[1] На основе заметки Пример работы с OpenGL 3
[2] Информация по wglCreateContextAttribsARB
[3] Полезный документ от AMD Introduction to OpenGL 3.0

#C, #OpenGL

14 октября 2009 (Обновление: 12 ноя 2009)