Необходимо отметить, что в 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.
|