Подскажите, пожалуйста, планируете ли вы возобновление программ высшего образования? Если да, есть ли какие-то примерные сроки? Спасибо! |
Структура приложений, использующих OpenGL
Цель лекции: Создать базовые приложения с использованием OpenGL на C# и на Object Pascal (Delphi).
Примеры
Пример № 3.1 Базовые приложения на C# (WinForms) и Object Pascal (Delphi), использующие библиотеку OpenGL.
В состав приложения, формирующего изображениe с помощью OpenGL, должно входить несколько программных блоков:
- Инициализация библиотеки OpenGL.
- Подготовительные операции для формирования изображения библиотекой OpenGL (при необходимости).
- Определение области вывода изображения.
- Основная функция формирования изображения.
- Обработка событий мыши и клавиатуры для реализации интерактивности в программе (при необходимости).
- Завершение работы c библиотекой OpenGL.
Инициализация OpenGL в библиотеке OpenTK
Инициализацию OpenGL в библиотеке OpenTK выполняет графический компонент GLControl, который размещается на одной из форм приложения. Вывод изображения, формируемого библиотекой OpenGL, выпоняется в области компонента GLControl. По умолчанию библиотека OpenTK инициализирует использование палитры RGBA, двойной буфер, устанавливает размер буфера глубины равным 16 бит.
Дополнительные настройки библиотеки OpenGL необходимо выполнять в обработчике события Load формы. В конструкторе формы этого делать не следует, так как еще не создан контекст изображения для компонента GLControl.
В следующем разделе рассмотрена инициализация библиотеки OpenGL в приложении на Object Pascal (Delphi). Аналогичную процедуру инициализации выполняет и библиотека OpenTK, чтобы в этом убедиться, достаточно заглянуть в исходный код этой библиотеки.
Инициализация библиотеки OpenGL в приложениях на Object Pascal (Delphi)
Перед началом использования команд OpenGL необходимо выполнить инициализацию библиотеки OpenGL. Основной задачей данного этапа является определение основных параметров работы библиотеки OpenGL, которые в дальнейшем не могут быть изменены без завершения работы с библиотекой OpenGL и её повторной инициализации. На этом этапе выполняется определение доступных возможностей аппаратуры для вывода изображения. Хотя библиотека OpenGL является кросплатформенной, но инициализация является специфичной для каждой платформы, поэтому на этом этапе используются функции операционной системы Windows. Инициализация библиотеки может выполняться в обработчике события OnCreate формы, на которой будет выводиться изображение. Для возможности использования функций и процедур библиотеки OpenGL необходимо указать модуль opengl.pas в разделе uses каждого модуля, в котором они будут использоваться. Ниже приведен пример инициализации библиотеки OpenGL.
implementation {$R *.dfm} Uses OpenGL; Const //угол поворота изображения при нажатии на клавишу AngleDl=5; // глобальные переменные var hrc: HGLRC; dc: HDC; // переменные для хранения текущих углов поворота изображения AngleX, AngleY, AngleZ: integer; procedure TForm1.FormCreate(Sender: TObject); var PFD: TPixelFormatDescriptor; i: integer; begin // получение контекста устройства с помощью системной функции GetDC dc:=GetDC(handle); // обнуление структуры pfd FillChar(PFD, SizeOf(PFD),0); pfd.dwFlags := PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER; // запрос у операционной системы наиболее подходящего формата пиксела i:=ChoosePixelFormat(dc, @PFD); if i=0 then raise Exception.Create('Не определен формат пиксела !'); // установка в качестве текущего формата пиксела, полученного с помощью // ф-ии ChoosePixelFormat if not SetPixelFormat(dc, i, @PFD) then raise Exception.Create('Ошибка при установке формата пиксела !'); // создание контекста воспроизведения для библиотеки OpenGL // и сохранение его дескриптора в глобальной переменной hrc:=wglCreateContext(dc); if hrc=0 then raise Exception.Create('Ошибка создания контекста воспроизведения !'); // установка текущего контекста воспроизведения if not wglMakeCurrent(dc, hrc) then raise Exception.Create('Невозможно установить текущий контекст воспроизведения !'); glEnable(GL_DEPTH_TEST); end;Листинг 3.1. Пример инициализации библиотеки OpenGL на Object Pascal
В листинге 3.1 объявляются глобальные переменные hrc и dc. В дальнейшем они будут использоваться для освобождения ресурсов операционной системы при завершении работы с библиотекой OpenGL ( пример 3.5). Большинство процедур и функций в листинге 3.1 не входят в состав OpenGL и являются функциями операционной системы. В частности функции, названия которых начинаются с последовательности символов "wgl", также являются системными и предназначены для поддержки возможностей OpenGL в операционной системе Windows.
При разработке программ на языке программирования Object Pascal c использованием библиотеки визуальных компонентов (VCL) системные функции использовать приходится довольно редко, так как набор классов библиотеки VCL позволяет этого избежать. При работе с библиотекой OpenGL потребуется несколько системных функций. В процедуре FormCreate с помощью системной функции GetDC выполняется получение дескриптора контекста устройства. Функция GetDC позволяет получить параметры вывода изображения, которые используются для формы. Информация о форме передается в функцию с помощью дескриптора формы, который возвращается свойством формы Handle.
Процедура FillChar также является системной и используется для побайтного заполнения области памяти указанного размера необходимым значением.
procedure FillChar(var Dest; count: Integer; Value: Char);
Процедура имеет следующие параметры:
- Dest - переменная, область памяти которой требуется заполнить значением Value;
- Count – размер заполняемой области памяти в байтах;
- Value – значение байта, которое должно быть скопировано в каждый байт памяти, определяемой параметром Dest.
В листинге 3.1 для определения размера структуры PFD используется функция
function SizeOf(X): Integer;
Функция возвращает размер в байтах переменной или типа данных, переданных ей в качестве параметра X.
Для работы с библиотекой OpenGL операционная система определяет наиболее подходящие параметры вывода изображения, основные из которых перечислены ниже:
- Тип используемой цветовой палитры: индексная или RGBA. В примерах будет использована только RGBA палитра, которая используется по умолчанию.
- Глубина цвета или количество бит, которое будет использоваться для хранения цвета каждого пиксела.
- Использование вторичного буфера.
- Число бит в буфере глубины.
- Размер буфера трафарета.
Эти параметры задаются с помощью значений полей структуры TPixelFormatDescriptor. Для разных приложений могут потребоваться различные варианты сочетаний этих параметров. Некоторые сочетания могут быть невозможны или не поддерживаться аппаратной платформой или операционной системой. Для того чтобы определить доступный вариант сочетания этих параметров реализуется диалог между программой и операционной системой: программа указывает, какие параметры ей необходимы и передает запрос операционной системе на возможность их использования. Операционная система анализирует возможности оборудования и возвращает приложению наиболее подходящую конфигурацию из возможных вариантов. Программа может проанализировать эту конфигурацию и определить возможность её использования. После выбора приложением подходящей конфигурации для работы библиотеки OpenGL эти параметры устанавливаются текущими.
Для запроса у операционной системы наиболее подходящей конфигурации библиотеки OpenGL для работы приложения используется функция
function ChoosePixelFormat(DC: HDC; p2: PPixelFormatDescriptor): Integer;
Назначение параметров функции:
- DC – контекст устройства, полученный с помощью системной функции GetDC.
- p2 – указатель на переменную типа TPixelFormatDescriptor. В переменной предварительно должны быть указаны параметры библиотеки OpenGL, которые требуются для работы приложения.
Функция возвращает номер наиболее подходящей конфигурации библиотеки OpenGL. Операционная система Windows предоставляет ограниченное количество возможных вариантов параметров работы библиотеки OpenGL. Каждое из таких сочетаний имеет свой уникальный целочисленный номер. Один из таких номеров и возвращает функция ChoosePixelFormat.
В выше приведенном примере ( пример 3.1) поля структуры TPixelFormatDescriptor в переменной PFD заполняются нулевыми значениями с помощью процедуры FillChar, и затем поле dwFlags инициализируется для использования библиотекой OpenGL вторичного буфера.
Для заданных значений структуры TPixelFormatDescriptor операционная система возвращает номер конфигурации для библиотеки OpenGL, в которой:
- используется палитра RGBA;
- глубина цвета соответствует текущим параметрам дисплея, на котором выводится форма;
- используется вторичный буфер;
- для буферов трафарета и глубины установлены максимальные значения.
Параметры выбранной конфигурации функция сохраняет во втором параметре и программа в дальнейшем может их проанализировать.
При использовании вторичного буфера библиотека OpenGL формирует изображение сначала во вторичном буфере. Вторичный буфер представляет собой блок памяти и непосредственно не отображается. После завершения формирования изображения во вторичном буфере он должен быть скопирован в область вывода изображения. Основным назначением вторичного буфера является увеличение скорости формирования изображения.
Константы, используемые для задания значения поля dwFlags структуры TPixelFormatDescriptor, имеют следующие значения:
- PFD_DRAW_TO_WINDOW – изображение формируется в окне (на форме). Значение должно быть указано обязательно.
- PFD_SUPPORT_OPENGL – изображение формируется с библиотекой OpenGL. Значение должно быть указано обязательно.
- PFD_DOUBLEBUFFER – для формирования изображения будет использоваться вторичный буфер.
Для отображения изображения, сформированного во вторичном буфере, используется системная функция:
function SwapBuffers(DC: HDC): BOOL;
Пример её использования приведен в листинге 3.3 .
Для установки выбранного значения формата пиксела используется функция:
function SetPixelFormat(DC:HDC;PixelFormat:Integer; FormatDef: PPixelFormatDescriptor): BOOL;
Назначение параметров функции:
DC – контекст устройства, полученный с помощью системной функции GetDC.
PixelFormat – номер формата пиксела, полученный с помощью функции ChoosePixelFormat.
FormatDef – указатель на переменную типа TPixelFormatDescriptor, в которой должны быть значения, соответствующие выбранному номеру формата пиксела, который указан в качестве значения параметра PixelFormat.
После задания формата пиксела должен быть создан контекст воспроизведения библиотеки OpenGL для выбранной формы с помощью функции
function wglCreateContext(DC: HDC): HGLRC;
Функции передается единственный параметр DC – контекст устройства, полученный с помощью системной функции GetDC. Функция возвращает дескриптор контекста воспроизведения.
Приложение может иметь несколько контекстов воспроизведения, например, для отображения нескольких проекций одной и той же сцены. Для того чтобы вывести изображение в одной из областей воспроизведения необходимо сделать текущим ассоциированный с ней контекст воспроизведения. Для этого используется функция wglMakeCurrent. Если в приложении всего один контекст воспроизведения, то достаточно сделать его текущим при инициализации библиотеки OpenGL.
function wglMakeCurrent(DC: HDC; p2: HGLRC): BOOL;
Назначение параметров функции:
- DC – контекст устройства, соответствующий форме, на которой располагается область вывода.
- p2 – дескриптор контекста воспроизведения, который необходимо сделать текущим.
Функция возвращает логическое значение, информирующее об успешности выполнения операции.
В листинге 3.1 после инициализации библиотеки вызывается процедура glEnable со значением параметра GL_DEPTH_TEST, который включает тест глубины.
Тест глубины реализует отбор примитивов и их фрагментов при формировании изображения в зависимости от удаленности от наблюдателя и выполняет удаление фрагментов, которые заслоняют примитивы, находящиеся ближе к точке наблюдения. При отключенном тесте глубины (по умолчанию после инициализации библиотеки) библиотека не выполняет анализ того, какой из примитивов не виден наблюдателю. Примитивы отображаются в порядке их формирования и поэтому примитивы, которые были сформированы последними, будут "заслонять" другие примитивы в не зависимости от их реальной удалённости от наблюдателя.