Главная
Статьи
Исходники
Гостевая книга
enZGLine
Галерея
Контакт
О себе







OpenGL. Основы

Инициализация

Итак, начнём. Изначально я предполагаю, что вы знаете, что такое Delphi, и с чем его едят. А OpenGL использовать не умеете, хотя, это не надолго.

А что такое, этот самый OpenGL? Это - библиотека высокоэффективного рендеринга на экране монитора. Но просто рисовать на мониторе у вас не получится. Нужно окно, на котором вы будете рисовать. Итак, какие переменные для инициализации необходимы:
var
  h_wnd: HWND;
  h_dc: HDC;
  pfd: TPixelFormatDescriptor;
  h_glrc: HGLRC;

И незабудьте, что в вашей программе, в разделе uses должны быть подключены модули OpenGL и Windows!!!

А теперь, о том, что же это за переменные мы описали.

h_wnd: HWND;
Эта переменная являет собой идентефикатор окна в операционной системе. Фактически, когда Windows "общается" с окном вашей программы, используется именно эта величина. Окно в вашей программе есть ничто иное, как компонент TForm. Чтобы получить его HWND достаточно обратится к его свойству Handle.
  h_wnd := Form1.Handle;

Отлично, хэндл окна получен. Поехали дальше.

h_dc: HDC;
Это - контекст устройства вывода. Всё дело в том, что для Windows нет никакой разницы, где осуществлять графический вывод, на окно программы, или, например, на принтер. И там и там используется контекст устройства. Просто для каждого случая он уникален. Как его получить? Элементарно просто, зная хэндл окна и используя всего одну функцию WinAPI:
  h_dc := GetDC(h_wnd);

Всё достаточно просто. Дальше будет чуть-чуть посложнее.

pfd: TPixelFormatDescriptor; Вот тут придётся поднапрячься. Работать прийдётся с целой структурой (в терминах Delphi - записью, record)
function InitPFD: boolean;
var
  nPixelFormat: integer;
begin
  ZeroMemory(@pfd,sizeof(pfd));
  result := false;
  with pfd do
  begin

    nSize := sizeof(pfd);
    nVersion := 1;
    dwFlags := PFD_DOUBLEBUFFER or PFD_SUPPORT_OPENGL or PFD_DRAW_TO_WINDOW;
    iPixelType := PFD_TYPE_RGBA;
    iLayerType := PFD_MAIN_PLANE;
    cColorBits := 32;
  end;
  nPixelFormat := ChoosePixelFormat(h_dc,@pfd);
  if nPixelFormat = 0 then
    exit;
  SetPixelFormat(h_dc,nPixelFormat,@pfd);
  result := true;
end;


Вся эта процедура создаёт пригодный для текущего контекста устройства формат пикселя. Если такой формат не найден, то функция вернёт значение false, в противном случае true. А теперь по шагам, что мы делали:
ZeroMemory(@pfd,sizeof(pfd));
Таким образом мы полностью заполнили структуру нулями, дабы в неё не попал какой-либо хлам.
nSize := sizeof(pfd);
Поле размера самой структуры. Никогда не забывайте его заполнять, иначе формат пикселя не будет найден корректно.
nVersion := 1;
Установка версии формата пиксла.
dwFlags := PFD_DOUBLEBUFFER or PFD_SUPPORT_OPENGL or PFD_DRAW_TO_WINDOW;
Самое интересное. Комбинация флагов.
PFD_DOUBLEBUFFER означает, что в программе будет использоватся режим двойной буфферизации. А что это означает? Это значит, что рисование будет осуществлятся не сразу на поверхность окна, а в "задний буфер", что, разумеется, происходит гораздо быстрее. Потом, в завершении прорисовки заднего буфера он станет передним, и разом будет осуществлён вывод на экран. А передний буфер, в свою очередь, станет задним. Такой подход очень сильно увеличивает скорость отрисовки приложения.
PFD_SUPPORT_OPENGL значит, что этот формат пикселя будет поддерживать OpenGL.
PFD_DRAW_TO_WINDOW Как видно из названия, вывод будет осуществлятся на окно.
iPixelType := PFD_TYPE_RGBA;
Тип пикселя, его формат. В данном случае RGBA (red, green, blue, alpha)
iLayerType := PFD_MAIN_PLANE;
Тип поверхности рендеринга. Как видно, становлена первичная поверхность.
cColorBits := 32;
Количество цветовых бит на один пиксел.
Далее, идёт проверка и установка формата пикселя:
nPixelFormat := ChoosePixelFormat(h_dc,@pfd);
if nPixelFormat = 0 then
  exit;
SetPixelFormat(h_dc,nPixelFormat,@pfd);

Функция WinAPI ChoosePixelFormat проверяет, возможно ли установить запрашиваемый формат пиксела. Если она возвращает ненулевое значение, то установка формата происходит функцией SetPixelFormat.

Так, с форматом пикселя вроде разобрались. Далее необходимо получить контекст воспроизведения h_glrc. Этот тип, в отличие от предыдущих специфичен именно для библиотеки OpenGL. Эта переменная необходима для использования любой команды OpenGL в вашей программе. Код её получения очень прост:
  h_glrc := wglCreateContext(h_dc);
  wglMakeCurrent(h_dc,h_glrc);

Как видно из кода, весь процесс создания контекста очень прост: сначала создали контекст, потом сделали его текущим.

Освобождение ресурсов

Ну, тут всё гораздо проще. Порядок действий прост:
I. Сделать текущим нулевой контекст
II. Уничтожить контекст воспроизведения
III. Освободить контекст устройства
Код:
  wglMakeCurrent(0,0);
  wglDeleteContext(h_glrc);
  ReleaseDC(h_wnd,h_dc);

Рисование в окне

Отлчно, с инициализацией и уничтожением OpenGL разобрались, теперь давайте попробуем закрасить окно другим цветом.
Код рисования:
  glClearColor(0,0,0,0);
  glClear(GL_COLOR_BUFFER_BIT);
  SwapBuffers(h_dc);

Обработку этого кода лучше всего записать в событие OnPaint формы.
А теперь, давайте разберёмся с каждой функцией отдельно.
  glClearColor(0,0,0,0);
Эта функция определяет, каким цветом будет перекрашет задний буфер. Все параметры этой функции являются числами с плавающей запятой типа single. т. е. для перекрашивания окна в красный цвет необходимо написать
  glClearColor(1.0,0,0,0);
  glClear(GL_COLOR_BUFFER_BIT);
Эта функция осуществляет перерисовку буфера заданным цветом.
  SwapBuffers(h_dc);
А эта функция меняет местами текущий буфер и задний. На этом, статью считаю оконченой, в следующей статье постараюсь рассказать о том, как рисовать примитивы.
Примеры к этой статье:
исходник бинарник

Автор: Zealot









Hosted by uCoz