Подключение библиотеки OpenGL в Delphi

СОДЕРЖАНИЕ

ВВЕДЕНИЕ__________________________________________________2стр.

      1.   Раздел 1 “Windows-приложения“_____________________5стр.

            1.1. Событие, сообщение, ссылка ___________________________5стр.

             1.2.  Перехват сообщений_________________________________10стр.

      2.   Раздел 2 “Подключение OpenGL”_____________________17стр.

             2.1. Минимальная программа OpenGL_____________________17стр.                              

             2.2. Вывод на компоненты Delphi средствами OpenGL _______27стр.

     Вывод_____________________________________________________41стр.

     Список литературы ____________________________________42стр.

 

 

 

 

 

 

 

 

 

Введение

Эта работа посвящена  компьютерной графике, а именно тому, как использовать OpenGL в Delphi. OpenGL - это стандартная библиотека для всех 32-разрядных операционных систем, в том числе и для операционной системы Windows. OpenGL - не отдельная программа, а часть операционной системы. Это означает, что откомпилированное приложение, использующее OpenGL, не нуждается ни в каких дополнительных программах и модулях, кроме стандартных, содержащихся на любом компьютере с установленной операционной системой Windows 95 версии OSR2 и выше. Вообще говоря, в этой курсовой работе идет речь о программировании приложений, использующих графический акселератор, однако все приводимые программы будут работать и на компьютере, не оснащенном ускорителем. Для программистов, использующих язык С, существует множество источников, из которых можно почерпнуть сведения о том, как использовать библиотеку OpenGL, для программистов же, работающих с Delphi, таких источников крайне мало. Данная работа призвана восполнить этот недостаток информации. В состав стандартной поставки Delphi (начиная с третьей версии) входит заголовочный файл, позволяющий строить приложения с использованием OpenGL, a также справочный файл по командам этой библиотеки. Однако инсталляция Delphi не снабжается ни одним примером по использованию OpenGL, a из файла справок новичку трудно понять, как это сделать. Поэтому основная цель курсовой работы - помочь программистам, в том числе и опытным, разобраться в этой теме. Многие примеры в работе представляют собой "перевод" свободно распространяемых программ, изначально написанных на С.

 

 

 

Хотелось бы отметить следующие особенности курсовой работы:

1. Отсутствует описание математического аппарата компьютерной графики.

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

2. Эта курсовая  работа не заменит документации  по OpenGL или Delphi. Есть довольно много книг, представляющих собой просто перевод содержимого файлов оперативной помощи. Может быть, кому-то такие переводы и нужны, но только не программистам, для которых знание английского языка является необходимым условием профпригодности. Как правило, я ограничиваюсь краткими замечаниями, позволяющими понять суть излагаемой темы, а подробности всегда можно найти в справочных файлах.

3. Работа рассчитана  на новичка в области машинной  графики, но не новичка в  программировании на Delphi. При изложении материала подразумевается, что читатель имеет навыки работы в Delphi, и чем увереннее он чувствует себя здесь, тем больше пользы сможет извлечь из этой работы. Heкоторые разделы, например функции API, могут показаться поначалу трудными. Однако в подавляющей части примеров особо сложные приемы программирования не используются, и они достаточно легко поддаются освоению.

               

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Раздел 1 “Windows-приложения“

Здесь дается представление о том, как в действительности работает Windows-приложение. Для понимания действий, требуемых для подключения OpenGL, необходимо иметь представление о важнейших понятиях операционной системы Windows, завуалированных в Delphi и напрямую обычно не используемых программистом. В качестве примера подробно разбирается минимальная программа, использующая OpenGL.

1.1. Событие, сообщение, ссылка

С понятием "событие" знаком каждый программист, использующий Delphi. Термин "сообщение" напрямую в концепции Delphi не используется. Код, написанный в проекте Delphi как обработчик события OnCreate, выполняется при получении приложением сообщения WM_CREATE, сообщению WM_PAINT соответствует событие OnPaint и т.д. Такие события - аналоги сообщений операционной системы - используют мнемонику, сходную с мнемоникой сообщений, т.e. сообщения начинаются с префикса "WM_" (Windows Message), a аналогичные события начинаются с префикса "On". Для того чтобы операционная система могла различать окна для осуществления диалога с ними, все окна при своем создании регистрируются в опе- рационной системе и получают уникальный идентификатор, называемый "ссылка на окно". Тип этой величины в Delphi - HWND (Handle WiNDow). Синонимом термина "ссылка" является дескриптор. Ссылка на окно может использоваться не только операционной системой, но и приложениями для идентификации окна, с которым необходимо производить манипуляции. Попробуем проиллюстрировать смысл ссылки на окно на несложном примере. Откомпилируйте минимальное приложение Delphi и начните новый проект. Форму назовите Form2, разместите на ней кнопку.

Теперь при нажатии кнопки выдается сообщение, открыто ли окно класса, зарегистрированного в операционной системе как 'TForml1', имеющее заголовок 'Form1'. Если одновременно запустить обе наши программы, то при нажатии кнопки будет выдано одно сообщение, а если окно с заголовком 'Form1' закрыть, то другое. Здесь мы используем функцию FindWindow, возвращающую величину типа HWND - ссылку на найденное окно либо ноль, если такое окно не найдено. Аргументы функции - класс окна и его заголовок. Если заголовок искомого окна безразличен, вторым аргументом нужно задать nil. Итак, ссылка на окно однозначно определяет окно. Свойство Handle формы и есть эта ссылка, а тип THandle в точности соответствует типу HWND, так что в предыдущем примере переменную Н можно описать как переменную типа THandle. Рассмотрим подробнее некоторые выводы. Класс окна минимального приложения, созданного в Delphi, имеет значение 'TForm1', что полностью соответствует названию класса формы в проекте. Следовательно, то, как мы называем формы в проектах Delphi, имеет значение не только в период проектирования приложения, но и во время его работы. Начните новый проект, назовите форму каким-нибудь очень длинным именем и откомпилируйте проект. Сравните размер откомпилированного модуля с размером самого первого проекта, и убедитесь, что он увеличился - вырос только за счет длинного имени класса. Также очень важно уяснить, что, если вы собираетесь распространять какие-либо приложения, необходимо взять за правило называть формы отлично от значения, задаваемого Delphi по умолчанию. Лучше, если эти названия будут связаны по смыслу с работой вашего приложения. Так, например, головную форму в примерах этой работы я буду называть, как правило, frmGL. Имея ссылку на окно, операционная система общается с ним путем посылки сообщений - сигналов о том, что произошло какое-либо событие, имеющее отношение именно к данному окну. Если окно имеет намерение отреагировать на событие, операционная система совместно с окном осуществляет эту реакцию.Окно может и, не имея фокус, получать сообщения и реагировать на них.

При движении курсора  мыши в заголовке формы выводятся  его координаты. Запустите два экземпляра программы и обратите внимание, что окно, не имеющее фокус, т. е. неактивное, тоже реагирует на перемещение указателя по своей поверхности и выводит в заголовке текущие координаты курсора в своей системе координат. Имея ссылку на окно, приложение может производить с ним любые (почти) действия путем посылки ему сообщений. Если имеется окно класса 'TForm1' с заголовком 'Form1', наше приложение посылает ему сообщение WM_CLOSE - пытается закрыть окно. Для посылки сообщения используем функцию операционной системы (функцию API) SendMessage. Функция postMessage имеет сходное назначение, но отличается тем, что не дожидается, пока посланное сообщение будет отработано. У этих функций четыре аргумента - ссылка на окно, которому посылаем сообщение, константа, соответствующая посылаемому сообщению, и два параметра сообщения, смысл которых определяется в каждом конкретном сообщении по-своему. Параметры сообщения называются wParam и lParam. При обработке сообщения WM_CLOSE эти значения никак не используются, поэтому здесь их можно задавать произвольно. Заметим, что одновременно могут быть зарегистрированы несколько окон класса 'TForm1', и необходимо закрыть их все. Пока наше приложение закрывает окна поодиночке при каждом нажатии на кнопку. Автоматизировать процесс можно разными способами, простейший из них используется в проекте подкаталога Ex04 и заключается в том, что вызов Findwindow заключен в цикл, работающий до тех пор, пока значение переменной H не станет равным нулю.

В заключение раздела, необходимо сказать, что ссылки, в зависимости от версии Delphi, соответствуют типам Integer или LongWord и описываются в модуле windows. pas.

 

 

Почему приложения Delphi имеют большой размер

Этот вопрос часто  задают начинающие программисты при  сравнении приложений, созданных  в различных средах программирования. Действительно, минимальное приложение, созданное в различных версиях Delphi, может достигать от 170 до 290 Кбайт. Это очень большая цифра для операционной среды Windows, в компиляторах C++ она составляет порядка 40 Кбайт. Конечно, это не катастрофическая проблема, когда емкости накопителей измеряются гигабайтами, и средний пользователь, как правило, не обращает внимания на размер файла. Неудобства возникают, например, при распространении приложений по сети. Использование пакетов значительно снимает остроту проблемы для масштабных проектов, но суммарный вес приложения и используемых пакетов все равно значителен. Краткий ответ на вопрос, поставленный в заголовке раздела, состоит в том, что большой размер откомпилированных приложений является платой за невероятное удобство проектирования, предоставляемое Delphi. Архитектура среды программирования, RTTI, компонентный подход - все это превращает Delphi в поразительно мощный инструмент. С помощью Delphi легко написать приложения, в которых, например, динамически создаются интерфейсные элементы любого типа (класса).

Программирование  на Delphi без VCL

После того как мы прикоснулись к основополагающим терминам и понятиям операционной системы Windows "сообщение" и "ссылка на окно", мы сможем опуститься ниже уровня объектно-ориентированного программирования, VCL и RAD-технологий. Требуется это по четырем причинам. Во-первых, приложения, активно использующие графику, чаще всего не нуждаются и не используют богатство библиотеки классов Delphi. Таким приложениям, как правило, достаточно окна в качестве холста, таймера и обработчиков мыши и клавиатуры. Во-вторых, при программировании, основанном только на использовании функций API, получаются миниатюрные приложения. Откомпилированный модуль не отягощается кодом описания компонентов и кодом, связанным с концепциями ООП. В-третьих, для понимания приемов, используемых для увеличения скорости воспроизведения, нужно иметь представление о подлинном устройстве Windows-программы. Например, чтобы команды перерисовки окна выполнялись быстрее, мы будем избегать использования методов Refresh и paint формы. В-четвертых, это необходимо для понимания действий, производимых для подключения OpenGL. Эта библиотека создавалась в эпоху становления ООП, и ее пока не коснулись последующие нововведения в технологии программирования.

Вывод с использованием функций GDI

В первом разделе мы рассмотрели, как, получив ссылку на чужое окно, можно производить с ним некоторые действия, например, закрыть его. Точно так же, если необходимо нарисовать что-либо на поверхности чужого окна, первым делом нужно получить ссылку на него. Для начала попробуем рисовать на поверхности родного окна. Разместите еще одну кнопку, обработку щелчка которой приведите к следующему виду:

procedure TForma2.

Button2Click(Sender: TObject);

var dc: HDC; // ссылка на контекст устройства

begin dc: = GetDC (Handle); // задаем значение ссылки

Rectangle (dc, 10, 10, 110, 110); // рисуем прямоугольник 

ReleaseDC (Handle, dc); // освобождение ссылки

DeleteDC (dc); // удаление ссьшки, освобождение памяти end;

Запустите приложение. После  щелчка на добавленной кнопке на поверхности  окна рисуется квадрат. Для рисования в этом примере используем низкоуровневые функции вывода Windows, так называемые функции GDI (Graphic Device Interface, интерфейс графического устройства). Эти функции требуют в качестве одного из своих аргументов ссылку на контекст устройства. Тип такой величины - hdc (Handle Device Context, ссылка на контекст устройства), значение ее можно получить вызовом функции API GetDC с аргументом-ссылкой на устройство вывода. В нашем примере в качестве аргумента указана ссылка на окно. После получения ссылки на контекст устройства обращаемся собственно к функции, строящей прямоугольник. Первым аргументом этой функции является ссылка на контекст устройства. После использования ссылки ее необходимо освободить, а в конце работы приложения - удалить для освобождения памяти.

1.2. Перехват сообщений

Большинство событий формы и  компонентов являются аналогами  соответствующих сообщений операционной системы. Конечно, не все сообщения имеют такие аналоги, поскольку их (сообщений) очень много, несколько сотен. С каждой новой версией Delphi y формы появляются все новые и новые свойства и события, благодаря чему программировать становится все удобнее, но зато размеры откомпилированного приложения все растут и растут.

Замечание 
          В угоду программистам, до сих пор использующим третью версию Delphi для получения сравнительно небольших по объему исполняемых модулей, все примеры данной книги я разрабатывал именно в этой версии, но все они прекрасно компилируются и в более старших версиях  У программистов всегда будет возникать потребность обрабатывать сообщения, не имеющие аналогов в списке событий, либо самостоятельно перехватывать сообщения, для которых есть аналоги среди событий формы и компонентов. Как увидим ниже, сделать это несложно. Например, мы программируем без VCL. Задача состоит в том, чтобы при двойном щелчке левой кнопкой мыши выводились текущие координаты указателя. Прежде всего, обратите внимание, что в стиль окна добавилась константа cs_Dblclks, чтобы окно могло реагировать на двойной щелчок, а оконная функция дополнилась обработкой сообщения wm_LButtonDblclk, в которой выводятся координаты курсора. Теперь создадим обработчик этого же сообщения в проекте Delphi обычного типа. Описание класса формы я дополнил разделом protected, в который поместил forward-описание соответствующей процедуры:

procedure MesDblClick (var MyMessage TWMMouse); message wm LButtonDblClk;

Замечание 
          Как правило, перехватчики сообщений для повышения надежности работы приложения описываются в блоке protected

Имя процедуры я задал таким, чтобы не появлялось предупреждение компилятора о том, что я перекрываю соответствующее событие формы. Служебное слово message указывает на то, что процедура будет перехватывать сообщение, мнемонику которого указывают за этим словом. Тип аргумента процедуры-перехватчика индивидуален для каждого сообщения. Имя аргумента произвольно, но, конечно, нельзя брать в качестве имени служебное СЛОВО message. Пожалуй, самым сложным в процессе описания перехвата сообщений является определение типа аргумента процедуры, здесь оперативная помощь оказывается малополезной. В четвертой и пятой версиях Delphi инспектор кода облегчает задачу, но незначительно. Чтобы решить эту задачу для сообщения wm_LButtonDblclk, я просмотрел все вхождения фразы "LButtonDblClk" в файле messages. pas и обнаружил строку, подсказавшую решение:

TWMLButtonDblClk = TWMMouse;

В этом же файле я нашел  описание структуры Twmouse, чем и воспользовался при кодировании процедуры MesDblclick для получения координат курсора. Обратите внимание, что здесь не пришлось самостоятельно разбивать, по словам значение параметра, как в предыдущем проекте. Итак, в рассматриваемом примере перехватывается сообщение "двойной щелчок левой кнопки мыши". Событие Dblclick формы наступает точно в такой же ситуации. Выясним, какая из двух процедур, перехватчик сообщения или обработчик события, имеет преимущество или же они равноправны. Создайте обработчик события OnDblclick формы - вывод любого тестового сообщения. Запустите проект, дважды щелкните на форме. Процедура-перехватчик среагирует первой и единственной, до обработчика события очередь не дойдет.

Замечание 
          Перехватчики сообщений приходится писать в тех случаях, когда в списке событий нет аналога нужного нам сообщения, а также тогда, когда важна скорость работы приложения. Обработка сообщений происходит быстрее обработки событий, поэтому именно этим способом мы будем пользоваться в приложениях, особенно требовательных к скорости работы в следующем проекте создан обработчик сообщения wmPaint - перерисовка окна:

protected 
          procedure WMPaint(var Msg: TWMPaint); message WM_PAINT; ...

procedure TForml. WMPaint(var Msg: TWMPaint);

var ps: TPaintStruct;

begin BeginPaint(Handle, ps);

Rectangle (Canvas. Handle, 10, 10, 100, 100);

EndPaint(Handle, ps);

end;

Строки Beginpaint и EndPaint присутствуют для  более корректной работы приложения, при их удалении появляется неприятное мерцание при изменении размеров окна Обратите внимание на функцию  построения прямоугольника: я воспользовался тем, что свойство canvas. Handle и есть ссылка на контекст устройства, соответствующая окну формы. Точно так же, как перехватчики сообщений предпочтительнее обработчиков событий, использование непосредственно ссылок на окно и ссылок на контекст устройства предпочтительнее использования их аналогов из мира ООП.

Работа с таймером

В этом разделе мы разберем, как  использовать таймер, основываясь только на функциях API. Поскольку вы наверняка умеете работать с компонентом класса TTimer, вам легко будет уяснить, как это делается на уровне функций API. Посмотрите простой пример, где с течением времени меняется цвет нарисованного кружочка. Первым делом замечаем, что блок описания констант дополнился описанием идентификатора таймера, в качестве которого можно взять любое целое число.

const 
          AppName = 'WinPaint';

id_Timer = 100; // идентификатор таймера

Идентифицировать таймер необходимо потому, что у приложения их может  быть несколько. Для включения таймера (то, что в привычном антураже соответствует Timerl. Enabled: = True) вызывается функция API SetTimer, где задается требуемый интервал таймера:

SetTimer (Window, id_Timer, 200, nil); // установка таймера

Сделал я это перед входом в цикл обработки сообщений, но можно  и при обработке сообщения WM_CREATE. Кстати, самое время сказать, что это сообщение обрабатывается в обход цикла обработки сообщений, поэтому таймер, включенный в обработчике WM_CREATE, начнет работать раньше. Оконная функция дополнилась обработкой сообщения, соответствующего такту таймера:

wm_Timer: InvalidateRect (Window, nil, False);

Как видим, работать с таймером, используя  только функции API, совсем не сложно. Компонент Delphi TTimer основывается на функциях и  сообщениях, которые мы только что  рассмотрели.

Работа с мышью и  клавиатурой

При нажатой левой кнопки мыши за указателем остается след. Оконная  функция дополнилась обработчиками  сообщений wm_LButtonDown, wm_LButtonUp И wm_MouseMove. Для определения координат курсора пользуемся тем, что поле iParam подобных сообщений содержит эти самые координаты.

Down: = not Down;

wm_Create: Down: = False;

wm_LButtonDown, wm_LButtonUp

wm_MouseMove:

begin If Down then begin xpos: = LoWord ( LParam);

ypos: = HiWord ( LParam); InvalidateRect(Window, nil, False); end; end;

wm_Paint: begin If Down then begin dc: = BeginPaint (Window, MyPaint);

Ellipse (dc, xPos, yPos, xPos + 2, yPos + 2);

EndPaint (Window, MyPaint); ReleaseDC (Window, dc);

end;

end; 
          Последнее, что мы рассмотрим в данном разделе и что обязательно потребуется в дальнейшем - это обработка клавиатуры. Оконная функция дополнилась обработчиком соответствующего сообщения

wm_Char: // анализ нажатой  клавиши

case wParam of $58, $78: If HiWord {GetKeyState (vk_Shift)) = 0 { Shift }  

then

MessageBox(Window, 'X', 'Нажата клавиша', MB_OK) else

MessageBox(Window, 'X вместе с Shift', 'Нажата клавиша', MB_OK);

end; // wm char

При нажатии клавиши 'X' выводится сообщение, в котором  указано, нажата ли одновременно клавиша <Shift>. Я использовал шестнадцатеричное  представление кода клавиши, но, конечно, можно использовать и десятичное. Надеюсь, здесь не требуются особые пояснения, и мы сможем использовать этот код в качестве шаблона в будущих проектах.

 

 

 

DLL

Файлы DLL (Dynamic Link Library, библиотека динамической компоновки) являются основой  программной архитектуры Windows и отличаются от исполняемых файлов фактически только заголовком

Для загрузки операционной системы необходимо запустить файл win com, имеющий размер всего 25 Кбайт. Как легко догадаться, в файл такого размера невозможно поместить код, реализующий всю ту гигантскую работу, которая производится по ходу выполнения любого приложения. Этот файл является загрузчиком ядра операционной системы, физически размещенным в нескольких DLL-файлах. Помимо кода, DLL-файлы могут хранить данные и ресурсы. Например, при изменении значка (ярлыка) пользователю предлагается на выбор набор значков из файла SHELL32. DLL. Библиотека OpenGL физически также размещена в виде двух DLL-файлов: opengl23. dll и glu32. dll. Первый из этих файлов и есть собственно библиотека OpenGL. Назначение его - осуществление взаимодействия с акселератором или программная эмуляция ускорителя за счет центрального процессора. Поддержка ЗD-акселерации осуществляется с помощью полного (устанавливаемого) клиентского драйвера (Installable Client Driver, ICD) и мини-драйвера (Mini-Client Driver, MCD). Библиотека OpenGL реализована по клиент-серверной схеме, т.e. ее одновременно может использовать несколько приложений при единственной копии сервера в памяти или вообще при удаленном расположении сервера (сервер в принципе может располагаться и не на компьютере клиента). Чаще всего DLL представляет собой набор функций и процедур. Как говорится в справке Delphi по DLL, "динамические библиотеки являются идеалом для многоязыковых проектов". Это действительно так: при использовании OpenGL совершенно безразлично, в какой среде созданы сама библиотека и вызывающие ее модули.

 

Раздел 2 “Подключение OpenGL”

2.1. Минимальная программа OpenGL

Рассмотрев основные вопросы функционирования приложения и его взаимодействия с операционной системой, мы можем перейти к изучению собственно OpenGL. Например, в программе с помощью команд OpenGL окно формы окрашивается в голубоватый цвет. Во-первых, обратите внимание на то, что список uses дополнен модулем OpenGL - это программист должен сделать сам Раздел private описания класса формы содержит строку

hrc: HGLRC; // ссылка на  контекст воспроизведения

Смысл этой величины мы рассмотрели  в предыдущем разделе. Обработчик события OnCreate формы содержит следующие строки:

SetDCPixelFormat(Canvas. Handle); //задаем формат пиксела

hrc: = wglCreateContext(Canvas. Handle); // создаем контекст воспроизведения

Первая строка - обращение  к описанной в этом же модуле пользовательской процедуре, задающей формат пиксела

procedure SetDCPixelFormat (hdc: HDC);

var

pfd: TPixelFormatDescriptor;

nPixelFormat: Integer;

begin 
FillChar (pfd, SizeOf (pfd), 0);

nPixelFormat: = ChoosePixelFormat (hdc, @pfd);

SetPixelFormat (hdc, nPixelFormat, @pfd);

end;

По поводу формата пиксела мы подробнее поговорим в следующем  разделе. Во второй строке обработчика OnCreate задается величина типа HGLRC, т.e. создается контекст воспроизведения. Аргументом функции wglCreateContext является ссылка на контекст устройства, на который будет осуществляться вывод. Сейчас устройством вывода служит окно формы. Для получения этого контекста OpenGL необходима величина типа HDC. Здесь, как и во многих других примерах, мы используем факт, что canvas. Handle и есть ссылка на контекст устройства, связанная с окном формы. Поскольку это первая функция, имеющая непосредственно отношение к OpenGL, то я немного отвлекусь на некоторые общие пояснения. Только начиная с пятой версии Delphi поставляется с системой помощи, удовлетворительно настроенной с точки зрения получения справок по командам OpenGL и функциям API, в предыдущих версиях ее вроде, как и нет. Однако на самом деле такая помощь доступна и в ранних версиях, и самый простой способ ее получения - контекстная подсказка. По командам OpenGL справки мы будем получать точно так же, как и по функциям API, т. e если вам необходима более подробная информация, например, о функции wglcreateContext, то установите курсор на строку с этой функцией и нажмите клавишу <F1>. Функция wgicreateContext физически размещается в файле opengl32 dll, а прототип ее находится в файле windows. pas. В этот файл также помещены прототипы всех функций и процедур, имеющих отношение к реализации OpenGL под Windows, a прототипы собственно команд OpenGL расположены в файле opengl pas функции и процедуры, имеющие отношение только к Windows-версии OpenGL, обычно имеют приставку wgl, как, например, wglcreateContext, но могут и не иметь такой приставки, как, например, SwapBuffers. Собственно команды OpenGL имеют приставки gl или glu в зависимости от размещения в библиотеках opengl32. dll и glu32. dll, соответственно. Итак, контекст воспроизведения создан, и теперь можно осуществлять вывод командами OpenGL. Обработка события onpaint выглядит следующим образом:

wglMakeCurrent (Canvas. Handle, hrc); // установить  контекст

glClearColor (0. 5, 0. 5, 0. 75, 1. 0); // цвет фона

glClear (GL_COLOR_BUFFER_BIT); // очистка буфера цвета

wglMakeCurrent (0, 0); // освободить контекст

Первая строка делает контекст воспроизведения  текущим, т.e. занимает его для последующего вывода. Далее задаем цвет фона. Следующую строку будем понимать как очистку экрана и окрашивание его заданным цветом. После работы освобождаем контекст.

Замечание 
          Согласно справке, для освобождения контекста воспроизведения оба параметра должны быть установлены в NULL, но хотя компилятор и пропустит такие значения, во время выполнения получим ошибку "Invalid variant type conversion", так что будем всегда для освобождения контекста задавать эти значения нулевыми. Обработка события onDestroy формы состоит из одной строки:

wglDeleteContext (hrc);

Тем самым мы по завершении работы приложения удаляем контекст воспроизведения, освобождая память.

Замечание 
          Очень важно запомнить, что процедуры и функции, имена которых начинаются на gl или glu, т.e. команды OpenGL, имеют какой-либо результат только при установленном контексте воспроизведения

Вернемся к команде glclearcolor, определяющей цвет фона. У нее четыре аргумента, вещественные числа, первые три из которых  задают долю красного, зеленого и синего в результирующем цвете. Четвертый аргумент я задал его значение равным единице. Можете варьировать это значение произвольно, в данном примере это никак не скажется, так что пока можете просто не обращать внимания на этот аргумент. Согласно справке, все четыре аргумента функции glclearColor имеют тип GLclampf, соответствующий вещественным числам в пределах от нуля до единицы. О типах OpenGL подробнее если вы используете Delphi версии три или четыре, вы, возможно, столкнетесь с одной небольшой проблемой. Если запускать проекты, использующие OpenGL, под управлением среды Delphi, программа может случайным образом аварийно завершаться. Оборот "случайным образом" здесь я употребил постольку, поскольку один и тот же проект может привести к аварийному завершению, а может и работать вполне успешно. Я сталкивался с этой проблемой на компьютерах с различной конфигурацией и с различными версиями операционной системы, и, по-видимому, она связана с некорректным взаимодействием среды Delphi c драйверами. Если подобная проблема возникла и у вас, я рекомендую просто не запускать под управлением среды проекты, использующие OpenGL, a запускать собственно откомпилированные модули. В пятой версии Delphi такая ситуация не возникала, так что, по-видимому, этот недостаток разработчиками выявлен и устранен.

Формат пикселя

Напомню, ссылка на контекст устройства содержит характеристики устройства и  средства отображения. Упрощенно говоря, получив ссылку на контекст устройства, мы берем в руки простой либо цветной  карандаш или кисть с палитрой в миллионы оттенков. Сервер OpenGL, прежде чем приступать к работе, также должен определиться, на каком оборудовании ему придется работать. Это может быть скромная персоналка, а может быть и мощная графическая станция.

Подключение библиотеки OpenGL в Delphi