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_dc: HDC;
Это - контекст устройства вывода. Всё дело в том, что для Windows нет никакой разницы, где осуществлять графический вывод, на окно программы, или, например,
на принтер. И там и там используется контекст устройства. Просто для каждого случая он уникален. Как его получить? Элементарно просто, зная хэндл окна и используя
всего одну функцию WinAPI:
Всё достаточно просто. Дальше будет чуть-чуть посложнее.
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
|