Статья
Версия для печати
Обсудить на форуме
OpenGL (часть 2)


Как я и обещал, мы продолжаем наш нелегкий путь изучения OpenGl.

В данном уроке научимся создавать OpenGl приложения, работающие под Windows. Возможно, в будущем, я посвящу пару уроков работе OpenGl под Linux.

Так как OpenGl независима от платформы (что мне очень нравится в отличие от Direct3D), то инициализацию обеспечивает сама OS. Для этого нам необходимо заполнить несколько структур и вызвать пару функций WINAPI.

Заполняем описатель пиксельного формата устройства контекста: PIXELFORMATDESCRIPTOR.Здесь мы указываем, сколько бит необходимо выделить под каждое значение цвета, буфер глубины и т.д.
Код:
   // Создадим объект типа PIXELFORMATDESCRIPTOR полностью нулевого значения.
   PIXELFORMATDESCRIPTOR pfd = {0};

   // Всегда необходимо заполнять поле nSize в размер структуры PIXELFORMATDESCRIPTOR;
   pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);

Необходимо выставить требуемые флаги в dwFlags. Поскольку мы будем выводить графические объекты в окно, выставляем флаг PFD_DRAW_TO_WINDOW-*, указываем ,что буфер кадра поддерживает вывод через OpenGl - PFD_SUPPORT_OPENGL, так как мы используем два буфера (back and front), то устанавливаем флаг PFD_DOUBLEBUFFER.
Код:
   pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;

В поле iPixelType выставим PFD_TYPE_RGBA - это означает, что цвет для пикселя представляется в виде RGBA  (цветовые компоненты: R-красный, G- зеленый, B- голубой, A - альфа). Устанавливаем глубину цвета cColorBits в 32bpp.

Заполнив все поля, выполняем запрос на выбор подходящего формата. Делаем это с помощью функции ChoosePixelFormat. Если функция не возвратила ноль, можно установить данный формат функцией SetPixelFormat.

Итак мы можем уже создать нашу функцию:
Код:
bool SetPixelFormat(HDC hDC)
{
   int pixelformat;
   PIXELFORMATDESCRIPTOR pfd = {0};

   pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
   pfd.nVersion = 1;
   pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;
   pfd.iPixelType = PFD_TYPE_RGBA;
   pfd.cColorBits = 32;

   if (!(pixelformat = ChoosePixelFormat(hDC, &pfd))) return false;
   if (!SetPixelFormat(hDC, pixelformat, &pfd)) return false;

   return true;
}

Если нам удалось выставить пиксельный формат, дальше необходимо создать просчитывающий контекст (rendering context) OpenGl. Это делается вызовом функции wglCreateContext(). Далее, созданный контекст выставляется функцией wglMakeCurrent(). Теперь вы можете спокойно пользоваться функциями OpenGl!

Как видим, для инициализации OpenGl (в оконном режиме) нужно сделать совсем не много! Но не пугайтесь, не намного больше усилий надо приложить и для установки полноэкранного режима! По окончанию работы необходимо освободить все занятые ресурсы: освободить контекст - wglMakeCurrent() и разрушить этот контекст wglDeleteContext().

Что ж, напишем модуль, который позволит нам работать с OpenGl:
Код:
#include
#include

   HWND hWnd;
   HDC hDC;
   HGLRC hRC;

   bool InitGl(HWND a _hWnd);

   void DoneGl(void);

   bool SetPixelFormat(HDC a_hDC);

bool InitGl(HWND a_hWnd)
{
   hWnd = a_hWnd;
   hDC = GetDC(hWnd);
   if (!SetPixelFormat(hDC)) return false;
   hRC = wglCreateContext(hDC);
   wglMakeCurrent(hDC, hRC);
   return true;
}

void DoneGl(void)
{
   if (hRC)
   {
      wglMakeCurrent(hDC, 0);
      wglDeleteContext(hRC);
      hRC = NULL;
   }
   if (hDC)
   {
      ReleaseDC(hWnd, hDC);
      hDC = NULL;
   }
}

bool SetPixelFormat(HDC a_hDC)
{
   int pixelformat;
   PIXELFORMATDESCRIPTOR pfd = {0};
   pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
   pfd.nVersion = 1;
   pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;
   pfd.iPixelType = PFD_TYPE_RGBA;
   pfd.cColorBits = 32;

   if (!(pixelformat = ChoosePixelFormat(a_hDC, &pfd))) return false;
   if (!SetPixelFormat(a_hDC, pixelformat, &pfd)) return false;

   return true;
}

Теперь для работы Вам необходимо просто вызвать функцию InitGl, указав идентификатор окна.

В конце работы не забывайте вызвать DoneGl(). Как все просто! 
Версия для печати
Обсудить на форуме