Воскресенье, 06.07.2025, 14:24
Приветствую Вас Гость | RSS
Главная | Регистрация | Вход
Библиотека программиста
Форма входа
[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Обучение Delphi
proglibДата: Четверг, 12.03.2009, 16:08 | Сообщение # 1
Admin
Группа: Администраторы
Сообщений: 149
Репутация: 0
Статус: Offline
Урок 1. Введение

OpenGL является на данный момент одним из самых популярных программных интерфейсов (API) для разработки приложений в области двумерной и трехмерной графики. Стандарт OpenGL был разработан и утвержден в 1992 году ведущими фирмами в области разработки программного обеспечения, а его основой стала библиотека IRIS GL, разработанная Silicon Graphics.
На данный момент реализация OpenGL включает в себя несколько библиотек (описание базовых функций OpenGL, GLU,GLUT,GLAUX и другие), назначение которых будет описано ниже.
Характерными особенностями OpenGL, которые обеспечили распространение и развитие этого графического стандарта, являются:

Стабильность
Дополнения и изменения в стандарте реализуются таким образом, чтобы сохранить совместимость с разработанным ранее программным обеспечением.

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

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

Основные возможности OpenGL
• Набор базовых примитивов: точки, линии, многоугольники и т.п.
• Видовые и координатные преобразования
• Удаление невидимых линий и поверхностей (z-буфер)
• Использование сплайнов для построения линий и поверхностей
• Наложение текстуры и применение освещения
• Добавление специальных эффектов: тумана, изменение прозрачности,сопряжение цветов (blending), устранение ступенчатости (anti-aliasing).

Как уже было сказано, существует реализация OpenGL для разных платформ, для чего было удобно разделить базовые функции графической системы и функции для отображения графической информации и взаимодействия с пользователем. Были созданы библиотеки для отображения информации с помощью оконной подсистемы для операционных систем Windows и Unix (WGL и GLX соответственно), а также библиотеки GLAUX и GLUT, которые используются для создания так называемых консольных приложений.
Библиотека GLAUX уступает по популярности написанной несколько позже библиотеке GLUT, хотя они предоставляют примерно одинаковые возможности.

В состав библиотеки GLU вошла реализация более сложных функций, таких как набор популярных геометрических примитивов (куб, шар, цилиндр, диск), функции построения сплайнов, реализация дополнительных операций над матрицами и т.п. Все они реализованы через базовые функции OpenGL.

 
proglibДата: Четверг, 19.03.2009, 05:13 | Сообщение # 2
Admin
Группа: Администраторы
Сообщений: 149
Репутация: 0
Статус: Offline
Урок 2. Введение в низкоуровневое программирование в Delphi

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

С понятием "событие" знаком каждый программист, использующий Delphi. Термин "сообщение" напрямую в концепции Delphi не используется.
Очень часто это синонимы одного и того же термина операционной системы, общающейся с приложениями (окнами) посредством посылки сигналов, называемых сообщениями.

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

Ссылка на окно может использоваться не только операционной системой, но и приложениями для идентификации окна, с которым необходимо производить манипуляции.

Можно проиллюстрировать смысл ссылки на окно на несложном примере.
Откомпилируйте минимальное приложение Delphi и начните новый проект. Форму назовите Form2, разместите на ней кнопку. Обработчик события нажатия кнопки OnClick приведите к следующему виду:

Quote
procedure. TForm2.ButtonlClick(Sender: TObject);
var
H : HWND; // ссылка на окно
begin
H := FindWindow ('TForml', 'Form1’); // ищем окно
If H <> 0 then ShowMessage ('Есть Forml!') // окно найдено
else ShowMessage ('Нет Forml!') // окно не найдено
end;

Теперь при нажатии кнопки выдается сообщение, открыто ли окно класса, зарегистрированного в операционной системе как 'Tform1, имеющее заголовок 'Forml' Если одновременно запустить обе наши программы, то при нажатии кнопки будет выдано одно сообщение, а если окно с заголовком ‘Forml’ закрыть, то другое.
Здесь мы используем функцию Fmdwmdow, возвращающую величину типа HWND - ссылку на найденное окно либо ноль, если такое окно не найдено Аргументы функции -класс окна и его заголовок. Если заголовок искомого окна безразличен, вторым аргументом нужно задать mi
Итак, ссылка на окно однозначно определяет окно. Свойство Handle формы и есть эта ссылка, а тип THandie в точности соответствует типу HWND, так что в предыдущем примере переменную Н можно описать как переменную типа
THandle.

Рассмотрим подробнее некоторые выводы. Класс окна минимального приложения, созданного в Delphi, имеет значение 'Tform1', что полностью соответствует названию класса формы в проекте. Следовательно, то, как мы называем формы в проектах Delphi, имеет значение не только в период проектирования приложения, но и во время его работы. Начните новый проект, назовите форму каким-нибудь очень длинным именем и откомпилируйте проект. Сравните размер откомпилированного модуля с размером самого первого проекта, и убедитесь, что он увеличился — вырос только за счет длинного имени класса.
Также очень важно уяснить, что, если вы собираетесь распространять какие-либо приложения, необходимо взять за правило называть формы отлично от значения, задаваемого Delphi по умолчанию. Лучше, если эти названия будут связаны по смыслу с работой вашего приложения.

Имея ссылку на окно, операционная система общается с ним путем посылки сообщений — сигналов о том, что произошло какое-либо событие, имеющее отношение именно к данному окну. Если окно имеет намерение отреагировать на событие, операционная система совместно с окном осуществляет эту реакцию.
Окно может и, не имея фокус, получать сообщения и реагировать на них. Проиллюстрируем это на примере.
Обработчик события OnMouseMove формы приведите к следующему виду:

Quote
procedure TForm2.FormMouseMove(Sender: T0b3ect; Shift: TShiftState; X,
Y: Integer);
begin Caption : = 'x=' + IntToStr (X) + ', y=' + IntToStr (Y) // X, Y -
// координаты курсора
end;

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

Quote
procedure TForm2.ButtonlClick(Sender: TObject);
var
H: HWND;
begin
H := FindWindow ('TForml', 'Forml');
If H <> 0 then SendMessage (H, WM_CLOSE, 0, 0)//закрыть найденное окно
end;

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

Одновременно могут быть зарегистрированы несколько окон класса 'TForm1', и необходимо закрыть их все. Пока наше приложение закрывает окна поодиночке при каждом нажатии на кнопку. Автоматизировать процесс можно разными способами, простейший из них заключается в том, что вызов FindWindow заключен в цикл, работающий до тех пор, пока значение переменной Н не станет равным нулю:

Quote
procedure TForm2.ButtonlClick(Sender: TObject);
var
H : HWND;
begin
Repeat
H := FindWindow ('TFormi', 'Forml');
If H <> 0 then SendMessage (H, WM_CLOSE, 0, 0)
Until H = 0;
end;

Для работы с приложениями, класс окна которых не известен, служит утилита Ws32, поставляемая с Delphi.

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

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

Quote
procedure TForm2.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 с аргументом-ссылкой на устройство вывода. В нашем примере в качестве аргумента указана ссылка на окно.
После получения ссылки на контекст устройства обращаемся собственно к функции, строящей прямоугольник. Первым аргументом этой функции является ссылка на контекст устройства.
После использования ссылки ее необходимо освободить, а в конце работы приложения — удалить для освобождения памяти.
Поставленная "клякса" будет оставаться на окне формы при изменении размеров окна и исчезнет только при его перерисовке, для чего можно, например, минимизировать окно формы, а затем вновь его развернуть. Исчезновение квадрата после такой операции объясняется тем, что за перерисовку окна отвечает его собственный обработчик. Теперь можно порисовать на поверхности чужого окна, для чего изменим только что написанный код:

Quote
procedure TForm2.Button2Click(Sender: TObject);
var
dc: HOC;
Window: HWND;
begin
Window := FindWindow ('TForml', 'Forml');
If Window <> 0 then begin // окно найдено
dc := GetDC (Window); // ссылка на найденное окно
Rectangle (dc, 10, 10, 110, 110); // квадрат на чужом окне
ReleaseDC (Window, dc); // освобождение ссылки
DeleteDC (dc); // удаление ссылки
end;
end;

Теперь при щелчке на кнопке, если в системе зарегистрировано хотя бы одно окно класса ‘TForm1’ с заголовком ‘Form1’, вывод (рисование квадрата) будет осуществляться на него.
При щелчке на кнопке квадрат рисуется на поверхности чужого окна.
Заметим, что если закрыть Project1.exe и загрузить в Delphi соответствующий ему проект, то при щелчке на кнопке прямоугольник будет рисоваться на поверхности окна формы, что будет выглядеть необычно
Этот эксперимент показывает, что окна, создаваемые Delphi во время проектирования, такие же равноправные окна, как и любые другие, т.е. они регистрируются в операционной системе, идентифицируются, и любое приложение может иметь к ним доступ. Если попытаться минимизировать окно класса 'TForm1', окно формы будет отрабатывать эту команду точно так же, как полученную от пользователя.
Окно со значением ссылки, равным нулю, соответствует окну рабочего стола.
Во всех примерах этого раздела для вывода мы использовали функции GDI потому, что если для вывода на родном окне Delphi и предоставляет удобное средство — методы свойства формы canvas, то для вывода на чужом окне мы этими методами воспользоваться не сможем в принципе.
Разберем основные детали вывода с помощью функций GDI. В проекте из подкаталога Ех12 оконная функция минимальной программы дополнилась обработкой сообщения WM_PAINT. Вывод заключен между строками с вызовом функций BegmPamt и EndPamt, первая из которых возвращает ссылку на контекст устройства, т. е. величину типа нос, требуемую для функций вывода GDI. Еще раз повторю, что после использования ссылки ее необходимо освободить и удалить по окончании работы — это необходимо для корректной работы приложения.

DLL

Файлы DLL (Dynamic Link Library, библиотека динамической компоновки) являются основой программной архитектуры Windows и отличаются от исполняемых файлов фактически только заголовком.
Но это не означает, что если переименовать DLL-файл, то он станет исполняемым: имеется в виду заголовочная информация файла.
Для загрузки операционной системы необходимо запустить файл win.com, имеющий размер всего 25 Кбайт. Как легко догадаться, в файл такого размера невозможно поместить код, реализующий всю ту гигантскую работу, которая производится по ходу выполнения любого приложения. Этот файл является загрузчиком ядра операционной системы, физически размещенным в нескольких DLL-файлах.

Помимо кода, DLL-файлы могут хранить данные и ресурсы. Например, при изменении значка (ярлыка) пользователю предлагается на выбор набор значков из файла SHELL32.DLL.
Для создания любой программы Windows, имеющей собственное окно, в проекте необходимо подключать как минимум два модуля: windows и Messages. Первый из этих файлов содержит прототипы функций API и GDI. Посмотрим на прототип одной из них:
function CreateDC; external gdi32 name 'CreateDCA';
Здесь величина gdi32 — константа, описанная в этом же модуле:
const
gdi32 = 'gdi32.dll';

Таким образом, функция CreateDC физически размещена в файле gdi32.dll и каждое приложение, использующее функции GDI, обращается к этой библиотеке.

Приблизительно так же выглядят прототипы остальных функций и процедур, но указываемые в прототипе имена библиотек индивидуальны для каждой из них.
Использование DLL, в частности, позволяет операционной системе экономить память.
Приложение не умеет ни создавать окно, ни выводить в него информацию и не содержит кода для этих действий. Все запущенные приложения (клиенты) передают соответствующие команды файлу gdi32.dll (серверу), который отрабатывает их, осуществляя вывод на устройство, ссылку на контекст которого передается в качестве первого аргумента функции. При этом клиентов обслуживает единственная копия сервера в памяти.
Помимо важности DLL как основы программной архитектуры операционной системы, представление о динамических библиотеках необходимо иметь каждому разработчику программных систем. Многие программные системы строятся по следующему принципу: основной код и данные размещаются в динамических библиотеках, а исполняемому файлу отводится роль загрузчика.
Библиотека OpenGL физически также размещена в виде двух DLL-файлов: opengl23.dll и glu32.dll. Первый из этих файлов и есть собственно библиотека OpenGL. Назначение его — осуществление взаимодействия с акселератором или программная эмуляция ускорителя за счет центрального процессора Поддержка 3D-акселерации осуществляется с помощью полного (устанавливаемого) клиентского драйвера (Installable Client Driver, ICD) и мини-драйвера (Mini-Client Driver, MCD).
Библиотека OpenGL реализована по клиент-серверной схеме, т. е. ее одновременно может использовать несколько приложений при единственной копии сервера в памяти или вообще при удаленном расположении сервера (сервер в принципе может располагаться и не на компьютере клиента).
Для просмотра списка функций и процедур, размещенных в конкретном файле DLL можно воспользоваться либо утилитой быстрого просмотра, поставляемой в составе операционной системы, либо утилитой tdump.exe, поставляемой в составе Delphi.
Для вызова утилиты быстрого просмотра установите курсор мыши на значок нужного файла и нажмите правую кнопку. В появившемся меню должен присутствовать пункт "Быстрый просмотр", если этого пункта нет, то требуется установить компонент операционной системы "Быстрый просмотр".

Контекст устройства и контекст воспроизведения

Мы уже знаем, что ссылка на контекст устройства — это величина типа HDC. Для ее получения можно вызвать функцию GetDC, аргументом которой является ссылка на нужное окно.
Ссылке на контекст устройства соответствует свойство Canvas.Handle формы, принтера и некоторых компонентов Delphi.
Например, строки программы

Quote
Forml.Canvas.Ellipse (0, 0, 100, 100); И
Printer.BeginDoc ;
Printer.Canvas.Ellipse (0, 0, 100, 100);
Printer.EndDoc;

рисуют один и тот же круг, как на поверхности формы, так и в распечатываемом документе, т. е. на различных устройствах, причем если мы будем выводить разноцветную картинку на монохромный принтер, он справится с этой задачей, передавая цвета оттенками серого.
Такие вопросы приложение перекладывает на плечи операционной системы, решающей их посредством использования драйверов устройств.
Для того чтобы воспользоваться функциями воспроизведения Windows, приложению необходимо только указать ссылку на контекст устройства, содержащий средства и характеристики устройства вывода.
Справочный файл Win32 Programmer's Reference фирмы Microsoft, поставляемый в составе Delphi, о контексте устройства сообщает следующее:
"Контекст устройства является структурой, которая определяет комплект графических объектов и связанных с ними атрибутов и графические режимы, влияющие на вывод. Графический объект включает в себя карандаш для изображения линии, кисть для закраски и заполнения, растр для копирования или прокрутки частей экрана, палитру для определения комплекта доступных цветов, области для отсечения и других операций, маршрут для операций рисования".
В OpenGL имеется аналогичное ссылке на контекст устройства понятие ссылка на контекст воспроизведения.
Графическая система OpenGL, как и любое другое приложение Windows (хоть и размещенное в DLL), также нуждается в ссылке на устройство, на которое будет осуществляться вывод. Это специальная ссылка на контекст воспроизведения — величина типа HGLRC (Handle OpenGL Rendering Context, ссылка на контекст воспроизведения OpenGL).
В частности, упомянутые контексты являются хранилищами состояния системы, например, хранят информацию о текущем цвете карандаша.

 
proglibДата: Четверг, 19.03.2009, 05:15 | Сообщение # 3
Admin
Группа: Администраторы
Сообщений: 149
Репутация: 0
Статус: Offline
Урок 3. Минимальная программа OpenGL

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

Пример 1

Quote
unit Unit1;
interface

uses
Windows, Messages, Forms, Classes, Controls, ExtCtrls, ComCtrls,
StdCtrls, Dialogs, SysUtils,
OpenGL;

type
TfrmGL = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormPaint(Sender: TObject);
procedure FormDestroy(Sender: TObject);

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

var
frmGL: TfrmGL;

implementation

{$R *.DFM}

{=======================================================================
Рисование картинки}
procedure TfrmGL.FormPaint(Sender: TObject);
begin
wglMakeCurrent(Canvas.Handle, hrc);

glClearColor (0.5, 0.5, 0.75, 1.0); // цвет фона
glClear (GL_COLOR_BUFFER_BIT); // очистка буфера цвета

wglMakeCurrent (0, 0);
end;

{=======================================================================
Формат пикселя}
procedure SetDCPixelFormat (hdc : HDC);
var
pfd : TPixelFormatDescriptor;
nPixelFormat : Integer;
begin
FillChar (pfd, SizeOf (pfd), 0);
nPixelFormat := ChoosePixelFormat (hdc, @pfd);
SetPixelFormat (hdc, nPixelFormat, @pfd);
end;

{=======================================================================
{Создание формы}
procedure TfrmGL.FormCreate(Sender: TObject);
begin
SetDCPixelFormat(Canvas.Handle);
hrc := wglCreateContext(Canvas.Handle);
end;

{=======================================================================
Конец работы приложения}
procedure TfrmGL.FormDestroy(Sender: TObject);
begin
wglDeleteContext(hrc);
end;

end.

Список 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, т. е. создается контекст воспроизведения. Аргументом функции wglCreateContext является ссылка на контекст устройства, на который будет осуществляться вывод. Сейчас устройством вывода служит окно формы. Для получения этого контекста OpenGL необходима величина типа HDC. Здесь, как и во многих других примерах, мы используем факт, что Canvas.Handle и есть ссылка на контекст устройства, связанная с окном формы.

Функция wglCreateContext физически размещается в файле opengl32.dll, а прототип ее находится в файле windows.pas. В этот файл также помещены прототипы всех функций и процедур, имеющих отношение к реализации OpenGL под Windows, а прототипы собственно команд OpenGL расположены в файле opengl.pas.

Функции и процедуры, имеющие отношение только к Windows-версии OpenGL, обычно имеют приставку wgl, как, например, wgicreatecontext, но могут и не иметь такой приставки, как, например, SwapBuffers. Собственно команды OpenGL имеют приставки gl или glu в зависимости от размещения в библиотеках opengl32.dll и glu32.dll, соответственно.
Итак, контекст воспроизведения создан, и теперь можно осуществлять вывод командами OpenGL. Обработка события onPamt выглядит следующим образом:

Quote
wglMakeCurrent (Canvas.Handle, hrc); // установить контекст
glClearColor (0.5, 0.5, 0.75, 1.0); // цвет фона
glClear (GL_COLOR_BUFFER_BIT); // очистка буфера цвета
wglMakeCurrent (0,0); // освободить контекст
Первая строка делает контекст воспроизведения текущим, т. е. занимает его для последующего вывода. Далее задаем цвет фона. Следующую строку будем понимать как очистку экрана и окрашивание его заданным цветом. После работы освобождаем контекст.
Обработка события onDestroy формы состоит из одной строки:
wglDeleteContext(hrc);

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

Вернемся к команде glclearcolor, определяющей цвет фона. У нее четыре аргумента, вещественные числа, первые три из которых задают долю красного, зеленого и синего в результирующем цвете. Согласно справке, все четыре аргумента функции glclearcolor имеют тип GLclampf, соответствующий вещественным числам в пределах от нуля до единицы.

 
proglibДата: Четверг, 19.03.2009, 05:16 | Сообщение # 4
Admin
Группа: Администраторы
Сообщений: 149
Репутация: 0
Статус: Offline
Урок 4. Типы OpenGL

Библиотека OpenGL является переносимой по отношению к платформам, операционным системам и средам программирования.
Для обеспечения этой независимости в ней, в частности, определены собственные типы. Их префикс — "GL", например, GLint.
В каждой среде программирования в заголовочных файлах эти типы переопределяются согласно собственным типам среды. Разберем, как это делается в Delphi.

Заголовочный файл Delphi opengl.pas начинается с определения знакомого нам типа HGLRC:

type
HGLRC = THandle;

Далее следует описание всех остальных типов OpenGL, например, наиболее "ходовой" тип GLf loat соответствует типу single:

GLfloat = Single;

Но нe все из типов OpenGL удается точно перевести Например, GLclampf — вещественное число в пределах от нуля до единицы — в Delphi определен просто как single. Поэтому обычно в программах устанавливают "ручную" проверку на вхождение величины такого типа в требуемый диапазон.

Будьте внимательны с целыми числами: помимо типа GLint имеется тип GLuint — целое без знака, соответствующее типу cardinal.
В ряду типов OpenGL особо надо сказать о типе

GLboolean = BYTEBOOL;

Соответственно, определены две константы:
GL_FALSE = 0; GLJTRUE = 1;

Константы эти имеют непосредственное отношение к типу GLboolean, однако их значения не соответствуют типу BYTEBOOL. Из-за ошибки в описании типа (или определении констант) не удастся использовать стандартный для OpenGL код, поэтому вместо констант GL_FALSE и GLJTRUE будем использовать False и True, соответственно.
Конечно, можно самому скорректировать описание типа, например, так:

GLboolean = 0. .1;

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

TGLArrayf4 = array [0..3] of GLFloat;
TGLArrayfS = array [0..2] of GLFloat;
TGLArrayi4 = array [0..3] of GLint;

Разработчикам также пришлось ввести специальные типы для указателей, например:

PGLfloat = ^GLFloat;

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

 
proglibДата: Четверг, 19.03.2009, 05:17 | Сообщение # 5
Admin
Группа: Администраторы
Сообщений: 149
Репутация: 0
Статус: Offline
Урок 5. Тип TColor и цвет в OpenGL

Разберем еще одну версию нашей первой программы, использующей OpenGL

Пример 2

Quote
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls,
OpenGL;

type
TfrmGL = class(TForm)
btnColor: TButton;
ColorDialog1: TColorDialog;
procedure FormCreate(Sender: TObject);
procedure FormPaint(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure btnColorClick(Sender: TObject);

private
hrc : HGLRC;
R, G, B : GLFloat;
procedure ColorToGL (c : TColor; var R, G, B : GLFloat);
end;

var
frmGL: TfrmGL;

implementation

{$R *.DFM}

{=======================================================================
Перевод цвета из TColor в OpenGL}
procedure TfrmGL.ColorToGL (c : TColor; var R, G, B : GLFloat);
begin
R := (c mod $100) / 255;
G := ((c div $100) mod $100) / 255;
B := (c div $10000) / 255;
end;

{=======================================================================
Рисование картинки}
procedure TfrmGL.FormPaint(Sender: TObject);
begin
wglMakeCurrent(Canvas.Handle, hrc);

glClearColor (R, G, B, 1.0); // цвет фона
glClear (GL_COLOR_BUFFER_BIT); // очистка буфера цвета

wglMakeCurrent(0, 0);
end;

{=======================================================================
Формат пикселя}
procedure SetDCPixelFormat (hdc : HDC);
var
pfd : TPixelFormatDescriptor;
nPixelFormat : Integer;
begin
FillChar (pfd, SizeOf (pfd), 0);
nPixelFormat := ChoosePixelFormat (hdc, @pfd);
SetPixelFormat (hdc, nPixelFormat, @pfd);
end;

{=======================================================================
Создание формы}
procedure TfrmGL.FormCreate(Sender: TObject);
begin
SetDCPixelFormat(Canvas.Handle);
hrc := wglCreateContext(Canvas.Handle);
Randomize;
R := random;
G := random;
B := random;
end;

{=======================================================================
Конец работы приложения}
procedure TfrmGL.FormDestroy(Sender: TObject);
begin
wglDeleteContext(hrc);
end;

procedure TfrmGL.btnColorClick(Sender: TObject);
begin
If ColorDialog1.Execute then begin
ColorToGL (ColorDialog1.Color, R, G, B);
Refresh;
end;
end;

end.

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

Цвет, возвращаемый диалогом, хранится в свойстве color компонента класса TColorDiaiog. Согласно справке, значение $OOFFFFFF этого свойства соответствует белому цвету, $OOFFOOOO — синему, $OOOOFFOO — зеленому, $OOOOOOFF — красному. То есть для выделения красной составляющей цвета необходимо вырезать первый слева байт, второй байт даст долю зеленого, третий — синего. Максимальное значение байта — 255, минимальное — ноль. Цвета же OpenGL располагаются в интервале от нуля до единицы.

Введена пользовательская процедура, определяющая тройку составляющих цветов для OpenGL по заданному аргументу типа

TColor:
procedure TfrmGL.ColorToGL (с : TCoior; var R, G, В : GLFloat); begin
R := (c mod $100) / 255;
G := «c div $100) mod $100) / 255;
В := {с div $10000) / 255; end;

Из аргумента вырезаются нужные байты и масштабируются в интервал [0; 1].

Те же действия можно сделать и другим, более "продвинутым" способом

R .= (с and $FF) / 255;
G := ((с and $FFOO) shr 8) / 255;
В := ((с and $FFOOOO) shr 16) / 255.

Эта процедура используется в обработчике нажатия кнопки:
If ColorDialogl.Execute then begin
ColorToGL (ColorDialogl.Color, R, G, B);
Refresh; end;
В примере для простоты окно перекрашивается обычным для Delphi способом — через вызов метода Refresh формы.

 
proglibДата: Четверг, 19.03.2009, 05:18 | Сообщение # 6
Admin
Группа: Администраторы
Сообщений: 149
Репутация: 0
Статус: Offline
Урок 6. Двумерные построения. Точка

Необходимо отметить, что в OpenGL левый нижний угол области вывода имеет координаты [-1; —1], правый верхний — [1, 1].
Нарисуем на экране пять точек, четыре по углам окна и одну в центре:

Пример :

Quote
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, OpenGL;

type
TfrmGL = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormPaint(Sender: TObject);
procedure FormDestroy(Sender: TObject);

private
hrc: HGLRC;
end;

var
frmGL: TfrmGL;

implementation

{$R *.DFM}

{=================================================Перерисовка окна}
procedure TfrmGL.FormPaint(Sender: TObject);
begin
wglMakeCurrent(Canvas.Handle, hrc);

glViewPort (0, 0, ClientWidth, ClientHeight); // область вывода

glClearColor (0.5, 0.5, 0.75, 1.0); // цвет фона
glClear (GL_COLOR_BUFFER_BIT); // очистка буфера цвета

glPointSize (20); // размер точек
glColor3f (1.0, 0.0, 0.5); // текущий цвет примитивов
glBegin (GL_POINTS); // открываем командную скобку
glVertex2f (-1, -1);
glVertex2f (-1, 1);
glVertex2f (0, 0);
glVertex2f (1, -1);
glVertex2f (1, 1);
glEnd; // закрываем командную скобку

SwapBuffers(Canvas.Handle); // содержимое буфера - на экран
wglMakeCurrent(0, 0);
end;

{===================================================Формат пикселя}
procedure SetDCPixelFormat (hdc : HDC);
var
pfd : TPixelFormatDescriptor;
nPixelFormat : Integer;
begin
FillChar (pfd, SizeOf (pfd), 0);
pfd.dwFlags := PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER;
nPixelFormat := ChoosePixelFormat (hdc, @pfd);
SetPixelFormat (hdc, nPixelFormat, @pfd);
end;

{=====================================================Создание формы}
procedure TfrmGL.FormCreate(Sender: TObject);
begin
SetDCPixelFormat(Canvas.Handle);
hrc := wglCreateContext(Canvas.Handle);
end;

{============================================Конец работы приложения}
procedure TfrmGL.FormDestroy(Sender: TObject);
begin
wglDeleteContext(hrc);
end;

end.

Обработчик события OnPaint формы дополнился следующими строками:
glViewPort (0, 0, ClientWidth, ClientHeight); // область вывода
glPointSize (20); // размер точек
glColorSf (1.0, 1.0, 1.0); // цвет примитивов
glBegin (GL_POINTS); // открываем командную скобку
glVertex2f (-1, -1); // левый нижний угол
glVertex2f (-1, 1); // левый верхний угол
glVertex2f (0, 0); // центр окна
glVertex2f (1, -1); // правый верхний угол
glVertex2f (1, 1); // правый нижний угол
glEnd; // закрываем командную скобку
SwapBuffers(Canvas.Handle); // содержимое буфера - на экран

Первая строка задает область вывода указанием координат левого нижнего и правого верхнего углов (в пикселах, в оконных координатах). Если третий параметр процедуры glviewport записать как round (clientwidth / 2), то картинка вдвое сузится, но окрашено будет все окно.
Следующие две строки программы определяют параметры выводимых точек, размер и цвет.
На примере команды glColorSf разберем синтаксис команд OpenGL.
Из справки по этой команде ясно, что она принадлежит к целому набору команд glColor с различными окончаниями: 3b, 4i и прочие. Цифра в окончании соответствует количеству требуемых аргументов, а следующая цифрой буква показывает требуемый тип аргументов. То есть gicoior3f требует в качестве аргументов тройку вещественных (float) чисел, а glColor3i — тройку целых (int) чисел.
Аналогичный синтаксис мы встретим у многих других команд OpenGL.
Здесь же, в справке, выясняем, что при записи функции в вещественной форме аргументы лежат в интервале [0; 1], а в целочисленной форме — линейно отображаются на этот интервал, т. е. для задания белого цвета целочисленная форма команды будет выглядеть так:
glColor3i (2147483647, 2147483647, 2147483647); // цвет примитивов
где максимальное 8-битное целое без знака соответствует предельному значению интервала.
Почти всегда предпочтительно использовать команду в вещественной форме, поскольку OpenGL хранит данные именно в вещественном формате. Исключения оговариваются в файле справки.
Если имя команды заканчивается на v (векторная форма), то аргументом ее служит указатель на структуру, содержащую данные, например, массив. То есть, например, если последние три символа в имени команды 3fv, то ее аргумент — адрес массива трех вещественных чисел. Использование такой формы команды является самым оптимальным по скоростным характеристикам.
Далее в программе следуют функции (командные скобки) glBegin и glEnd, между которыми заключены собственно процедуры рисования.
Разберемся подробнее с функциями glBegin и glEnd ввиду их особой важности: большинство графических построений связано с использованием именно этой пары функций.
Во-первых, необходимо уяснить, что это командные скобки библиотеки OpenGL, не заменяющие операторные скобки языка Pascal и не имеющие к ним никакого отношения. Ошибка при использовании командных скобок не распознается компилятором. Если в программе написана неправильная вложенность командных скобок OpenGL, то ошибка проявится только в процессе диалога приложения с сервером.
Во-вторых, внутри этих скобок могут находиться любые операторы языка Pascal и почти любые функции OpenGL (вернее, очень многие). Включенные в скобки команды OpenGL отрабатываются так же, как и за пределами этих скобок. Главное назначение командных скобок — это задание режима (примитива) для команд glvertex (вершина), определяющих координаты вершин для рисования примитивов OpenGL.
В рассмотренном примере аргументом функции glBegin взята символическая константа GL_POINTS. Из файла справки выясняем, что в этом случае все встретившиеся до закрывающей скобки glEnd вершины (аргументы glvertex) задают координаты очередной отдельной точки. Команду glvertex мы взяли в форме с двумя вещественными аргументами.
Мы собирались нарисовать четыре точки по углам окна и одну в центре, поэтому между командными скобками располагаются пять строк с вызовом glvertex, аргументы которых соответствуют положениям точек в системе координат области вывода библиотеки OpenGL.
Сейчас обратите внимание на то, что вместе с изменением размеров окна рисуемое изображение также изменяется: точки всегда рисуются на своих местах относительно границ окна. Следующее замечание тоже очень важно: обработчик события onResize формы тот же, что и у события onPaint.

 
proglibДата: Четверг, 19.03.2009, 05:19 | Сообщение # 7
Admin
Группа: Администраторы
Сообщений: 149
Репутация: 0
Статус: Offline
Урок 7. Двумерные построения. Отрезок

От точек перейдем к линиям. Разберем следующий возможный аргумент команды glBegin — константу GL_LINES, задающий примитив "независимый отрезок".
Для этого примитива следующие в командных скобках вершины (т. е. функции glertex) задают попарно координаты начала и конца каждого отрезка прямой. Снова вернемся к примеру с точками и подправим код рисования следующим образом :

Quote
glBegin (GL_LINES);
glVertex2f (-1, 1);
glVertex2f (1, -1);
glVertex2f (-1,-1);
glVertex2f (1, 1);
glEnd;

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

glLineWidth (2.5);

Эта функция также должна выноситься за командные скобки.
Как и у точек, у линий можно устранять ступенчатость. Исправьте код следующим образом (Пример):

Quote
glLineWidth (15);
glEnable (GL_LINE_SMOOTH);
glBegin (GL_LINES);
glVertex2f (-0.7, 0.7);

и посмотрите результаты работы программы с вызовом и без вызова
glEnable (GL_LINE_SMOOTH) .

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

Следующая константа — GL_LINE_STRIP — определяет примитив, когда перечисляемые вершины последовательно соединяются одна за другой. Приводимый код поясняет отличие этого примитива от предыдущего.

Quote
glBegin (GL_LINE_STRIP);
glVertex2f (-1, -1);
glVertex2f (-1, 1);
glVertex2f (1, 1);
glVertex2f (1, -1) ;
glEnd;

Результат — буква П по границе окна.

В примитиве, задаваемом константой GL_LINE_LOOP, также последовательно соединяются перечисляемые вершины, однако последняя вершина замыкается с самой первой. Если в предыдущем примере использовать GL_LINE_ LOOP, будет построен квадрат по границе окна.

В примерах на отрезки мы пока использовали непрерывную линию. Для рисования пунктирной линией перед командными скобками добавьте следующие строки (Пример):

Quote
glLineStipple (I, $FOFO);
glEnable (GL__LINE_STIPPLE) ;

У функции glLineStipple первый аргумент — масштабный множитель, второй аргумент задает шаблон штриховки (побитовым способом).

 
proglibДата: Четверг, 19.03.2009, 05:19 | Сообщение # 8
Admin
Группа: Администраторы
Сообщений: 149
Репутация: 0
Статус: Offline
Урок 8. Двумерные построения. Треугольник

Закончив с линиями, перейдем к треугольникам — примитиву, задаваемому константой GL_TRIANGLES. В этом примитиве последующие вершины берутся триплетами, тройками, по которым строится каждый отдельный треугольник.
Следующий код служит иллюстрацией рисования одного треугольника.

Quote
glBegin (GL_TRIANGLES);
glVertex2f (-1, -1);
glVertex2f (-1, 1);
glVertex2f (1, 0);

glEnd;

Для рисования правильного шестиугольника из отдельных треугольников код должен выглядеть так:

Quote
glBegin (GL_TRIANGLES);
For i := 0 to 5 do begin
glVertex2f (0, 0);
glVertex2f (0.5 * cos (2 * Pi * i / 6),
0.5 * sin (2 * Pi * i / 6));
glVertex2f (0.5 * cos (2 * Pi * (i + 1) / 6),
0.5 * sin (2 * Pi * (i + 1) / 6));
end;
glEnd;

В качестве опорных точек выбраны шесть точек на окружности.
Мы можем перейти к примитиву, задаваемому константой GL_TRIANGLE_STRIP: связанная группа треугольников. Первые три вершины образуют первый треугольник, вершины со второй по четвертую — второй треугольник, с третьей по пятую — третий и т. д.

Пример нарисует флажок, образованный наложением двух треугольников (рис. 1):

Quote
glBegin (GL_TRIANGLE_STRIP);
glVertex2f (1, 1);
glVertex2f (-1, 1);
glVertex2f (-1, -1);
glVertex2f (1, -1);
glEnd;

Рис. 1. Флаг получается наложением двух отдельных треугольников

Попробуем поэкспериментировать с нашей программой: будем рисовать треугольники разного цвета (проект из подкаталога Ех10):

Quote
glBegin (GL_TRIANGLE_STRIP);
glColor3f (0.0, 0.0, 1.0);
glVertex2f (1, 1);
glVertex2f (-1, 1);
glColor3f (1.0, 0.0, 0.0);
glVertex2f (-1, -1);
glVertex2f (1, -1);
glEnd;

Результат окажется неожиданным и живописным: у фигуры возникнет плавный переход синего цвета в красный (рис. 2).

Рис. 2. Плавный переход цвета

Вызов перед командными скобками функции glShadeModel (GL_FLAT) , задающей правило тонирования, избавит от градиентного заполнения фигуры, но результат все равно будет неожиданным — оба треугольника станут красными, т. е. цвета второго из них.

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

Доступно только для пользователей

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

Quote
glBegin (GL_TRIANGLE_FAN);
glVertex2f (0, 0);
For i := 0 to 6 do begin
glColor3f (random, random, random);
glVertex2f (0.5 * cos (2 * Pi * i / 6),
0.5 * sin (2 * Pi * i / 6));
end;
glEnd;

Теперь поговорим о режимах вывода многоугольников.
Для устранения ступенчатости многоугольников используется команда glEnable с аргументом GL_POLYGON_SMOOTH.

Если в примеры на треугольники перед командными скобками поместить строку glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
то треугольники будут рисоваться контурно — только линии
Команда glPolygonMode задает режим воспроизведения для всех типов многоугольников.

Ширину линий контура можно варьировать с помощью glLinewidth, пунктирные линии контура задаются командой glLineStipple.

Команда glPolygonMode позволяет выводить вместо заполненных и контурных многоугольников только их вершины, если ее вторым аргументом взять константу GL_POINT (не путать с GL_POINTS!). Размеры точек вершин и наличие сглаживания у них можно задавать так же, как и для обычных точек. По умолчанию многоугольники строятся заполненными (включен режим GL_FILL).

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

 
proglibДата: Четверг, 19.03.2009, 05:20 | Сообщение # 9
Admin
Группа: Администраторы
Сообщений: 149
Репутация: 0
Статус: Offline
Урок 9. Многоугольник

Для рисования прямоугольника на плоскости можно воспользоваться командой glRectf. Это одна из версий команды glRect. Ее аргументом являются координаты двух точек — противоположных углов рисуемого прямоугольника. Посмотрите простой пример на построение прямоугольника с использованием этой команды.
При использовании glRect необходимо помнить, что координата по оси Z в текущей системе координат для всех вершин равна нулю.
Константа GL_QUADS задает примитив, когда перечисляемые вершины берутся по четыре и по ним строятся независимые четырехугольники.
Следующий код — иллюстрация использования этого примитива: строятся два независимых четырехугольника

Quote
glBegin (GL_QUADS);
glColor3f (random, random, random);
glVertex2f (-0.6, 0.2);
glVertex2f (-0.7, 0.7);
glVertex2f (0.1, 0.65);
glVertex2f (0.25, -0.78);
glColor3f (random, random, random);
glVertex2f (0.3, -0.6);
glVertex2f (0.45, 0.7);
glVertex2f (0.8, 0.65);
glVertex2f (0.9, -0.8);
glEnd;

Результат работы программы иллюстрирует рисунок

Примитив, задаваемый константой GL_QUAD_STRIP, состоит из связанных четырехугольников. Первый четырехугольник формируется из вершин номер один, два, три и четыре. Второй четырехугольник в качестве опорных берет вторую, третью, пятую и четвертую вершины. И так далее.
Если в предыдущем примере поменять константу на GL_QUAD_STRIP то изображение в окне получится таким, как на рисунке
Для рисования выпуклого многоугольника используется примитив GL_POLYGON. Многоугольник строится из связанных треугольников с общей вершиной, в качестве которой берется первая среди перечисляемых в командных скобках. Код для рисования шестиугольника может выглядеть так:

Quote
glBegin (GL_POLYGON);
For i := 0 to 6 do begin
glColor3f (random, random, random);
glVertex2f (0.5 * cos (2 * Pi * i / 6), 0.5 * sin (2 * Pi * i / 6));
end;
glEnd;

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

 
proglibДата: Четверг, 19.03.2009, 05:21 | Сообщение # 10
Admin
Группа: Администраторы
Сообщений: 149
Репутация: 0
Статус: Offline
Урок 10. Массивы вершин

Мы рассмотрели все десять примитивов, имеющихся в нашем распоряжении. Код практических построений, включающих сотни и тысячи отдельных
примитивов, подчас чересчур громоздок, большая часть его в таких случаях — сотни и тысячи строк с вызовом команды glVertex.
Библиотека OpenGL располагает средством сокращения кода, базирующимся на использовании массивов вершин. В массиве вершин, т. e. массиве вещественных чисел, задаются координаты опорных вершин, по которым вызовом одной команды glDrawArrays строится последовательность примитивов заданного типа.
У команды glDrawArrays три аргумента: тип примитива и характеристики используемого массива.
Для использования этой функции надо, как минимум, задать массив вершин, по которым будет строиться множество примитивов. Ссылка на массив вершин создается командой glVertexPointer, также являющейся расширением стандарта. Помимо массива вершин, для украшения картинки будем также использовать массив цвета вершин, ссылка на который задается командой glColorPointer, тоже не входящей в стандарт. Прибавив окончание Ехт к именам этих команд, можно получить контекстную подсказку, по которой легко разобраться с их аргументами. Но, к сожалению, для использования массива вершин полученной информации недостаточно, необходимо еще использовать, как минимум, команду glEnableClientState, справку по которой уже невозможно получить никакими ухищрениями. Эта команда аналогична glEnable, но применяется только в контексте массивов вершин. У нее имеется парная команда — glDisableClientState, отключающая использование массива вершин.
В заголовочном файле opengl.pas, поставляемом с Delphi, отсутствуют прототипы команд, не входящих в стандарт OpenGL, a также отсутствует описание констант, используемых такими командами, что немного затруднит наше изучение этой библиотеки.

Массив с именем vertex содержит координаты четырех точек — углов квадрата, а в массиве цветов Colors содержатся соответствующие вершинам значения RGB:

Quote
Vertex : Array [0..3, 0..1] of GLFloat; Colors : Array [0..3, 0..2] of GLFloat;

Код рисования выглядит так:

Quote
glVertexPointer(2, GL_FLOAT, 0, @Vertex); // указатель на массив вершин glColorPointer(3, GL FLOAT, 0, @Colors); // указатель на массив цветов
glEnableClientState(GL_VERTEX_ARRAY); // массив вершин - включаем режим
glEnableClientState(GL_COLOR_ARRAY); // массив цветов — включаем режим
glDrawArrays(GL_POLYGON, 0, 4); // рисование множества полигонов
glDisableClientState(GL_COLOR_ARRAY); // выключаем режимы (в этом
glDisableClientState(GL_VERTEX_ARRAY); // примере не обязательно)

Значение первого аргумента команды glVertexPointer равно двум, поскольку вершины заданы указанием двух координат. To есть этот аргумент задает, по сколько вещественных чисел считывать для каждой точки.
Результат работы программы показан на рисунке

Для использования команд-расширений программу пришлось дополнить строками с описанием прототипов процедур:

Quote
procedure glVertexPointer (size: GLint; atype: GLenum;
stride: GLsizei; data: pointer); stdcall; external OpenGL32;
procedure glColorPointer (size: GLint; atype: GLenum; stride: GLsizei;
data: pointer); stdcall; external OpenGL32;
procedure glDrawArrays (mode: GLenum; first: GLint; count: GLsizei);
stdcall; external OpenGL32;
procedure glEnableClientState (aarray: GLenum); stdcall; external OpenGL32;
procedure glDisableClientState (aarray: GLenum); stdcall; external OpenGL32;

Здесь openGL32- константа, определяемая в модуле opengl.pas.
Потребовалось также задать значение констант, используемых этими процедурами:
const
GL_VERTEX_ARRAY = $8074; GL COLOR ARRAY = $8076;
Значения констант и информацию о типах аргументов процедур можно почерпнуть из заголовочных файлов сторонних разработчиков. Информация о команде glEnableClientstate взята из описания OpenGL фирмы SGI.
Первым аргументом glDrawArrays может быть любая константа, которую допускается использовать в glBegin.

В примере по массиву вершин строится множество полигонов вызовом команды

glDrawArrays(GL_POLYGON, 0, 4); // рисование множества полигонов
Эта команда является сокращением следующей последовательности команд

Quote
glBegin (GL_POLYGON);
glArrayElement(0) ;
glArrayElement(1);
glArrayElement(2);
glArrayElement(3) ;
glEnd;

Используемая здесь функция glArrayElement (также расширение стандарта) берет в качестве вершины примитива элемент массива с заданным индексом. Индекс, как видно из примера, начинается с нуля.

Вы, возможно, задаетесь вопросом, почему в заголовочном файле, поставляемом с Delphi, отсутствуют прототипы процедур, хоть и не входящих в стандарт OpenGL, но документированных разработчиком библиотеки. Ответ на этот вопрос заключается, по-видимому, в том, что этот файл является трансляцией заголовочных файлов gl.h и glu.h, опубликованных SGI, и в него вошло только то, что документировано в этих файлах. Как явствует из заголовка файла, за основу положены файлы версии 1993 года.
Помимо массивов вершин и массива цветов вершин, имеется массив границ — аналог команды glEdgeFlag применительно к массивам вершин. В этом случае необходимо использовать команду glEdgeFlagPointer. Прибавив суффикс Ехт, вы можете получить справку по этой команде. В ней, в частности, говорится, что включение режима использования массива границ осуществляется так:
glEnable (GL_EDGE_FLAG_ARRAY_EXT);
Однако это указание, по-видимому, является ошибочным. Можно воспользоваться массивом флагов границ только с использованием следующего кода:
glEnableClientState(GL_EDGE_FLAG_ARRAY);
To же самое можно сказать по поводу аргументов команды.

Источник

 
  • Страница 1 из 1
  • 1
Поиск:


Библиотека программиста © 2025 - все права нарушены! | Бесплатный хостинг uCoz
Rambler's Top100