OpenGL и Delphi. Введение

Здравствуйте, это первая статья посвященная OpenGL в Delphi. Она должна подготовить Вас к обучению графическому программированию с OpenGL и Delphi. В этой статье дается основной смысл, как OpenGL и Delphi работает вместе.

Чтобы начать программировать с OpenGL  в Delphi, необходимо иметь заголовочный файл OpenGL и собственно Delphi.

В стандартной поставке Delphi уже есть заголовочные файлы OpenGL, но мы сейчас поговорим о хорошем заголовочном файле, чем все остальные. Так как, стандартные постанавливаемые с Delphi заголовки, являются ущербными, не придерживается стандарта OpenGL, а так же полностью устаревшими. Для эффективного использования OpenGL в Delphi необходимо загрузить заголовочный файл DGLOpenGL.pas с этого сайта или сайта разработчиков (команды DGL) www.delphigl.com.

Прежде чем приступить к работе необходимо загруженный файл dglOpenGL.pas разместить в нужном месте, лучше всего его разместить в папке “\lib” в каталоге Delphi.
Теперь запустите Delphi, перед вами должен открыться пустой проект.
Примечание: если у вас установлена операционная система Windows 7. Вам так же необходимо произвести  некоторые действия, чтобы успешно все компилировалось. Для начала вам необходимо выделить папку “\lib” кликнуть на ней правой кнопкой мыши. В контекстном меню выбрать «свойства» снять галочку «только для чтения». Потом выбрать закладку «безопасность» нажать кнопку «изменить». Появится окно «разрешения для группы «lib»». В этом окне выбрать пользователи и разрешить полный доступ и нажать кнопку применить (смотрите рисунок ниже).

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

Теперь объявить два свойства формы в разделе public (которые будут общедоступны):

dc  : HDC – контекст устройств
hrc : HGLRC – контекст рендеринга, он необходим для OpenGL, чтобы рисовать на форме Инициализацию необходимо производить непосредственно при создании формы. Таким образом, следующий код должен быть в событии OnCreate формы:

            Строчка Application.OnIdle := IdleHandler; объясняется ниже.
После этой совершенно простой инициализации (можно, конечно, делать все вручную, с помощью стандартных функций Delphi,и определять формат пикселя, но это делается дольше, а с InitOpenGL все это делается проще и быстрей), вы имеете сразу в распоряжении все особенности OpenGL, которые определенны в начальных значениях. Но часто, определенные параметры по умолчанию в OpenGL не будут использоваться или их
нужно изменить. Поэтому напишем еще маленькую дополнительную процедуру: SetupGL.

То, что здесь происходит, объясняется в комментариях.

Вы можете устанавливать цвет фона по своему усмотрению с glClearColor. В OpenGL цвета всегда определены как смесь красного, зеленого и синего.

Процедура SetupGL должна вызывать в конце FormCreate:

[…]
ActivateRenderingContext(dc,hrc);  //активируем контекст рендеринга
SetupGL;                          //установка режимов OpenGL
end; Так как OpenGL выводится на форму, то при изменении её размеров,  изменяется и выход изображения OpenGL, и не которые части могут скрыться, чтобы этого не происходило, необходимо среагировать на событие OnResize и она будет следующей.

Строка 2: Это булева переменная используется как манекен.
Строка 4: Задает область вывода указанием координат левого нижнего и правого верхнего углов (в пикселях, в оконных координатах).
Строка 5: Задаем, что используется проекционная матрица
Строка 6 и 9: Устанавливаем текущую матрицу равной единичной.
Строка 7: Здесь устанавливается, как зритель должен видеть сцену.
Строка 8: Задаем, что используется модельная матрица
Строка 11: То, что делает IdleHandler, описывается позже.
Кроме того необходимо определить две константы NearClipping и FarClipping в части Const. Они указывают расстояние до уровней отсечения (ограничения сцен) и играют определенную роль в тесте глубины.

Так как мы создавали контексты программно, то что бы после закрытия программы они в памяти не оставляли мусор необходимо освободить память. Лучше всего это сделать в событии OnDestroy.

  До сих пор ядро нашей программы отсутствовало. В конце концов, графическая карта, должна что-нибудь выводить. Это происходит в процедуре Render:



Строка 3: Этот вызов заботиться  о том, чтобы буфер цвета и буфер глубины удалялись. Если это не сделать, вы уведите все что угодно, но только не, то, что вы хотели передать. Цвет буфера не удаляется, а просто перезаписывается glClearColor, который вы определили в создании формы
Строка 7: здесь снова ставиться перспектива. Этот же вызов и при FormResize, они должны быть идентичны по параметрам. Иначе после Resize вывод будет другим. Если перспектива не изменяется между рендерингом, то эта команда также может пропускаться.
Строка 12: Этот вызов перемещает «камеру» (собственно в данном случае это ничего не дает), потому что мы хотим видеть, что мы изображаем. Все что находится слишком близко, отрезается плоскостью отсечения.
Строка 14: glBegin/glEnd инкапсулирует команды. Ими строятся красочный четырехугольник. Думаю для первого раза должно хватить. Очень важно в этом контексте следующее: OpenGl не важно, где команда вызывается. Все будет оцениваться и может оказаться в буфере кадра. Таким образом, вы можете написать подпрограмму, в  которой содержатся команды OpenGL.
Строка 21: SwapBuffers гарантирует, что содержимое буфера кадра будет появляться на экране. Без этой команды, вы ничего не увидите OpenGL.

Так…Отлично. Теперь у вас есть функция рисования, но так или иначе, вы должны вызвать её. Но вызвать просто при активации или при нажатии какой-нибудь кнопки это очень просто. Результат нужно изменять так, например, как в играх, чтоб  функция вызывалась снова и снова. Есть два варианта, оба имеют свои преимущества и недостатки. Смотрите таблицу

Аргумент

Таймер

OnIdle

Максимальная частота кадров достижима

нет

да

Число кадров регулируемо

да

Условно (затруднительно)

Доступна плавная анимация (для шутеров)

Условно (плохо)

Да

Доступно для меню

да

Да

Доступно для простой анимации (стратегий)

да

Да

Не разрежает аккумулятор ротативных компьютеров

да

нет

Кто хочет писать простые приложения, которые хорошо справляются с 25 кадров в секунду и сохранить батарею ноутбуков программисты должны использовать вариант с таймером. Кто хочет в полной мере использовать потенциал видеокарты должны использовать OnIdle.
При методе с таймером, таймер должен быть помещен на форму. Таймер имеет свойств «Интервал». С этим свойством можно устанавливать через, сколько миллисекунд событие OnTimer будет вызываться функция Render. Нельзя  уменьшать таймер сколько угодно. Значение ниже 25 не может производиться правильно стандартным таймером, который использует Windows.

Второй вариант с событием OnIdle, это событие типа TIdleEvent возникает при простое приложения. Чтобы смочь реагировать на «событие Idle», вы должны соединить теперь лишь эту функцию с  событием. Это необходимо сделать, в то время когда пишете событие формы OnCreate в последней строчке:

[…]
SetupGL;                          //установка режимов OpenGL
Application.OnIdle := IdleHandler;
end; Как вы поймете сами, этот метод загружает процессор на 100% (это плохо для батареи ноутбука), вы можете обходить это, маленьким трюком:
вставлять перед “Done := false”  строку Sleep(1) или Sleep(5). Вследствие этого опускается нагрузка процессора до 80%. Таким образом, код процедуры IdleHandler  будет выглядить так:

Вот и все собственно, вы теперь можете откомпилировать и увидеть то, что у вас получилось.

Если у вас что-то не получилось, прочтите внимательнее, или скачайте готовый пример с этого сайта.

Скачать готовые примеры.
Дополнения скачать Если у вас возникнуть вопросы вы можете написать мне письмо oryth84@gmail.com

© Олин Р.И. aсьka Oryth



Оглавление || OpenGL и Delphi. Урок 1.