Назначение функции и организация графической библиотеки opengl. Графическая библиотеки OpenGl. Набор модулей для Windows

Новости 29.03.2019
Новости

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

Читатель, наверное, знает, что OpenGL это оптимизированная, высокопроизводительная графическая библиотека функций и типов данных для отображения двух-и трехмерной графики. Стандарт OpenGL был утвержден в 1992 г. Он основан на библиотеке IRIS GL, разработанной компанией Silicon Graphics (www.sgi.com). OpenGL поддерживают все платформы. Кроме того, OpenGL поддержана аппаратно. Существуют видеокарты с акселераторами и специализированные SD-карты, которые выполняют примитивы OpenGL на аппаратном уровне.

Материал первой части этого урока навеян очень хорошей книгой (доступной в online-варианте) издательства Addison-Wesley "OpenGL Programming Guide, The Official Guide to Learning OpenGL". Если читатель владеет английским языком, то мы рекомендуем ее прочесть.

Подключаемые библиотеки

Microsoft-реализация OpenGL включает полный набор команд OpenGL, то есть глобальных функций, входящих в ядро библиотеки OPENGL32.LIB и имеющих префикс gl (например, glLineWidth). Заметьте, что функции из ядра библиотеки имеют множество версий, что позволяет задать желаемый параметр или настройку любым удобным вам способом. Посмотрите справку по функциям из семейства glColor*. Оказывается, что задать текущий цвет можно 32 способами. Например, функция:

Void glColorSb(GLbyte red, GLbyte green, GLbyte blue);

Определяет цвет тремя компонентами типа GLbyte, а функция:

Void glColor4dv (const GLdouble *v);

Задает его с помощью адреса массива из четырех компонентов.

С учетом этих вариантов ядро библиотеки содержит более 300 команд. Кроме того, вы можете подключить библиотеку утилит GLU32.LIB, которые дополняют основное ядро. Здесь есть функции управления текстурами, преобразованием координат, генерацией сфер, цилиндров и дисков, сплайновых аппроксимаций кривых и поверхностей (NURBS - Non-Uniform Rational B-Spline ), а также обработки ошибок. Еще одна, дополнительная (auxiliary ) библиотека GLAUX.LIB позволяет простым способом создавать Windows-окна, изображать некоторые SD-объекты, обрабатывать события ввода и управлять фоновым процессом. К сожалению, эта библиотека не документирована. Компания Microsoft не рекомендует пользоваться ею для разработки коммерческих проектов, так как она содержит код цикла обработки сообщений, в который невозможно вставить обработку других произвольных сообщений.

Примечание
Тип GLbyte эквивалентен типу signed char, a GLdouble - типу double. Свои собственные типы используются в целях упрощения переносимости на другие платформы. Список типов OpenGL мы приведем ниже. Четвертый компонент цвета определяет прозрачность цвета, то есть способ смешивания цвета фона с цветом изображения. Некоторые команды OpenGL имеют в конце символ v, который указывает, что ее аргументом должен быть адрес массива (вектора). Вектор в математике - это последовательность чисел (координат), единственным образом задающих элемент векторного пространства. Многие команды имеют несколько версий, позволяя в конечном счете задать вектор разными способами
.

Около двадцати Windows GDI-функций создано специально для работы с OpenGL. Большая часть из них имеет префикс wgl (аббревиатура от Windows GL). Эти функции являются аналогами функций с префиксом glx, которые подключают OpenGL к платформе X window System. Наконец, существует несколько Win32-функций для управления форматом пикселов и двойной буферизацией. Они применимы только для специализированных окон OpenGL.

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

Так как в этих случаях область выбора определяется на проекции трехмерной сцены, то необходимо определить соответствующую ей область трехмерной сцены (сцена выбора). Сцена выбора будет зависеть от нескольких факторов: используемой проекции, размеров сцены и области вывода.

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

В библиотеке OpenTK функции библиотеки GLUT находятся в классе Glu в пространстве имен Tao .OpenGL (C#). В Object Pascal все функции и процедуры библиотеки GLUT имеют префикс "glu" , что позволяет их отличать от процедур и функций OpenGL .

Для формирования матрицы проекции на основе выбранного фрагмента проекции сцены можно использовать команду PickMatrix библиотеки GLUT :

C#: void gluPickMatrix(double x, double y, double width, double height, int viewport); Object Pascal: procedure gluPickMatrix(x,y,width,height: GLdouble; viewport: PGLint);

Команда PickMatrix библиотеки GLUT изменяет текущую матрицу таким образом, чтобы размер области сцены соответствовал области выбора, определённой в координатах проекции этой сцены. Команды имеет следующие параметры:

  • x, y – горизонтальная и вертикальная координаты области выбора в координатах окна, в котором отображается проекция трехмерной сцены.
  • width, height – ширина и высота выбранной прямоугольной области проекции трехмерной сцены в координатах окна.
  • viewport – массив четырех целочисленных элементов. В C# передается непосредственно массив в качестве параметра, в Object Pascal в качестве параметра передаётся указатель на массив. Массив определяет область вывода проекции трехмерной сцены. Значения массива должны соответствовать координатам области вывода, определённым с помощью команды ViewPort . Элементы этого массива должны иметь следующие значения: 1й и 2й элементы – координаты x и у левого верхнего угла выделенной области в координатах экрана, 3 и 4 элементы – ширина и высота этой области.

Команда должна быть выполнена перед выполнением команд Ortho или Frushtum , с помощью которых формируется матрица проекции.

Перевод библиотеки OpenGL в режим выбора

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

C#: int RenderMode(RenderingMode mode); Object Pascal: function glRenderMode(mode: GLenum): GLint;

Параметр mode определяет режим работы библиотеки OpenGL и может принимать одно из трех значений:

Таблица 10.1. Возможные значения параметра mode команды RenderMode
Описание Значение
Библиотека OpenTK, C# Object Pascal
Режим выбора, данное значение используется для перевода библиотеки в режим выбора. RenderingMode.Select GL_SELECT
Режим формирования изображения сцены. Этот режим используется по умолчанию после инициализации библиотеки OpenGL. Именно в этом режиме выполняется формирование изображения библиотекой OpenGL. RenderingMode.Render GL_RENDER
Режим обратной связи. RenderingMode.Feedback GL_FEEDBACK

После переключения в режим выбора библиотека OpenGL не формирует изображение до тех пор, пока режим не будет изменен на режим формирования изображения сцены с помощью команды RenderMode со значением параметра RenderingMode.Render на C# и GL_RENDER на Object Pascal.

Именование и формирование объектов сцены

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

Так как объекты, с которыми работает пользователь, обычно формируются из множества различных примитивов, то для определения выбранного объекта используется стек имен. Имена представляют собой целочисленные значения. Перед началом вывода очередного объекта в стек имен помещается имя (номер) этого объекта. Если при формировании объекта библиотека обнаруживает, что примитивы этого объекта попадают в область выбора, то содержание стека имен копируется в буфер выбора (вместе с некоторой дополнительной информацией), инициализированного с помощью команды SelectBuffer . При попадании в область сцены примитивов другого именованного объекта, содержание стека имен так же будет скопировано в буфер выбора. Таким образом, могут быть получены имена (номера) объектов, которые полностью или частично попали в область выбора. Необходимо учитывать, что для корректного определения выбранных объектов необходимо, чтобы координатные преобразования объектов, совпадали с теми, которые выполнялись при формировании изображения сцены.

Для работы со стеком имен используются несколько команд. Очистка стека имён выполняется с помощью команды InitNames :

C#: void InitNames(); Object Pascal: procedure glInitNames;

Помещение имени в стек выполняется с помощью команды PushName :

C#: void PushName(uint name); Object Pascal: procedure glPushName(name: GLuint);

Имя передается в качестве параметра команды.

Перед использованием стека имен он должен быть инициализирован с помощью команды InitNames . Затем в стек необходимо поместить один элемент с помощью команды PushName . Перед формированием каждого из объектов единственный элемент стека имен будет заменяться на имя формируемого объекта с помощью команды LoadName . Процедура заменяет последний элемент в стеке имен на заданный в качестве параметра. Таким образом, инициализация и использование стека имен схематически можно представить следующим образом:

InitNames; PushName(0); … LoadName(1); //формирование объекта № 1 LoadName(2); //формирование объекта № 2 LoadName(3); //формирование объекта № 3 //и т.д. Листинг 10.7. Схема использования стека имен для выбора объектов

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

Именования

Скажем пару слов об именовании функций в OpenGL. Во-первых имена всех функций, предоставляемых непосредственно OpenGL, начинаются с приставки gl . Во-вторых функции, задающие некоторый параметр, характеризующийся набором чисел (например координату или цвет), имеют суффикс вида [число параметров + тип параметров + представление параметров].
  • Число параметров - указывает число принимаемых параметров. Принимает следующие значения: 1 , 2 , 3 , 4
  • Тип параметров - указывает тип принимаемых параметров. Возможны следующие значения: b , s , i , f , d , ub , us , ui . Т.е. byte (char в C, 8-битное целое число), short (16-битное целое число), int (32-битное целое число), float (число с плавающей запятой), double (число с плавающей запятой двойной точности), unsigned byte, unsigned short, unsigned int (последние три - беззнаковые целые числа)
  • Представление параметров - указывает в каком виде передаются параметры, если каждое число по отдельности, то ничего не пишется, если же параметры передаются в виде массива, то к названию функции дописывается буква v
Пример: glVertex3iv задает координату вершины, состоящую из трех целых чисел, передаваемых в виде указателя на массив.

Графика

Все графические объекты в OpenGL представляют собой набор точек, линий и многоугольников. Существует 10 различных примитивов, при помощи которых строятся все объекты. Как двухмерные, так и трехмерные. Все примитивы в свою очередь задаются точками - вершинами.
  • GL_POINTS - каждая вершина задает точку
  • GL_LINES - каждая отдельная пара вершин задает линию
  • GL_LINE_STRIP - каждая пара вершин задает линию (т.е. конец предыдущей линии является началом следующей)
  • GL_LINE_LOOP - аналогично предыдущему за исключением того, что последняя вершина соединяется с первой и получается замкнутая фигура
  • GL_TRIANGLES - каждая отдельная тройка вершин задает треугольник
  • GL_TRIANGLE_STRIP - каждая следующая вершина задает треугольник вместе с двумя предыдущими (получается лента из треугольников)
  • GL_TRIANGLE_FAN - каждый треугольник задается первой вершиной и последующими парами (т.е. треугольники строятся вокруг первой вершины, образуя нечто похожее на диафрагму)
  • GL_QUADS - каждые четыре вершины образуют четырехугольник
  • GL_QUAD_STRIP - каждая следующая пара вершин образует четырехугольник вместе с парой предыдущих
  • GL_POLYGON - задает многоугольник с количеством углов равным количеству заданных вершин
Для задания примитива используется конструкция glBegin (тип_примитива)…glEnd () . Вершины задаются glVertex* . Вершины задаются против часовой стрелки. Координаты задаются от верхнего левого угла окна. Цвет вершины задается командой glColor* . Цвет задается в виде RGB или RGBA. Команда glColor* действует на все вершины, что идут после до тех пор, пока не встретится другая команда glColor* или же на все, если других команд glColor* нет.
Вот код рисующий квадрат с разноцветными вершинами:
  1. glBegin(GL_QUADS) ;
  2. glVertex2i(250 , 450 ) ;
  3. glVertex2i(250 , 150 ) ;
  4. glVertex2i(550 , 150 ) ;
  5. glVertex2i(550 , 450 ) ;
  6. glEnd() ;

Основы программы на OpenGL

Для платформонезависимой работы с окнами можно использовать библиотеку . GLUT упрощает работу с OpenGL.
Для инициализации GLUT в начале программы надо вызвать glutInit (&argc, argv) . Для задания режима дисплея вызывается glutInitDisplayMode (режим) , где режим может принимать следующие значения:
  • GLUT_RGBA - включает четырехкомпонентный цвет (используется по умолчанию)
  • GLUT_RGB - то же, что и GLUT_RGBA
  • GLUT_INDEX - включает индексированный цвет
  • GLUT_DOUBLE - включает двойной экранный буфер
  • GLUT_SINGLE - включает одиночный экранный буфер (по умолчанию)
  • GLUT_DEPTH - включает Z-буфер (буфер глубины)
  • GLUT_STENCIL - включает трафаретный буфер
  • GLUT_ACCUM - включает буфер накопления
  • GLUT_ALPHA - включает альфа-смешивание (прозрачность)
  • GLUT_MULTISAMPLE - включает мультисемплинг (сглаживание)
  • GLUT_STEREO - включает стерео-изображение
Для выбора нескольких режимов одновременно нужно использовать побитовое ИЛИ "|". Например: glutInitDisplayMode (GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH) включает двойную буферизацию, Z-буфер и четырехкомпонентный цвет. Размеры окна задаются glutInitWindowSize (ширина, высота) . Его позиция - glutInitWindowPosition (х, у) . Создается окно функцией glutCreateWindow (заголовок_окна) .
GLUT реализует событийно-управляемый механизм. Т.е. есть главный цикл, который запускается после инициализации, и в нем уже обрабатываются все объявленные события. Например нажатие клавиши на клавиатуре или движение курсора мыши и т.д. Зарегистрировать функции-обработчики событий можно при помощи следующих команд:
  • void glutDisplayFunc (void (*func) (void)) - задает функцию рисования изображения
  • void glutReshapeFunc (void (*func) (int width, int height)) - задает функцию обработки изменения размеров окна
  • void glutVisibilityFunc (void (*func)(int state)) - задает функцию обработки изменения состояния видимости окна
  • void glutKeyboardFunc (void (*func)(unsigned char key, int x, int y)) - задает функцию обработки нажатия клавиш клавиатуры (только тех, что генерируют ascii-символы)
  • void glutSpecialFunc (void (*func)(int key, int x, int y)) - задает функцию обработки нажатия клавиш клавиатуры (тех, что не генерируют ascii-символы)
  • void glutIdleFunc (void (*func) (void)) - задает функцию, вызываемую при отсутствии других событий
  • void glutMouseFunc (void (*func) (int button, int state, int x, int y)) - задает функцию, обрабатывающую команды мыши
  • void glutMotionFunc (void (*func)(int x, int y)) - задает функцию, обрабатывающую движение курсора мыши, когда зажата какая-либо кнопка мыши
  • void glutPassiveMotionFunc (void (*func)(int x, int y)) - задает функцию, обрабатывающую движение курсора мыши, когда не зажато ни одной кнопки мыши
  • void glutEntryFunc (void (*func)(int state)) - задает функцию, обрабатывающую движение курсора за пределы окна и его возвращение
  • void glutTimerFunc (unsigned int msecs, void (*func)(int value), value) - задает функцию, вызываемую по таймеру
Затем можно запускать главный цикл glutMainLoop () .

Первая программа

Теперь мы знаем основы работы с OpenGL. Можно написать простую программу для закрепления знаний.
Начнем с того, что нужно подключить заголовочный файл GLUT:

Теперь мы уже знаем, что писать в main. Зарегистрируем два обработчика: для рисования содержимого окна и обработки изменения его размеров. Эти два обработчика по сути используются в любой программе, использующей OpenGL и GLUT.
  1. int main (int argc, char * argv )
  2. glutInit(& argc, argv) ;
  3. glutInitDisplayMode(GLUT_DOUBLE| GLUT_RGBA) ; /*Включаем двойную буферизацию и четырехкомпонентный цвет*/
  4. glutInitWindowSize(800 , 600 ) ;
  5. glutCreateWindow(«OpenGL lesson 1» ) ;
  6. glutReshapeFunc(reshape) ;
  7. glutDisplayFunc(display) ;
  8. glutMainLoop() ;
  9. return 0 ;

Теперь надо написать функцию-обработчик изменений размеров окна. Зададим область вывода изображения размером со все окно при помощи команды glViewport (х, у, ширина, высота) . Затем загрузим матрицу проекции glMatrixMode (GL_PROJECTION) , заменим ее единичной glLoadIdentity () и установим ортогональную проекцию. И наконец загрузим модельно-видовую матрицу glMatrixMode (GL_MODELVIEW) и заменим ее единичной.
В итоге получим:
  1. void reshape(int w, int h)
  2. glViewport(0 , 0 , w, h) ;
  3. glMatrixMode(GL_PROJECTION) ;
  4. glLoadIdentity() ;
  5. gluOrtho2D(0 , w, 0 , h) ;
  6. glMatrixMode(GL_MODELVIEW) ;
  7. glLoadIdentity() ;

Осталось только написать функцию рисования содержимого окна. Рисовать будем тот квадрат, что я приводил выше в качестве примера. Добавить придется совсем немного кода. Во-первых перед рисованием надо очистить различные буфера при помощи glClear (режим) . Используется также как и glutInitDisplayMode. Возможные значения:
  • GL_COLOR_BUFFER_BIT - для очистки буфера цвета
  • GL_DEPTH_BUFFER_BIT - для очистки буфера глубины
  • GL_ACCUM_BUFFER_BIT - для очистки буфера накопления
  • GL_STENCIL_BUFFER_BIT - для очистки трафаретного буфера
В нашем случае нужно очистить только буфер цвета, т.к. другие мы не используем. Во-вторых после рисования нужно попросить OpenGL сменить экранные буфера при помощи glutSwapBuffers () , ведь у нас включена двойная буферизация. Все рисуется на скрытом от пользователя буфере и затем происходит смена буферов. Делается это для получения плавной анимации и для того, чтобы не было эффекта мерцания экрана.
Получаем:
  1. void display()
  2. glClear(GL_COLOR_BUFFER_BIT) ;
  3. glBegin(GL_QUADS) ;
  4. glColor3f(1.0 , 1.0 , 1.0 ) ;
  5. glVertex2i(250 , 450 ) ;
  6. glColor3f(0.0 , 0.0 , 1.0 ) ;
  7. glVertex2i(250 , 150 ) ;
  8. glColor3f(0.0 , 1.0 , 0.0 ) ;
  9. glVertex2i(550 , 150 ) ;
  10. glColor3f(1.0 , 0.0 , 0.0 ) ;
  11. glVertex2i(550 , 450 ) ;
  12. glEnd() ;
  13. glutSwapBuffers() ;

Итог

Все! Можно компилировать. Должно получиться что-то вроде этого:

Вы читаете мой первый урок по OpenGL!

Прежде чем начинать изучать сам OpenGL, мне кажется, лучше рассказать вам как компилировать код, запускать его и самое главное - как экспериментировать с исходными кодами, приведенными в этих уроках.

Что нужно знать

Данные уроки ориентируются на читателя без особых познаний в программировании. Конечно, знание какого-либо языка программирования(C, Java, Lisp, JavaSript) будет огромным плюсом, но это не обязательно, просто вам придется изучать два предмета одновременно – 3д графику и программирование.

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

Забудьте все, что знали про OpenGL 1/2

Данные уроки предполагают, что вы ничего не знаете про 3д графику. Но если вы читали уроки по OpenGL и встречали что-то наподобие glBegin(),то забудьте это. Тут мы будем изучать OpenGL 3 и 4, а то, что вы читали относиться к OpenGL 1 или 2. Поэтому рекомендую вам забыть все, что вы знали раньше, иначе ваши мозги начнут плавиться от нестыковок.

Сборка проекта

Код из данных уроков можно скомпилировать под Windows, Linux. Чтобы начать компилировать код под любую из платформ, нужно сделать следующее:

  1. Обновите драйвера на вашу видеокарту!! Я вас предупредил:)
  2. Скачайте компилятор, если у вас его еще нет.
  3. Установите CMake
  4. Скачайте готовые исходники уроков.
  5. Сгенерируйте проект с помощью CMake
  6. Соберите проект.
  7. Поэкспериментируйте с кодом для лучшего понимания, что там происходит.

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

Сборка под Windows


Сборка под Linux

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

  1. Установите последние драйвера на вашу видеокарту. Очень рекомендую не опенсорсные драйвера. Они не входят в состав GNU, но они часто работают гораздо лучше. Если ваша сборка линукса не предоставляет автоматического инсталлятора, попробуйте почитать Ubuntu"s guide.
  2. Поставьте компилятор со всеми необходимыми библиотеками и инструментами. Вот список того, что вам нужно: cmake make g++ libx11-dev libgl1-mesa-dev libglu1-mesa-dev libxrandr-dev libxext-dev. Используйте sudo apt-get install ***** или su /yum install ******
  3. Скачайте исходники примеров и разархивируйте их в папку, например, ~/Projects/OpenGLTutorials/
  4. Зайдите в папку ~/Projects /OpenGLTutorials / и введите следующие команды:
  • mkdir build
  • cd build
  • cmake ..
  1. Если предыдущие команды были выполнены успешно, то в папке build/ будет создан makefile
  2. введите «make all» и после этого будут скомпилированы все примеры и их зависимости. Если не будет никаких ошибок, то готовые исполняемые файлы будут помещены в папку ~/Projects/OpenGLTutorials/

Мне очень нравится использовать IDE QtCreator. Данная IDE умеет из коробки работать с CMake и предоставляет кучу других плюшек, таких как отладка автодополнение итд.

Инструкция по сборке проекта в QtCreator:

1. В QtCreator нажмите File->Tools->Options->Compile&Execute->CMake

2. Укажите путь к CMake. Скорее всего, это будет /usr/bin/cmake

3. File->Open Project ивыберите tutorials/CMakeLists.txt

4. Укажите build папку, папка желательно должна быть вне папки tutorials.

5. Опционально установите –DCMAKE_BUILD_TYPE=Debug в поле параметры.

6. Щелкните на молоток внизу. После этого примеры можно будет запустить из папки tutorials/

7. Чтобы запустить примеры из QtCreator выберите Projects ->Execution parameters ->Working Directory , и выберите каталог где лежат шэйдеры текстуры и модели. Для урока 2 это будет ~/opengl -tutorial /tutorial02_red_triangle/

Запуск примеров

После того, как проект будет скомпилирован, приложения можно будет запускать прямо из каталога.
Если нужно запускать примеры прямо из-под IDE, воспользуйтесь инструкцией приведенной выше, чтобы правильно установить рабочий каталог.

Как проходить эти уроки

Каждый урок идет вместе с исходным кодом и данными. Все эти файлы можно найти в соответствующем каталоге tutorialXX/.

Но я рекомендую вам не менять в этих файлах ничего, они лишь для справки. Лучше играйтесь в playground/playground.cpp и изменяйте там все что захотите. Если вы что-то сломали и не можете восстановить назад, то можно вернуть этот файл просто скопировав его из любого другого урока.

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

Открываем окно

Наконец-то! OpenGL!

Хотя, придется еще немного подождать. Во всех уроках 3д операции будут выполнятся на очень низком уровне, поэтому там не будет для вас никакой магии. Однако работа с окнами и сообщениями системы не интересная и скучная, поэтому мы позволим библиотеке GLFW сделать всю грязную работу за нас. Если вам конечно очень сильно хочется, вы можете использовать Win32 Api для Windows или X11 API для Linux, или использовать что-нибудь другое, типа SFML, FreeGLUT, SDL, … почитайте страничку ссылки.

Ладно, давайте уже начнем. Начнем с того, что нам нужно подключить зависимости. Так как нам необходимо выводить сообщения на консоль, мы напишем следующее:

// Подключаем стандартные заголовки

#include

#include

Потом подключаем GLEW

// Нужно не забывать, что GLEW обязательно необходимо подключать перед gl . h или glfw . h

#include

Потом подключаем GLFW. Эта библиотека будет делать всю магию управления окнами.

#include

На данном этапе нам не нужна эта библиотека, но она содержит математические функции и вскоре нам понадобится. Никакой магии в GLM нет, и если вам сильно хочется, вы можете использовать любую другую библиотеку по работе с матрицами и векторами. Мы подключаем «using namespace» для того, чтобы писать «vec3», а не «glm::vec3»

#include

using namespace glm;

Если вы скопируете эти куски кода в playground.cpp, то компилятор начнет возмущаться, что нет функции main(). Поэтому давайте добавим:

int main(){

Сначала лучше бы инициализировать GLFW:

// Инициализируем GLFW

if(!glfwInit())

{

fprintf(stderr, "Failed to initialize GLFW\n");

return -1;

}

А теперь создадим наше OpenGL окошко:

glfwOpenWindowHint ( GLFW _ FSAA _ SAMPLES , 4); // 4 x сглаживание

glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3); // нам нужен OpenGL 3.3

glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 3);

glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // нам не нужен старый OpenGL

// Откроем окно и создадим контекст

if(!glfwOpenWindow(1024, 768, 0,0,0,0, 32,0, GLFW_WINDOW))

{

fprintf(stderr, "Failed to open GLFW window\n");

ВВЕДЕНИЕ

OpenGL является одним из самых популярных прикладных программных интерфейсов (API - Application Programming Interface) для разработки приложений в области двумерной и трехмерной графики.

Стандарт OpenGL (Open Graphics Library - открытая графическая библиотека) был разработан и утвержден в 1992 году ведущими фирмами в области разработки программного обеспечения как эффективный аппаратно-независимый интерфейс, пригодный для реализации на различных платформах. Основой стандарта стала библиотека IRIS GL, разработанная фирмой Silicon Graphics Inc.

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

На сегодняшний день графическая система OpenGL поддерживается большинством производителей аппаратных и программных платформ. Эта система доступна тем, кто работает в среде Windows, пользователям компьютеров Apple. Свободно распространяемые коды системы Mesa (пакет API на базе OpenGL) можно компилировать в большинстве операционных систем, в том числе в Linux.

Характерными особенностями OpenGL, которые обеспечили распространение и развитие этого графического стандарта, являются:

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

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

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

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

ПРОГРАММИРОВАНИЕ С ИСПОЛЬЗОВАНИЕМ БИБЛИОТЕКИ OPENGL

Назначение и возможности библиотеки OpenGL

Для упрощения разработки программ на языке Си++ существует большое количество готовых библиотек с реализацией алгоритмов для конкретных предметных областей, от численных расчетов до распознавания речи. Библиотека OpenGL является одним из самых популярных программных интерфейсов (API) для работы с трехмерной графикой. Стандарт OpenGL был утвержден в 1992 г. ведущими фирмами в области разработки программного обеспечения. Его основой стала библиотека IRIS GL, разработанная фирмой Silicon Graphics на базе концепции графической машины Стэнфордского университета (1982 г.).

OpenGL переводится как Открытая Графическая Библиотека (Open Graphics Library). Программы, использующие OpenGL, гарантируют одинаковый визуальный результат во многих операционных системах - на персональных компьютерах, на рабочих станциях и на суперкомпьютерах.

С точки зрения программиста, OpenGL - это программный интерфейс для графических устройств (например, графических ускорителей). Он включает в себя около 150 различных функций, с помощью которых программист может задавать свойства различных трехмерных и двумерных объектов и выполнять их визуализацию (рендеринг). Т.е. в программе надо задать местоположение объектов в трехмерном пространстве, определить другие параметры (поворот, растяжение), задать свойства объектов (цвет, текстура, материал и т.д.), положение наблюдателя, а затем библиотека OpenGL выполнит генерацию двумерной проекции этой трехмерной сцены.

Можно сказать, что библиотека OpenGL является библиотекой только для визуализации трехмерных сцен (rendering library). Она не поддерживает какие либо периферийные устройства (например, клавиатуру или мышь) и не содержит средств для управления экранными окнами. Обеспечение взаимодействия периферийных устройств с библиотекой OpenGL в конкретной операционной системе является задачей программиста.

Основные возможности OpenGL, предоставляемые программисту, можно разделить на несколько групп:

1. Геометрические и растровые примитивы. На основе этих примитивов строятся все остальные объекты. Геометрические примитивы - это точки, отрезки и многоугольники. Растровыми примитивами являются битовые массивы и изображения.

2. Сплайны. Сплайны применяются для построения гладких кривых по опорным точкам.

3. Видовые и модельные преобразования. Эти преобразования позволяют задавать пространственное расположение объектов, изменять форму объектов и задавать положение камеры, для которой OpenGL строит результирующее проекционное изображение.

4. Работа с цветом. Для операций с цветом в OpenGL есть режим RGBA (красный - зелёный - синий - прозрачность) и индексный режим (цвет задается порядковым номером в палитре).

5. Удаление невидимых линий и поверхностей.

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

7. Наложение текстуры. Текстуры упрощают создание реалистичных сцен. Если на объект, например, сферу, наложить текстуру (некоторое изображение), то объект будет выглядеть иначе (например, сфера будет выглядеть как разноцветный мячик).

8. Сглаживание. Автоматическое сглаживание компенсирует ступенчатость, свойственную растровым дисплеям. При сглаживании отрезков OpenGL изменяет интенсивность и цвет пикселей так, что эти отрезки отображаются на экране без зигзагов".

9. Освещение. Указание расположения, интенсивности и цвета источников света.

10. Специальные эффекты. Например, туман, дым, прозрачность объектов. Эти средства позволяют сделать сцены более реалистичными.

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

Одна из этих библиотек называется GLU. Эта библиотека является частью стандарта и поставляется вместе с главной библиотекой OpenGL. В состав GLU входят более сложные функции (например, для создания цилиндра или диска требуется всего одна команда). В библиотеке GLU есть также функции для работы со сплайнами, реализованы дополнительные операции над матрицами и дополнительные виды проекций.

Еще две известные библиотеки - GLUT (для Unix) и GLAUX (для MS Windows). В них реализованы не только дополнительные функции OpenGL (для построения некоторых сложных фигур вроде конуса и тетраэдра), но также есть функции для работы с окнами, клавиатурой и мышью в консольных приложениях. Чтобы работать с OpenGL в конкретной операционной системе (например, Windows или Unix), надо провести некоторую предварительную настройку, которая зависит от операционной системы. GLUT и GLAUX позволяют буквально несколькими командами определить окно, в котором будет работать OpenGL, задать функции для обработки команд от клавиатуры или мыши.

Возможности OpenGL описаны через функции его библиотеки. Все функции можно разделить на пять категорий.

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

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

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

Функции визуализации позволяет задать положение наблюдателя в виртуальном пространстве, параметры объектива камеры. Зная эти параметры, система сможет не только правильно построить изображение, но и отсечь объекты, оказавшиеся вне поля зрения.

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

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



Рекомендуем почитать

Наверх