Міністерство освіти і науки України
Національний університет „Львівська Політехніка”
Лабораторна робота № 4
„ ДВОМІРНІ ПОБУДОВИ З ВИКОРИСТАННЯМ OpenGL
ЗАСОБАМИ BORLAND DELPHI”
з курсу „ Геометричне моделювання у конструюванні інженерних об'єктів і систем ”
Львів-2005
МЕТА РОБОТИ
Мета роботи – ознайомлення та практичне освоєння технології й основ роботи з графічними можливостями бібліотеки OpenGL на площині в операційному середовищі Wіndows. Вивчити способи підключення бібліотеки OpenGL при розробці програмних проектів
засобами візуального середовища програмування Borland Delphi. Ознайомитися та засвоїти основні графічні функцій та процедури, набути практичних навиків програмування графіки для Wіndows-програм на основі OpenGL.
КОРОТКІ ТЕОРЕТИЧНІ ВІДОМОСТІ
ОСНОВНІ ПОНЯТТЯ
OpenGL – це стандартна бібліотека для усіх 32-розрядних операційних систем, у тому числі і для операційної системи Windows.
OpenGL – не окрема програма, а частина операційної системи. Це означає, що відкомпільована програма, яка використовує OpenGL, не потребує ніяких додаткових програм чи модулів, крім стандартних, що містяться на будь-якому комп’ютері з встановленою
операційною системою Windows 95 версії OSR2 та вище. У склад стандартної поставки Delphi (починаючи з третьої версії) входить заголовочний файл, який дозволяє будувати програми з використанням OpenGL, а також довідковий файл по
командах цієї бібліотеки.
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.
Архітектура і особливості синтаксису
З точки зору архітектури, графічна система OpenGL є конвейєром, що складається з декількох етапів обробки даних:
• Апроксимація кривих і поверхонь.
• Обробка вершин і збирання примітивів.
• Растеризация і обробка фрагментів.
• Операції над пікселями.
• Підготовка текстури.
• Передача даних в буфер кадру.
Узагалі, OpenGL можна порівняти з кінцевим автоматом, стан якого визначається безліччю значень спеціальних змінних (їхні імена звичайно починаються з символів GL_) і значеннями поточної нормали, кольору та координат текстури. Уся ця інформація буде
використана при надходженні в систему координат вершини для побудови фігури, в яку вона входить. Зміна станів відбувається за допомогою команд, які оформляються як виклики функцій.
ПІДКЛЮЧЕННЯ OPENGL
КОНТЕКСТ ГРАФІЧНОГО ПРИСТРОЮ
Графічні функції зі складу APІ Wіndows об’єднані в окрему групу – підсистему GDІ (Graphіc Devіce Іnterface, інтерфейс графічного пристрою). Важлива риса підсистеми GDІ – апаратна незалежність багатьох функцій від конкретного графічного пристрою.
Контекст графічного пристрою (Devіce Context) – це важливий елемент графіки в середовищі операційної системи Wіndows. Поняття контексту введене для опису того, де буде малюватися зображення. Іншими словами, контекст графічного пристрою вказує площину
відображення, на яку робиться графічний вивід. Як контекст може бути вікно програми на екрані дисплея, чи сторінка принтера, чи інше місце, куди можна направити графічний вивід. Якщо ваша програма робить виклик графічних функцій APІ Wіndows, таких як
малювання крапок, ліній, фігур, тексту тощо, необхідно вказувати ідентифікатор контексту (handle of devіce context) і координати. Виклик необхідного драйвера – для екрана дисплея, принтера чи іншого пристрою – робить уже сама Wіndows. Це значною мірою звільняє програміста від другорядних справ і полегшує розробку програм, однак бажано враховувати
специфіку роботи конкретного пристрою. Ідентифікатор контексту графічного пристрою (hdc, Handle Device Context) – це числове
значення, знання якого дає можливість направити графічний вивід у потрібне місце. Перед початком малювання необхідно одержати це числове значення. Після малювання звичайно потрібно звільнити, деактивизировать контекст. Недотримання цієї вимоги чревате
неприємними наслідками – від втрати пам’яті до припинення нормальної роботи програми.
Коректне використання контексту графічного пристрою здійснюється в такій послідовності:
1. Створення, активізація контексту, одержання значення hdc.
2. Малювання за допомогою графічних функцій APІ Wіndows.
3. Знищення, деактивизация контексту відповідного hdc.
Для того щоб операційна система могла розрізняти вікна для здійснення діалогу з ними, усі вікна при своєму створенні реєструються в операційній системі та отримують унікальний ідентифікатор, який називається “зсилка на вікно”. Тип цієї величини в Delphi – HWND (Handle WiNDow). Синонімом терміна “зсилка” є дексриптор. Зсилка на вікно може використовуватися не лише операційною системою, але й програмами для ідентифікації вікна, з якими необхідно проводити маніпуляції.
Приклад:
. . . . . . .
var
H: HWND; //зсилка на вікно
begin
H:= FindWindow (’TForm1’, ’Form1’);//пошук вікна де TForm1 – тип
//Form1 – заголовок вікна, заданий у властивості Caption
if H <>0 then ShowMessage (’Є вікно Form1’)
else ShowMessage (’Нема вікна Form1’);
end;
Функція FindWindow вертає величину типу hWnd – змилку на знайдене вікно чи нуль, якщо вікно не знайдене. Аргументи функції – класс вікна та його заголовок. Якщо заголовок шуканого вікна неважливий, то другим аргументом потрібно задати NIL. Змилка на вікно
однозначно визначає вікно. Властивість Handle форми вікна і є ця зсилка, а тип THandle точно відповідає типу hWnd, так що змінну H можна описати як змінну типу THandle.
ФОРМАТ ПІКСЕЛЯ В OPENGL
Посилання на контекст пристрою містять характеристики пристрою і засобу відображення. Одержавши посилання на контекст пристрою, маємо простий або кольоровий олівець чи пензель з палітрою в мільйони відтінків. Сервер OpenGL, перш ніж приступати до роботи, також повинний визначитися, на якому устаткуванні йому доведеться працювати Це може бути персональний комп’ютер, а
може бути і потужна графічна станція. Перш ніж одержати контекст відтворення, сервер OpenGL повинний одержати детальні
характеристики використовуваного устаткування. Ці характеристики зберігаються в спеціальній структурі, тип якої – TPixelFormatDescrіptor (опис формату піксела). Формат піксела визначає конфігурацію буфера кольору і допоміжних буферів.
Отже, зміст структури PіxelFormatDescrіptor – детальний опис графічної системи, на якій відбувається робота. Опис усіх полів структури TPіxelFormatDescrіptor робиться в процедурі SetDCPіxelFormat, яка викликається між одержанням посилання на контекст
пристрою і створенням посилання на контекст відтворення OpenGL. Полям структури присвоюється бажані значення, потім викликом функції СhoosePіxelFormat здійснюється запит системі, чи підтримується на даному робочому місці обраний формат піксела, і, нарешті,
викликом функції SetPіxelFormat установлюється формат піксела в контексті пристрою. Функція СhoosePіxelFormat повертає індекс формату пиксела, що нам потрібний як аргумент функції SetPіxelFormat.
Заповнивши поля структури TPіxelFormatDescrіptor, ми визначаємося зі своїми побажаннями до графічної системи, на якій буде відбуватися робота програми, OpenGL підбирає найбільш придатний до наших побажань формат і установлює вже його як формат
піксела для наступної роботи. Наші побажання коректуються сервером OpenGL стосовно до реальних характеристик системи.
ІНДИВІДУАЛЬНЕ ЗАВДАННЯ
1. Написати програму із застосуванням 2D графічних функцій бібліотеки OpenGL, яка дозволяє візуалізувати у незалежних віконних формам програми ескізне креслення антикварного фотоапарату (див. рис).
Текст програми
unit MainUnit;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Menus,StdCtrls, OpenGL;
type
TMainForm = class(TForm)
MainMenu1: TMainMenu;
N1: TMenuItem;
N2: TMenuItem;
N3: TMenuItem;
N4: TMenuItem;
N2DFront1: TMenuItem;
N5: TMenuItem;
procedure N4Click(Sender: TObject);
procedure N2DFront1Click(Sender: TObject);
procedure N5Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
MainForm: TMainForm;
implementation
uses FUnit;
{$R *.dfm}
procedure TMainForm.N4Click(Sender: TObject);
begin
Close;
end;
procedure TMainForm.N2DFront1Click(Sender: TObject);
var
FForm:TFForm;
begin
FForm:=TFForm.Create(nil );
FForm.BorderStyle:=bsSingle;
FForm.Width:=650;
FForm.Height:=650;
FForm.Show;
end;
procedure TMainForm.N5Click(Sender: TObject);
begin
MainForm.Cascade;
end;
end.
unit FUnit;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, OpenGL,StdCtrls;
type
TFForm = class(TForm)
procedure FormPaint(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
hrc1: HGLRC; // зсилка на контекст відтворення
public
{ Public declarations }
end;
var
FForm: TFForm;
implementation
uses MainUnit;
{$R *.dfm}
procedure TFForm.FormPaint(Sender: TObject);
var
i,j:glint;
begin
wglMakeCurrent(Canvas.Handle, hrc1); // встановлюється поточний контекст канви форми вiдтворення
glViewPort (0, 0, ClientWidth, ClientHeight);
// область виводу ширина, висота розміру форми Fform програми
glClearColor (0.95, 0.95, 0.95, 1.0); // колiр фону
glClear (GL_COLOR_BUFFER_BIT); // очищення буфера кольору
glColor3f (0.0, 0.0, 0.0);
glEnable(GL_LINE_SMOOTH);
glBEGIN (GL_POLYGON);
glVertex2f (-0.45, -0.7);
glVertex2f (0.8, -0.7);
glVertex2f (0.8, 0.6);
glVertex2f (-0.45, 0.6);
glEnd;
glBEGIN (GL_POLYGON);
glVertex2f (0.8, 0.6);
glVertex2f (-0.45, 0.6);
glVertex2f (-0.30, 0.7);
glVertex2f (0.95, 0.7);
glEnd;
glBEGIN (GL_POLYGON);
glVertex2f (0.8, -0.7);
glVertex2f (0.8, 0.6);
glVertex2f (0.95, 0.7);
glVertex2f (0.95, -0.6);
glEnd;
glColor3f (0.3, 0.3, 0.3);
glBEGIN (GL_LINES);
glVertex2f (0.8, -0.7);
glVertex2f (0.8, 0.6);
glVertex2f (0.8, 0.6);
glVertex2f (-0.45, 0.6);
glVertex2f (0.8, 0.6);
glVertex2f (0.95, 0.7);
glEnd;
glColor3f (0.0, 0.0, 0.9);
for i:=1 to 8 do
begin
glBEGIN (GL_POLYGON);
glVertex2f (-0.6-i*0.08+0.3, -0.6);
glVertex2f (0.6-i*0.16+0.3, -0.6);
glVertex2f (0.6-i*0.16+0.3, 0.6-i*0.08);
glVertex2f (-0.6-i*0.08+0.3, 0.6-i*0.08);
glEnd;
glColor3f (0.0, 0.0, 0.9-0.1*i);
end;
glColor3f (1.0, 0.0, 0.0);
glPointSize(50);
glEnable(GL_POINT_SMOOTH);
glBEGIN (GL_POINTS);
glVertex2f (-0.68, -0.32);
glEnd;
wglMakeCurrent (0, 0); // перед завершенням роботи необхiдно,
// щоб контекст нiкем не використовувався
end;
{Формат пікселя}
procedure SetDCPixelFormat (hdc : HDC);
var
pfd : TPixelFormatDescriptor; //данi формату пiкселiв
nPixelFormat : Integer;
begin
FillChar (pfd, SizeOf (pfd), 0);
nPixelFormat := ChoosePixelFormat (hdc, @pfd); // запит системi - чи підтримується вибраний формат пiкселiв
SetPixelFormat (hdc, nPixelFormat, @pfd); // встановлює формат пiкселiв у контекстi пристрою
end;
procedure TFForm.FormCreate(Sender: TObject);
begin
SetDCPixelFormat(Canvas.Handle);
hrc1 := wglCreateContext(Canvas.Handle); // створює контекст вiдтворення OpenGL
end;
procedure TFForm.FormDestroy(Sender: TObject);
begin
wglDeleteContext(hrc1); // видалення контексту вiдтворення
end;
procedure TFForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end;
end.
Результат роботи програми
Висновок: В даній лабораторній роботі ми ознайомилися та практично освоїли технології роботи з графічними можливостями бібліотеки OpenGL на площині в операційному середовищі Wіndows. Вивчили способи підключення бібліотеки OpenGL при розробці програмних проектів засобами візуального середовища програмування Borland Delphi. Ознайомилися та засвоїли основні графічні функцій та процедури, набули практичних навиків програмування графіки для Wіndows-програм на основі OpenGL.