Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

675

.pdf
Скачиваний:
1
Добавлен:
06.12.2022
Размер:
4.11 Mб
Скачать

привключенном режимесмешивания цветов, впротивномслучае игнорируется). Величины R, G, B, A имеют специальный тип данных OpenGL — GLclampf, вещественный тип данных, изменяющихся в пределах [0; 1].

Наличие собственных типов данных в аргументах функций OpenGL — один из элементов обеспечения независимости библиотеки от операционной системы.

Цвет отдельных примитивов, создающих изображение, — точек, отрезков, полигонов—определяется непосредственнопри описании вершин (узловых точек) этих примитивов функцией glColor3f (R, G, B);

где R, G, B — компоненты цвета.

Следует отметить, что OpenGL представляет собой конечный автомат — назначенные режимы отображения действуют на все последующие построения вплоть до отмены сделанных назначений. Например, установленный функцией glColor3f (R, G, B) цвет примитивов будет действовать на все создаваемые примитивы, пока не встретится следующая функция glColor3f (R, G, B).

Порядок работы. Геометрические построения

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

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

Рассмотрим частьпрограммного модуля [2], рисующеготочки в центре и по углам формы.

1 1

glPointSize (20); glBegin (GL_POINTS);

glVertex2f ( -1, -1); glVertex2f (-1, 1); glVertex2f (0, 0); glVertex2f (1, -1); glVertex2f (1, 1);

glEnd;

В OpenGL описание геометрии примитива (указание координат вершин) располагается в пределах операторных скобок glBegin ()… glEnd. Тип примитива (точки, отрезки или многоугольники) указывается аргументом функции glBegin (). В приведенном примере это GL_POINTS.

Координаты вершин задаются функцией glVertex2f (x, y). Посколькумы работаемнаплоскости, тоздесьотсутствуеттретья координата z. Полныйформат координатвершин задается в виде

glVertex4f (x, y, z, w),

где величина w используется как множитель в однородных координатах, и если w = 1, то может быть опущена. Тип данных, применяемыхдляаргументовфункцииglVertexnf(),—GLfloat.

С каждой вершиной ассоциируются ее атрибуты. В число основных атрибутов, помимо положения вершины в пространстве, входят цвет вершины и вектор нормали.

Функция glPointSize (), вынесенная запределы операторных скобок, определяет размер точки в пикселях.

Любой отрезок определяется координатами его конечных точек. Одиночный отрезок должен быть описан так:

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

glEnd;

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

1 2

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

glEnd;

Наконец, замкнутую фигуру можно получить, используя предыдущий код, указав в качестве аргумента операторных скобок параметр GL_LINE_LOOP. Примеры реализации примитивов «Отрезок» и «Точка» представлены на рис. 1.

Рис. 1. Примеры реализации примитивов «Точка» и «Отрезок» [1]

Так же как и точки, отрезки имеют толщину, которая устанавливается также за пределами операторных скобок функцией glLineWidth (n), где n — ширина линии в пикселях. Но, в отличие от точек, отрезки могут быть нарисованы в особом режиме рисования — с учетом типа линии. Тип линии — это способ начертания линии (сплошная, штриховая, штрих-пунк- тирная и т.д.).

Цвет задается только для вершин примитива. Его значение по длине примитива (отрезка) определяется по правилам интерполяции (по умолчанию). Например, интересный результат будет в следующем случае (цвет плавно меняется по длине широкого отрезка):

1 3

glLineWidth (10); glBegin (GL_ LINES);

glColor3f (0.0, 0.0, 0); glVertex2f (-1, -1); glColor3f (1.0, 0.0, 0); glVertex2f (1, 1);

glEnd;

Любой режим рисования устанавливается в OpenGL функцией glEnable (А), где аргумент А указывает задаваемый режим. Рисование с учетом типа линии требует указания

glEnable (GL_LINE_STIPPLE).

Собственно тип линии задается функцией glLineStipple (n, m),

где n — масштаб штриха (масштаб типа линии); m — шестнадцатеричный код типа линии. Этот шестнадцатеричный код преобразуется в двоичную последовательность, каждая единица которой означает закрашенный пиксель. Например, шестнадцатеричному коду m = $F0F0 соответствует двоичная последовательность 1111000011110000, что приведет к изображению линии, состоящей из штрихов длиной четыре пикселя и таких же пробелов между ними. Длина штриха умножается на масштаб типа линии, и если назначить n =2, то изображаемая линия будет иметь штрихи и пробелы между ними длиной уже по восемь пикселей.

Рекомендуется любой установленный функцией glEnable (А) режим рисования отменять парной ей функцией glDisable (А).

Порядок работы. Работа с мышью и преобразование координат

В среде Delphi работа с мышью выполняется через соответствующие события формы и в большинстве случаев сводится к получению текущих координат курсора. Однако координаты, непосредственно полученные с указателя мыши, — это координаты экрана в пикселях (рис. 2, а). Их необходимо преобразовать в координаты геометрической модели в единицах формы, которыеимеют нетолькодругие единицы измерения, ноидругое направление координатных осей (рис. 2, б).

1 4

Рис. 2. Системы координат: а — естественная экранная; б — формы Delphi

Преобразование координат при построении на плоскости можно выполнить по формулам:

Xмодели = (2/ClientWidth) * Xкурсора – 1;

Yмодели = (2/ClientHeight) * (ClientHeight – Yкурсора) – 1.

Чтобы изменения координат модели были отображены на экране, необходимо применить функцию API Windows перерисовки окна (вызывает событие OnPaint):

InvalidateRect (Handle, nil, False).

Интересный пример использования мыши можно найти в [2, примеры к гл. 1].

Порядок работы. Окончание

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

procedure TfrmGL.FormDestroy(Sender: TObject); begin

wglMakeCurrent(0, 0); wglDeleteContext(hrc); ReleaseDC (Handle, DC); DeleteDC (DC);

end;

Пример приложения

Приведем текст основных модулей программы, рисующей две разноцветные перекрещивающиеся линии на единственной форме:

unit Unit1; interface uses

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

1 5

type

TfrmGL = class(TForm)

procedure FormCreate(Sender: TObject); procedure FormPaint(Sender: TObject); procedure FormDestroy(Sender: TObject);

private

hrc: HGLRC; dc: HDC;

end;

var

frmGL: TfrmGL; implementation {$R *.DFM}

{============Перерисовка окна}

procedure TfrmGL.FormPaint(Sender: TObject); begin

wglMakeCurrent (DC, hrc);

glViewPort (0, 0, ClientWidth, ClientHeight); glClearColor (0.5, 0.5, 0.75, 1.0);

glClear(GL_COLOR_BUFFER_BIT); glLineWidth (15);

glLineStipple (1, $F0F0); glEnable (GL_LINE_STIPPLE); glBegin (GL_LINES);

glColor3f (1.0, 0.0, 0.0); glVertex2f (-1, -1); glVertex2f (1, 1); glColor3f (0.0, 1.0, 0.0); glVertex2f (-1, 1); glVertex2f (1, -1);

glEnd;

SwapBuffers(DC); wglMakeCurrent (0, 0);

end;

1 6

{==========================Форматпикселя} 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

DC:=GetDC (Handle);

SetDCPixelFormat(DC);

hrc := wglCreateContext(DC); end;

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

wglDeleteContext(hrc); ReleaseDC (Handle, DC); DeleteDC (DC);

end;

end;

В отличие от приведенных выше рассуждений, здесь установление иудалениетекущего контекста воспроизведения помещено в модуль события OnPaint. Функции в модуле завершения работы приложения ReleaseDC (Handle, DC) иDeleteDC (DC)

освобождают и удаляют контекст устройства.

Синтаксис команд

Все команды, процедуры и функции OpenGL начинаются с префиксов wgl, gl, glu, glut, указывающих на библиотеку, содержащую описание команды.Все константы OpenGL начинаются с префикса GL_ и записываются прописными буквами. В

1 7

состав команд входят суффиксы, указывающие на количество и тип аргументов. В общем виде полное имя команды имеет вид:

[wgl gl glu glut]CommandName[1 2 3 4][b s i f d ub us ui][v] ([args]),

где wgl, gl, glu, glut — имя библиотеки, в которой описана эта функция:

wgl — модуль Windows.pas, файл opengl32.dll; gl — модуль OpenGL.pas, файл opengl32.dll;

glu —модульOpenGL.pas, файл glu32.dl; glut библиотека,

не имеющая непосредственной реализации в Delphi. Некоторая ее модификация для ObjectPascal приведена в [2].

CommandName

имя команды (процедуры или функции)

[1 2 3 4]

количество аргументов команды

[b i f]

тип аргумента: b — GLbyte (аналог char),

 

i — Glint, GLsizei (аналог int),

f — GLfloat, GLclampf (аналог float) и т.д.

[v]впараметрах используется указательна массив значений

Таблица 2

Справочные сведения о командах, использованных в лабораторной работе

Команда

Действие

wglCreateContext (hdc DC)

Создание контекста воспроизведения

 

(визуализации), связанного с контекстом

 

устройства DC

wglMakeCurrent (hdc DC, hglrc

Установление текущим контекста воспроизведения

HRC)

HRC, связанного с контекстом устройства DC.

 

Освобождение текущего контекста устройства –

 

вызов функции с параметрами 0, 0

glViewPort (GLint X0, GLint Y0,

Установление параметров области вывода

GLsizei WIDTH, GLsizei HEIGHT)

 

glClearColor (GLclampf R,

Установление цвета фона в цветовой модели

GLclampf G, GLclampf B,

RGBA. При этом тип GLclampf определяет

GLclampf A)

вещественный тип данных в диапазоне [0…1]

glClear (bitfield BUF)

Очистка буфера BUF:

 

Если BUF = GL_COLOR_BUFFER_BIT, то

 

очищается (обнуляется) буфер цвета и заполняется

 

значениями цвета фона;

 

Если BUF = GL_DEPTH_BUFFER_BIT, то

 

очищается (обнуляется) буфер глубины;

 

Если BUF = GL_COLOR_BUFFER_BIT or

 

GL_DEPTH_BUFFER_BIT, то обнуляются оба

 

указанных буфера

1 8

 

Продолжение табл. 2

Команда

Действие

 

glLineWidth (n)

Назначение толщины линии в пикселях

 

glPointSize (n)

Назначение размера точки в пикселях

 

glLineStipple (n, m)

Задание типа линии. Параметр n – масштаб

 

 

штриха (масштаб типа линии); параметр m

 

шестнадцатеричный код типа линии

glEnable (GL_LINE_STIPPLE)

Назначение режима рисования с учетом типа

 

 

линии

glVertex2i (Glint X, Glint Y)

Задание координат вершины на плоскости

 

 

целыми числами

glVertex3f (GLfloat X, GLfloat Y,

Задание координат вершины в пространстве

 

GLfloat Z)

вещественными числами

glVertex3fv (GLfloat @XYZ)

Задание координат вершины в пространстве

 

 

массивом вещественных чисел

glVertex4f (GLfloat X, GLfloat Y,

Задание координат вершины в пространстве

 

GLfloat Z, GLfloat W)

вещественными числами в формате однородных

 

координат

glColor3f (GLclampf R, GLclampf G,

Задание текущего цвета вершины в формате

 

GLclampf B)

цветов RGB:

 

0.0, 0.0, 0.0 – черный;

 

1.0, 0.0, 0.0 – красный;

 

0.0, 1.0, 0.0 – зеленый;

 

0.0, 0.0, 1.0 – синий и т.д.

glColor4f (GLclampf R, GLclampf G,

Задание текущего цвета вершины в формате

 

GLclampf B, GLclampf A)

цветов RGBA, т.е. с учетом -компоненты (только

 

в режиме смешивания цветов)

glBegin (GLenum mode)

Операторные скобки для задания вершин

 

геометрических примитивов. Параметр mode

glEnd ()

определяет тип примитива, который задается

 

внутри операторных скобок glBegin()…glEnd() и

 

может принимать следующие значения:

 

GL_POINTS – рисует точку на месте каждой из

 

вершин (рис. 1);

 

GL_LINES – рисует серию несоединенных между

 

собой отрезков. Рисуются отрезки между V0 и V1,

 

между V2 и V3, и т.д. Если число вершин нечетно,

 

то лишняя вершина игнорируется;

 

GL_LINE_STRIP – рисование незамкнутой

 

ломаной линии путем последовательного

 

соединения указанных вершин. При одной

 

вершине ничего не рисуется;

 

GL_LINE_LOOP – рисование замкнутой ломаной

 

линии.

 

Внутри операторных скобок можно вызывать

 

только функции: glVertex, glColor, glIndex,

 

glNormal, glTexCoord, glEvalCoord, glEvalPoint,

 

glMaterial

 

1 9

 

Окончание табл. 2

 

 

Команда

Действие

SwapBuffers (hdc DC)

Обмен содержимым заднего и переднего буферов

 

кадра. Используется только при установленном

 

режиме двойной буферизации

 

(PFD_DOUBLEBUFFER)

InvalidateRect (Handle, nil, False)

Перерисовка окна, указанного параметром Handle

wglDeleteContext (hglrc HRC)

Освобождение контекста воспроизведения

 

(визуализации)

ReleaseDC (Handle, hdc DC)

Освобождение контекста устройства

DeleteDC (hdc DC)

Удаление контекста устройства

Варианты заданий

Написать программу построения фигур с помощью отрезков (рис. 3). Во всех вариантах фигура вписывается в окно формы, имеющее координаты нижнего левого угла [–1; –1] и верхнего правого — [1; 1]. Шаг смещения фигур — постоянный. Цвет фигур и тип линий — различны.

Контрольные вопросы

1.Архитектура библиотек OpenGL и организация конвейера.

2.Категории команд (функций) библиотеки.

3.Для чегонужнафункция обновления изображения ичтоона делает?

4.Примитивы и атрибуты в OpenGL.

5.Что такое операторные скобки и для чего они используются

вOpenGL?

6.Что подразумевается под термином «область вывода»?

7.Приведите примеры примитивов, используемых библиоте-

кой OpenGL.

8.Как задаются координаты примитивов для построения объектов в двухмерном построении?

9.Что подразумевается под термином«сглаживание примитивов»?

10.Приведите примеры методики создания отрезков.

11.Приведите примеры изменения толщины отрезка.

12.Приведите примеры изменения типа линии отрезка.

13.Приведите примеры изменения цвета отрезка.

14.Назначение процедуры SwapBuffers().

15.Понятие однородных координат.

16.Особенностикоординатныхсистемвкомпьютернойграфике.

2 0

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]