Содержание
Введение
Что такое OpenGL
Типы данных
Контекст рендеринга
Проблемы, зависимые от формата пикселя
Другие типы данных
Советы по использованию типов данных
Синтаксис команд
Заключение
Введение
Привет, в этом уроке я хотел бы познакомить вас поближе с OpenGL. Большая часть этого урока состоит из голой теории, но которая очень важна. Поэтому не стоит расстраиваться, если в конце этого урока вы не увидите демонстрацию какого-либо красивого графического объекта. Но, я вам обещаю, рисование начнется со следующих уроков.
Что такое OpenGL?
Чтобы ответить на этот вопрос, мы должны знать, что OpenGL — это аббревиатура (Open Graphics Library — открытая графическая библиотека). Слово Open означает «открытая». То есть, стандарт OpenGL, с появлением новых технологий, позволяет отдельным производителям добавлять в библиотеку функциональность через механизм расширений. Расширения распространяются с помощью двух составляющих: заголовочный файл, в котором находятся прототипы новых функций и констант, а также драйвер устройства, поставляемого разработчиком.
Слово Graphics — означает «графическая», то есть OpenGL предназначен для создания 2-ух и 3-ёх мерной графики. OpenGL владеет относительно маленьким набором команд, порядка 250 отдельных команд (около 200 в ядре OpenGL и около 50 в GLU), что позволяет их быстро изучить. Но в связи с этим в OpenGL нет функций для рисования комплексных объектов, таких как птица или автомобиль. Такие объекты строятся из небольшого набора, так называемых, примитив: точек (вершин), линий, треугольников и многоугольников.
Слово Library — означает «библиотека», то есть OpenGL это программный интерфейс приложения (Application Programming Interface — API). Таким образом, когда мы говорим «программа основана на OpenGL» или «приложение OpenGL», то мы подозреваем, что приложение написано на каком-то языке программирования (например, на Delphi) и это приложение вызывает функции OpenGL из одной или несколько библиотек OpenGL. Ядро OpenGL находится в библиотеке opengl32.dll, расположенной в системном каталоге Windows. Так же на большинстве платформ библиотека OpenGL сопровождается библиотекой GLU (OpenGL Utility Library — набор программ OpenGL), которая располагается в файле glu32.dll также в системном каталоге. Эта библиотека является набором служебных функций для моделирования кривых и поверхностей, а также имеет множество инструментов, таких как вычислители и NURBS.
Стоит также отметит, что OpenGL не зависит от платформы. Теоретически вы можете использовать OpenGL в любой операционной системе и запускать приложения с OpenGL на любой платформе. Однако это влечет за собой недостаток, определенные вещи, как управление окнами, клавиатурой или мыши, исключены из библиотеки. Об этих вещах мы должны позаботиться сами. К счастью, управление окнами и организацию пользовательского ввода можно реализовать с помощью Delphi.
Типы данных
Контекст рендеринга
Как мы уже знаем OpenGL не зависит от платформы и для обеспечения этой независимости, в ней определены собственные типы. Одним из самых важных типов, который используется в OpenGL это контекст рендерига (контекст визуализации), он обозначается как HGLRC. Контекст рендеринга содержит всю необходимую информацию, которая описывает область рисования и связанные с ней ресурсы. Эта информация содержит указания к использованию формата пикселей, размер области рисования (высота, ширина, пропорции), а также указания для буфера цвета, трафарета, буфера глубины и прозрачности. Кроме того, контекст рендеринга содержит общую информацию состояния, такую как тип и толщина изображаемых линий, используемые текстуры, а так же множество других указаний.
Описывающие процедуры создания контекста редеринга в этом разделе только под Windows. Под Linux детали отличаются и мы их изучим позже. Чтобы начать работать с OpenGL, необходимо в первую очередь указать контекст устройства (HDC), потому что, контекст рендеринга связывается с контекстом устройства. Так как, контексты рендеринга и устройства связаны, то они имеют одинаковый формат пикселей. Не смотря, что формат пикселей у этих контекстов одинаковый, контекст рендеринга и контекст устройство не одно и то же. Контекст устройства содержит информацию, относящуюся к GDI Windows. Контекст рендеринга содержит информацию, относящуюся к OpenGL. Таким образом, контекст рендеринга OpenGL является «портом», через который проходят все команды OpenGL, соединяя OpenGL с Windows. У каждого потока, который делает вызов команд OpenGL, должен быть текущий контекст рендеринга. Если приложение делает вызовы команд OpenGL из потока, у которого отсутствует контекст рендеринга, то ничего не происходит. Окно может иметь несколько контекстов рендеринга, но поток может иметь только один текущий (активный) контекст рендеринга, а контекст рендеринга может быть актуальным только к одному потоку. Вот пример создания контекста рендеринга с помощью dglOpenGL.pas
Var
DC : HDC;
RC : HGLRC;
TfrmMain.FormCreate procedure (Sender : TObject);
Begin
DC := GetDC(Handle) //получаем контекст устройства
RC := CreateRenderContext(DC, //контекст рендеринга
[opDoubleBuffered], /опции
32, //глубина цвета
24, //сколько битов зарезервировано для буфера глубины
0, //сколько битов зарезервировано для теста трафарета
0, //сколько бит сохраняется в буфере накопления
0, //сколько бит сохраняется во вспомогательном буфере
0); //определяет количество слоев
ActivateRenderingContext(DC,RC); //активация и связывание контекстов рендеринга и утсройства
End;
В процедуре CreateRenderContext, первый парметр указывает контекст устройства, с которым связывается контекст рендеринга. Например, контекст Формы или контекст Панели. В зависимости где позже будет отображаться графика OpenGL.
Второй параметр, указывает опции. Например: opDoubleBuffered указывает, что будет использоваться двойная буферезация.
Третий параметр указывает глубину цвета, в этом примере стоит 32. Это означает, что для 4 цветовых каналов (красного, зеленого, синего и альфа (прозрачность)) находятся в распоряжение 32/4=8 бит (1 байт). Следовательно, для каждого канала можно использовать 256 градаций. Таким образом, всего можно получить 256^4 = 4 294 967 296 цветов.
Четвертый параметр указывает, сколько бит резервируется для буфера глубины. Здесь 24 бит, это значит, что возможно от 0 до 2^24 = 16,7 млн. Чем выше значение, чем тоньше и точнее происходит тест глубины
Пятый параметр указывает количество бит для использования теста трафарета (маскирование частей экрана).
Шестой параметр указывает, сколько бит может быть сохранено в буфере накопления.
Седьмой показывает, сколько бит может быть сохранено во вспомогательном буфере.
Восьмой определяет количество слоев.
Проблемы, зависимые от формата пикселя
Известная проблема, связана с тем, что контекст рендеринга связан с контекстом устройства и формат пикселей устанавливается только один раз, поэтому вы должны знать заранее какие значения формата пикселя подходят для создаваемого контекста устройства. Чтобы избавится от этой проблемы, часто необходимо создать тестовый контекст устройства на спрятанном окне, на котором создается тестовый контекст рендеринга. Эта проблема часто возникает при мультисэмплинге (сглаживании), поскольку сглаживание требует соответствующего расширения или способности оборудования.
Другие типы данных
Все типы данных OpenGL начинаются с GL, после чего указывается соответствующий тип данных на C (byte, short,int…). Перед некоторыми имеется u, что указывает на тип данных без знака. В таблице приведены типы данных OpenGL и соответствующие типы данных на Delphi. Правда не у всех типов OpenGL есть соответствие для Delphi. Например, GLclampf — вещественное число в пределах от нуля до единицы, в Delphi он определен как Single. Поэтому в программах устанавливают «ручную» проверку на вхождение величины такого типа в требуемый диапазо Таблица 1. Типы данных OpenGL и соответствующие типы на Delphi.
Тип данных OpenGL |
Представление в памяти |
Соответствующий тип Delphi |
Суффикс в командах |
Диапазон |
GLbyte |
1 байт, со знаком, целое |
ShortInt |
b |
-128..127 |
GLshort |
2 байта, со знаком, целое |
SmallInt |
s |
-32768..32767 |
Glint, GLsizei |
4 байта, со знаком, целое |
Integer(LongInt) |
i |
-2147483648..2147483647 |
GLfloat, GLclampf |
4 байта, вещественное |
Single |
f |
1.7?10^-45..3.4?10^38 |
GLdouble, GLclampd |
8 байт, вещественное |
Double |
d |
5.0?10^-324..1.7?10^308 |
GLubyte |
1 байт, без знака, целое |
Byte |
ub |
0..255 |
GLushort |
2 байта, без знака, целое |
Word |
us |
0..65535 |
GLuint |
4 байта, без знака, целое |
Cardinal |
ui |
0..4294967295 |
GLboolean |
1 байт, логическое |
ByteBool |
ub |
False, True (GL_FALSE, GL_TRUE) |
GLenum |
4 байта, без знака, целое |
Cardinal |
ui |
0..4294967295 |
GLbitfield |
4 байта, без знака, целое |
Cardinal |
ui |
0..4294967295 |
Вещественные в основном используются для определения координат и построения объектов, целые для указания размеров. Переменные типа GLboolean используются для обозначения условий true (истина) или False (ложь). GLenum — для перечисляемых переменных. GLbitfield — для переменных, содержащих поля двоичных разрядов.
Помимо основных типов, стандартных для OpenGL и вводимых в любой среде программирования, введены специфические только для Delphi. Например, для наиболее часто употребляемых в OpenGL массивов введены специальные типы:
TGLVectorub2 = array[0..1] of TGLubyte; |
TGlMatrixub3 = array[0..2, 0..2] of TGLubyte; |
TGLVectorub3 = array[0..2] of TGLubyte; |
TGlMatrixub4 = array[0..3, 0..3] of TGLubyte; |
TGLVectorub3 = array[0..2] of TGLubyte; |
|
TGLVectorub4 = array[0..3] of TGLubyte; |
|
Также используются специальные типы для указателей , например:
PGLfloat = ^GLfloat
PGLvoid = Pointer;
PGLbyte = ^GLbyte
В OpenGL существует также великое множество констант они все начинаются с GL_ и всегда пишутся заглавными буквами, например, GL_POINTS. Мы их все изучим постепенно, по мере надобности.
Советы по использованию типов данных
Я вам рекомендую использовать именно типы библиотеки OpenGL, во-первых, программы будут работать быстрей, так как если вы будете использовать типы Delphi, то OpenGL все рвано будет переводить их в свои типы, во-вторых, легче будет переносить программный код на другую платформу.
Для указания координат использовать тип GLfloat, с ним OpenGL работает быстрее, нежели с другими.
Хотя в Delphi нет различия между верхним и нижним регистром, все же я рекомендую писать константы OpenGL в верхнем регистре, так как это повышает читабельность кода.
Синтаксис команд
Для большинства функций OpenGL используется правила именования, позволяющие сообщить, из какой библиотеки пришла функция, сколько она принимает аргументов, и какого типа. Все функции имеют корень, представляющий соответствующую функции команду OpenGL. Например, функция glColor3f имеет корень Color. Префикс gl представляет библиотеку OpenGL32.dll, а суффикс 3f означает, что функция принимает 3 аргумента типа GLFloat.
Все функции OpenGL имеют следующий формат:
<Префикс библиотеки><Основная команда><Необязательный счетчик аргументов ><Необязательный тип аргументов>
Элементы функции OpenGL иллюстрируются на рисунке:
Эта функция с суффиксом 3f принимает три аргумента с плавающей запятой. Другие разновидности этой функции принимает три целых числа (glColor3i), три числа двойной точности (glColor3d) и так далее. Таким образом, команды:
glVertex3i(1,3,5);
glVertex3f(1.0,3.0,5.0);
эквивалентны, за исключением того, что первая определяет координаты вершин как переменные целого типа, а вторая — как числа вещественного типа с одинарной точностью.
Некоторые команды OpenGL заканчиваются буквой v, которая показывает, что команда принимает указатель на вектор (или массив) значений, а не несколько различных аргументов. Для многих команд допускается задание аргументов и в виде векторов и виде набора аргументов, но для отдельных команд возможны только набор значений, либо только векторная форма.
Заключение
Вот и все на сегодня. Я рад, что вы нашли время прочитать этот урок и желаете изучать OpenGL. Я надеюсь, вы будете читать и последующие уроки, и что каждый узнал что-то новое, и я пишу не напрасно. Я пишу, наверное, не совсем понятно, ну уж простите меня за это. Если возникнуть вопросы вы можете написать мне на почту oryth84@gmail.com или написать мне в ICQ мой номер 590138.
(с) Олин Р.И. aka Oryth