Реферат: «Применение OpenGL»

Название: «Применение OpenGL»
Раздел: Остальные рефераты
Тип: реферат

ФЕДЕРАЛЬНОЕ АГЕНСТВО ПО ОБРАЗОВАНИЮ

Государственное образовательное учреждение высшего профессионального образования
«ТОМСКИЙ ПОЛИТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ»

Факультет автоматики и вычислительной техники


Компьютерная графика

РЕФЕРАТ

«Применение OpenGL»

РАЗРАБОТАЛ

Студент группы 8В21 _________ Я.Е. Негрей

(ПОДПИСЬ)

__.__.____

(ДАТА)

УТВЕРЖДАЮ

Ассистент _________ А.Е. Соколов

(ПОДПИСЬ)

__.__.____

(ДАТА)

Томск – 2005

Содержание

Содержание. 2

1 Введение. 3

2 Начало работы с OpenGL. 4

3 Об игре. 6

4 Вывод изображения. 8

5 Принципы анимации. 10

6 Хранение изображений. 11

Приложение 1. OpenGL в Интернете. 13

1 Введение

Для ускорения выполнения этапов 3D – конвейера в ускоритель трехмерной графики должен обладать определенным наборам функций, т.е. аппаратно, без участия центрального процессора, производить операции, необходимые для построения 3D – изображения. Специальный пакет служебных команд и программ для выполнения этих функций называют интерфейсом прикладного программирования (Application Program Interface – API).

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

В настоящее время существуют различные пакеты API функций. Такие как DirectX, OpenGL. А также существуют частные разработки пакетов API функций некоторых фирм ориентированные только на свои 3D – акселераторы и Chipset.

DirectX – разработка фирмы Microsoft. Это пакет разработан в первую очередь для игровых приложений, работающих под операционной системой Windows NT/9X и более поздних версиях. Данный пакет является закрытой разработкой.

В отличии DirectX, OpenGL – это открытая разработка. Данный пакет состоит из двух частей. Первая часть – это базовый набор функций. Каждый производитель 3D – акселераторов, выпускающих свою продукцию с поддержкой OpenGL, должен их реализовать. И второй Части – функций расширения, реализующих более сложных преобразования.

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

2 Начало работы с OpenGL

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

procedure TMainWindow.FormCreate(Sender: TObject);

begin

SaveDefaultMode(); // Сохранения текущих параметров экрана

SetFullscreenMode(1); // Установка нового режима работы экрана

SetDCPixelFormat(Canvas.Handle); // установка параметров отображения

hrc := wglCreateContext(Canvas.Handle); // создание контекста отображения

// для функций OpenGL

If hrc = 0 then begin

ShowMessage ('Ошибка получения контекста воспроизведения!');

close ;

end;

glClearColor(0.0,0.0,0.0,1.0); //

wglMakeCurrent(Canvas.Handle, hrc); // выбираем текущем нашу форму

end ;

procedure TMainWindow.SetDCPixelFormat(DC : HDC);

var

nPixelFormat: Integer;

pfd: TPixelFormatDescriptor;

begin

FillChar(pfd, SizeOf(pfd), 0);

// устанавливаем параметры отображения пикселя

With pfd do begin

nSize := SizeOf(pfd);

nVersion := 1;

dwFlags := PFD_DRAW_TO_WINDOW or

PFD_SUPPORT_OPENGL or

PFD_DOUBLEBUFFER;

iPixelType:= PFD_TYPE_RGBA;

end;

nPixelFormat := ChoosePixelFormat(DC, @pfd);

SetPixelFormat(DC, nPixelFormat, @pfd);

end ;

Рассмотрим функции более подробнее:

С помощь функций SaveDefaultMode и SetFullscreenMode изменяют размер экрана используя функции ChangeDisplaySettings , но эта функция не из пакета OpenGL.

SetPixelFormat эта функция принудительна выставляет определенные настройки отображения пикселя и описывается эта функция следующим образом.

BOOL SetPixelFormat(HDC hdc,int iPixelFormat,CONST PIXELFORMATDESCRIPTOR * ppfd);

Здесь:

hdc – эта переменная отвечает за то к какому устройству применить установки.

iPixelFormat – номер формата пикселя, этот номер получают используя функцию ChoosePixelFormat

ppfd – это логической описания пикселя. PIXELFORMATDESCRIPTOR это специальная структура, описывающая все атрибуты выводимых пикселей. В виде основных элементов этой структуры можно выделить следующие:

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

· iPixelType – описывает как будет хранится информации о пикселе в буфере. Можно установить различные значения, например PFD_TYPE_RGBA или PFD_TYPE_COLORINDEX.

· cColorBits – устанавливает размер памяти отводимый под один пиксель в буфере

Как видно из кода программы мы установили двойную буферизацию, поддержку OpenGl и вывод на экан. Также установив формат хранения информации о пикселе в RGBA (Red Green Blue Alpha, где Alpha отвечает за прозрачность)

Далее необходимо создать контекст устройства отображения для OpenGL, это необходимо из-за того что OpenGL только со своим контекст и не может использовать контекст вывода Windows HDC. Данная операция осуществляется функцией wglCreateContext. В нашем случае мы создаем контекст на холст нашей формы. Но мало просто создать контекст его еще необходимо сделать текущим. Это используется для того, чтобы, создав несколько контекстов вывода, мы могли бы точно и быстро определить на какое устройство пойдет дальнейший вывод. Выбор контекста отображения осуществляется с помощью функции wglMakeCurrent.

HGLRC wglCreateContext( HDC hdc );

BOOL wglMakeCurrent( HDC hdc , HGLRC hglrc);

Для отмены выделения контекста отображения используется таже функция wglMakeCurrent, но с подачей констант NULL. А для удаления контекста отображения OpenGL необходимо использовать спезыальную функцию wglDeleteContext.

BOOL wglDeleteContext( HGLRC hglrc );

3 Об игре

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

Хотя на OpenGL трехмерные и двухмерные построения осуществляются с разной сложностью, но и возможности тоже различны, поэтому нужно рассмотреть плюсы и минусы более подробно.

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

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

Так как это наш первый проект того плана, поэтому мы остановимся на варианте двухмерной графики.

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

if ( (X >= 0) and ((Y+LibImages[N].Heigth )<= ScreenHeight)) then begin

gX:=X/(HalfScreenWidth)-1;

gY:=1-(Y+LibImages[N].Heigth)/HalfScreenHeight;

glRasterPos2f(gX, gY);

glPixelStorei(GL_UNPACK_ALIGNMENT, 0);

glDrawPixels(LibImages[N].Width,LibImages[N].Heigth,

GL_RGBA, GL_UNSIGNED_BYTE , LibImages[N].Pixels);

End

В нем нас интересуют только тру функции glRasterPos, glPixelStore и glDrawPixels. Рассмотрим их по порядку и поподробней.

Функция glRasterPos описывается следующим образом:

void glRasterPos[X][T](…);

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

Функция glPixelStore определяет как хранится пиксели которые мы будит выводить на экран. Она работает следующим образом.

void glPixelStore[f,i](GLenum pname, [GLfloat | GLint] param);

Выбираем один элемент из списка GLenum для этой функции и устанавливаем его в значение поданной в param разные элементы требуют подачу как целочисленных так и вещественных чисел поэтому данная функция имеет двк формы вызова.

Функция glDrawPixels выводит растровое изображения на экран.

void glDrawPixels(GLsizei width,GLsizei height,

GLenum format,GLenum type, const GLvoid *pixels);

Как мы можем видеть данная функция требует указать размеры выводимого изображения ( width и height), указать формат хранимых пикселей в нашем случае это RGBA. Далее идет указание типа переменных хранимых в массиве pixels . Здесь нет никакой ошибки именно массиве, а не матрицы. Все точки изображения записаны в массив подряд и зависимости от типа хранимых данных и от формата пикселя можно определить как происходит перевод адресации в матрицы к адресации в линейном массиве. Для режима GL_UNSIGNED_BYTE и формата GL_RGBA, адрес A[i][j] можно расписать так A[(i*width + j)*4], здесь происходит умножение на 4 т.к. при данном формате под каждую цветовую составляющую одного пикселя отводится по байту.

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

4 Вывод изображения

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

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

В Delphi для реализации собственного обработчика необходимо написать всего лишь следующую строку:

procedure TMainWindow.WMPaint(var Msg: TWMPaint);

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

procedure TMainWindow.WMPaint(var Msg: TWMPaint);

var

ps : TPaintStruct;

begin

BeginPaint(Canvas.Handle, ps);

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

glClear(GL_COLOR_BUFFER_BIT);

if (isGame=False) then begin

end

else begin

if ( not isStoped ) then begin

end

end;

SwapBuffers(Canvas.Handle);

EndPaint(Canvas.Handle, ps);

end;

5 Принципы анимации

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

Конечно, нам нужен таймер, но какой? Для простаты можно воспользоваться стандартным компонентом. Но я предлагаю воспользоваться системным таймером основанном на функциях API.

Для хранения информации для идентификации таймера нам понадобится переменная целого типа.

var

TimerId : uint;

Идентифицировать таймер необходимо потому, что у приложения их может быть несколько. Для включения таймера вызывается функция API SetTimer, где задается требуемый интервал таймера, а также указывается тип таймера, будет ли работать как таймер или одноразовая задержка.

UINT SetTimer(HWND hWnd, UINT nIDEvent,UINT uElapse, TIMERPROC lpTimerFunc);

Функция должна обрабатывать сообщение WM_Timer.

Как всегда в Windows, созданные объекты должны по окончании работы удаляться, дабы не поглощали ресурсы. Для удаления таймера вызываем Функцию KillTimer .

BOOL KillTimer(HWND hWnd, UINT uIDEvent );

6 Хранение изображений

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

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

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

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

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

В нашей игре реализован этот формат файла со следующее реализацией. На Рисунке 1 представлена общий вид файла и пример реализации метода сжатия изображения RLE.

Рисунок 1. структурная изображение файла (а). Пиксель без повторения (б.). Пиксель с повторением (в.).

В схеме указаны следующие блоки .

1. Размер изображения по вертикали.

2. Размер изображения по горизонтали.

3. Размер палитры.

4. Палитра. Под каждый цвет отводится по четыре биты и описываются форматом RGBA.

5. Данные

В данном формате применяется следующие ограничения. Максимальный размер палитры 128. Каждый пиксель в области данных описывается одним или тремя байтами. Сначала читается первый байт первые семь бит указывают на номер в палитре. Восьмой бит указывает на повторение. 0 – повторять бит не надо читаем следующий пиксель, 1 – необходимо прочитать следующие два байта и повторит этот пиксель это количество раз.

Формат прост, но достаточно эффективен так как смог упаковать 12 Мб в 700Кб. Самый распространенный форматом с использованием индексации и сжатием без потери качества стал формат GIF.

Приложение 1. OpenGL в Интернете.

  • http://www.opengl.org
    С этого сайта необходимо начинать знакомство с библиотекой OpenGL.
  • http://www.torry.ru/samples/saniples/primscr.zip
    Пример использования OpenGL в Delphi.
  • http://www.torry.ru/vcl/mmedia/ogl.zip Редактор на основе компонента TOpenGL. Автор - Enzo Piombo:
  • http://www.geocities.com/SiliconValley/Hills/6131
  • http://www.torry.ru/vcl/mmedia/ogld lO.zip Заголовочные файлы gl.pas и glu.pas. Автор - Alexander Staubo: http ://home .powertech. no/alex/
  • www.lischke-online.de
    Сайт Mike Lischke, содержит Opener, программу просмотра (viewer) 3DS-файлов, а также пакет GLScene.
  • http://www.delphi-jedi.org/DelphiGraphics/OpenGL/OpenGL.zip
    Альтернативный заголовочный файл opengl.pas. Автор - Mike Lischke. 336
  • www.gamedeveloper.org/delphi3d
    Сайт Tom Nuydens, содержит пакет CgLib и массу примеров и документации на его основе. Здесь можно получить заголовочный файл для использования библиотеки GLUT.
  • http://www.scitechsoft.com
    Библиотека программирования графики SciTech MGL.
  • http://wwwl.math.luc.edu/~jlayous/opengl/index.html http://www.p-m.org/delphi/ http://users.cybercity.dk/~bbl6194/delphi3dx.htm
  • http://www.geocities.com/SiliconValley^Vay/2132/
    Личные Web-страницы разработчиков, использующих OpenGL в проектах Delphi.
  • http://www.signsoft.com/downloadcenter/index.html Набор компонентов VisIt.
  • http://gl.satel.ru/
    Сайт "OpenGL в России".
    Ссылки на сайты и российские конференции.
  • http://www.sgl.com/software/opengl
    Курсы программирования для OpenGL.
    На этом сайте вы можете получить альтернативную версию OpenGL. П http://propro.ru/go/gallery.html
    Страница Геннадия Обухова, предоставившего модели для примеров этой книги.
  • http://delphi.vitpc.com
    Великолепный сайт "Королевство Delphi", на котором, в частности, находится и мой раздел с дополнительными примерами по использованию OpenGL.