Opengl что это в видеокарте
Знакомство с OpenGL нужно начать с того, что OpenGL — это спецификация. Т.е. OpenGL лишь определяет набор обязательных возможностей. Реализация же зависит от конкретной платформы.
OpenGL является кроссплатформенным, независимым от языка программирования API для работы с графикой. OpenGL — низкоуровневый API, поэтому для работы с ним неплохо иметь некоторое представление о графике в целом и знать основы линейной алгебры.
Структура API OpenGL
API OpenGL описан на языке C без применения C++ ради простоты и платформонезависимости. Он состоит только из функций, констант и примитивных типов, объявленных через typedef , таких как "typedef int GLenum;" .
Функции делятся на две группы:
- команды (англ. commands) для изменения состояния драйвера
- запросы (англ. queries) состояния драйвера
Вот несколько примеров:
- функция-команда void glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) устанавливает цвет очистки; RGBA компоненты цвета передаются как число с плавающей точкой на отрезке [0..1] .
- функция-команда void glClear() очищает буфер кадра путём заливки пикселей цветом очистки.
- функция-запрос const GLubyte *glGetString(GLenum name) возвращает строковое значение некоторой константы или величины в видеодрайвере, выбор величины зависит от параметра name ; при этом const GLubyte* можно преобразовать в const char* с помощью reinterpret_cast .
- тип данных GLclampf означает “число с плавающей точкой на отрезке [0..1] ”; при этом никаких проверок принадлежности диапазону компилятор делать не будет, потому что тип объявлен просто как typedef float GLclampf .
Функции-команды ничего не возвращают, даже статуса своего выполнения. Это даёт возможность выполнить команду асинхронно, не заставляя приложение ждать, пока видеодрайвер отправит данные на видеокарту и получит от неё ответ.
Расширения
Отличной возможностью OpenGL является поддержка расширений. В то время, когда производители видеокарт представляют новую технологию или новую обширную оптимизацию для отрисовки, в драйверах появляется расширение, относящееся к этому событию. Если аппаратное обеспечение, на котором запущено приложение, поддерживает расширение, значит разработчик может использовать функционал, предоставляемый этим расширением для более продвинутой, или эффективной отрисовки графики. Таким образом графический программист может использовать новые технологии без ожидания их реализация в новых версиях OpenGL, просто проверив поддержку технологии видеокартой. Зачастую, если какое-то расширение пользуется большим спросом, его реализуют как часть следующей версии OpenGL.
Разработчику надо лишь проверить доступность расширения (или использовать библиотеку расширения). Такой подход позволяет программисту выполнять действия более эффективно, основываясь на имеющихся у него расширениях:
C OpenGL 3.3 нам редко будут нужны расширения, но когда будут нужны, необходимые инструкции будут предоставлены.
Именования
Объекты
Библиотеки OpenGL написаны на C и имеют множественные ответвления, но в основном это C библиотека. Поскольку большинство конструкций из языка C не транслируется в высокоуровневые языки OpenGL был разработан с использованием большого количества абстракций. Одной из таких абстракций является система объектов в OpenGL.
Объект в OpenGL — это набор опций, которые представляют подмножество состояний OpenGL. К примеру мы можем создать объект, описывающий конфигурацию отрисовки окна; мы можем задать размер, количество цветов и так далее. Такой объект можно представить C-подобной структурой:
Примитивные типы
Заметьте, что при использовании OpenGL рекомендуется использовать примитивы, заданные OpenGL. Вместо использования float записывать его с приставной GL. Тоже самое для int, uint char, bool и так далее. OpenGL определяет разметку памяти для его GL примитивов для обеспечения кроссплатформенности, поскольку некоторые операционные системы могут иметь иную разметку. Использования OpenGL примитивов позволяет добиться полной кроссплатформенности вашего приложения.
Каждый раз, когда мы хотим использовать объекты в основном мы запишем это как-то так:
Этот небольшой участок кода — то, что вы будете часто встречать во время работы с OpenGL. В начале мы создаем объект и сохраняем ссылку на него в виде идентификационного номера (id). (Реальные данные объекта спрятаны в реализации). Затем мы привязываем объект к требуемой части контекста (Расположение целевого объекта окна из примера задано, как `GL_WINDOW_TARGET`). Затем мы устанавливаем значения опций окна и, в конце концов, отвязываем объект, установив id в 0. Значения, установленные нами продолжают храниться в объекте, доступ к которому мы можем получить через objectId и восстановить их снова привязав объект к GL_WINDOW_TARGET.
Данный код лишь показывает пример того, как работает OpenGL. В последствии будут представлены реальные примеры.
Основная фишка этих объектов состоит в том, что мы можем объявлять множество объектов в нашем приложении, задавать их опции и когда бы мы не запускали операции с использованием состояния OpenGL мы можем просто привязать объект с нашими предпочитаемыми настройками. К примеру этом могут быть объекты с данными 3D модели или нечто, что мы хотим на этой модели отрисовать. Владение несколькими объектами позволяет просто переключаться между ними в процессе отрисовки.
Первая программа
Теперь мы знаем основы работы с OpenGL. Можно написать простую программу для закрепления знаний.
Начнем с того, что нужно подключить заголовочный файл GLUT:
Теперь мы уже знаем, что писать в main. Зарегистрируем два обработчика: для рисования содержимого окна и обработки изменения его размеров. Эти два обработчика по сути используются в любой программе, использующей OpenGL и GLUT.
Теперь надо написать функцию-обработчик изменений размеров окна. Зададим область вывода изображения размером со все окно при помощи команды glViewport (х, у, ширина, высота). Затем загрузим матрицу проекции glMatrixMode (GL_PROJECTION), заменим ее единичной glLoadIdentity () и установим ортогональную проекцию. И наконец загрузим модельно-видовую матрицу glMatrixMode (GL_MODELVIEW) и заменим ее единичной.
В итоге получим:
- GL_COLOR_BUFFER_BIT — для очистки буфера цвета
- GL_DEPTH_BUFFER_BIT — для очистки буфера глубины
- GL_ACCUM_BUFFER_BIT — для очистки буфера накопления
- GL_STENCIL_BUFFER_BIT — для очистки трафаретного буфера
Все! Можно компилировать. Должно получиться что-то вроде этого:
Весь код целиком (для кто не осилил статью).
В принципе ничего сложного в этом нет, по крайней мере если вы уже сталкивались с графикой до этого.
Core-profile и Immediate mode (Мгновенный режим)
Раньше, использование OpenGL предполагало разработку в Immediate mode (также известен как фиксированный конвейер (fixed function pipeline)), которая была проста в использовании для рисования графики. Большинство функционала OpenGL было скрыто в библиотеках и у разработчиков не было свободы в понимании вычислений, производимых OpenGL.
Разработчики требовали большей гибкости в разработке и позже спецификация стала более гибкой, а разработчики получили больше контроля над процессом отрисовки их графики. Immediate mode был прост в использовании и понимании, но он был крайне неэффективным. По этой причине спецификация указала Immediate mode как устаревший, и начиная с версии 3.2 начала мотивировать программистов использовать Core-profile режим, который исключал весь устаревший функционал.
При использовании core-profile, OpenGL заставляет нас пользоваться современными практиками. Когда мы пытаемся использовать устаревшие функции, OpenGL выбрасывает ошибку и прекращает отрисовку. Преимущества использования современных практик — это гибкость и эффективность, но к сожалению бОльшая сложность в изучении. Immediate mode является бОльшей абстракцией и он скрывает большое количество реальной работы, выполняемой OpenGL и поэтому его было легко изучать, но трудно разобраться, как OpenGL на самом деле работает. Современный подход требует от разработчика полного понимания OpenGL и графического программирования в целом и хоть это немного сложнее, такая схема позволяет добиться большей гибкости, эффективности.
Это причина, почему наши уроки основаны на Core-Profile OpenGL версии 3.3.
Хоть он немного и сложнее, но это того стоит.
Сейчас уже вышли гораздо более новые версии OpenGL (на момент написания 4.5) и вы можете спросить: зачем мы должны изучать OpenGL 3.3, когда уже вышел 4.5? Ответ довольно прост. Все старшие версии OpenGL, начиная от версии 3.3 не добавляют различные полезные возможности без изменения основной механики. Новые версии просто предоставляют немного более эффективные или более удобные способы выполнения одних и тех же операций. В результате все концепты и техники, применимые к OpenGL 3.3 можно применить к новым версиям OpenGL.
Использование новейших версий OpenGL сопряжено с одной проблемой. Исполнять новейшие API смогут только современные видеокарты.
Альтернативы OpenGL
Хотя библиотека OpenGL и считается одной из лучших библиотек как для профессионального применения так и для игр, у неё существуют и конкуренты.
Одним из главных конкурентов считается Direct3D из пакета DirectX, разработанный фирмой Microsoft. Direct3D создавался исключительно для игровых приложений. Если сравнивать эти две библиотеки, то нельзя сказать, что одна из них лучше, а другая хуже, у каждой библиотеки имеются свои особенности. Например, если сравнивать их в плане переносимости программ с одной платформы на другую, то Direct3D будет работать только на Intel платформах под управлением операционной системы Windows, в то время программы, написанные с помощью OpenGL можно успешно перенести на такие платформы как Unix, Linux, SunOS, IRIX, Windows, MacOS и многие другие. А вот в плане объектно-ориентированного подхода OpenGL уступает Direct3D. OpenGL работает по принципу конечного автомата, переходя из одного состояния в другое, совершая при этом какие-то преобразования. Ещё одним преимуществом Direct3D является поддержка дешёвого оборудования, OpenGL же поддерживается не на всех графических картах, но для профессиональных ускорителей OpenGL является стандартом де-факто. И ещё, OpenGL легче чем Direct3D для изучения основ графики, OpenGL можно применять например для начального изучения трёхмерной графики.
GLide до недавнего времени тоже являлся довольно широко используемым стандартом для игровых приложений. Этот стандарт создала фирма 3Dfx и библиотека GLide создавалась исключительно для видео ускорителей фирмы 3Dfx Voodoo и была оптимизирована исключительно под них. GLide является более низкоуровневым по отношению к OpenGL и по своим командам похож на него. GLide мало чем отличается от OpenGL по своим возможностям, за исключением некоторых функций, которые специально предназначались для Voodoo ускорителей. Но к сожалению 3Dfx отказалась от этого стандарта, передав его в руки разработчиков открытого программного обеспечения.
Есть ещё несколько библиотек, среди них можно отметить Heidi. Heidi это библиотека или даже лучше сказать драйвер для визуализации трёхмерных сцен, используемый только в 3D Studio Max и только под Windows NT.
Стоит также отметить совместную разработку двух гигантов - Microsoft и Silicon Graphics в области стандартизации компьютерной графики. Этот проект носит название Fahrenheit и сейчас находится в стадии разработки.
Давайте начнем
Теперь вы немного узнали про OpenGL как о спецификации, так и о библиотеке. Узнали примерный алгоритм работы и несколько особенностей, используемых OpenGL. Не расстраивайтесь, если что-то недопоняли, далее мы пошагово пройдемся по всем этапам и вы увидите достаточно примеров, чтобы разобраться во всех хитросплетениях OpenGL. Если вы уже готовы начать — то мы можем начать создавать OpenGL контекст и наше первое окно прямо тут.
Графика
- 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 ( GL_QUADS ) ;
- glColor3f ( 1.0 , 1.0 , 1.0 ) ;
- glVertex2i ( 250 , 450 ) ;
- glColor3f ( 0.0 , 0.0 , 1.0 ) ;
- glVertex2i ( 250 , 150 ) ;
- glColor3f ( 0.0 , 1.0 , 0.0 ) ;
- glVertex2i ( 550 , 150 ) ;
- glColor3f ( 1.0 , 0.0 , 0.0 ) ;
- glVertex2i ( 550 , 450 ) ;
- glEnd ( ) ;
Узнаём о расширениях через GLEW
Читать полный список расширений, полученный через glGetString(GL_EXTENSIONS) , не очень удобно. Сканировать его программно слишком трудоёмко в плане вычислений.
Для удобного получения расширений у GLEW есть переменные-флаги, которые устанавливаются при вызове glewInit() . Для проверки наличия расширения надо:
Теперь можно улучшить функцию PrintOpenGLInfo :
На машине с Ubuntu 14.04 и встроенной видеокартой Intel программа выводит следующее:
На машине с Windows 8 и видеокартой Intel вывод отличается:
Содержание
Создаём работоспособное приложение
Код запроса версии OpenGL разместим в классе CWindow , потому что в дальнейших примерах нам уже не нужно будет печатать что-либо в консоль.
Здравствуйте. Несколько недель назад я начинал серию переводов статей по изучению OpenGL. Но на 4 статье один хабровчанин заметил, что мои переводы могут нарушать лицензию, по которой распространяются учебные материалы, предоставленные в исходной статье. И действительно, мои переводы нарушали лицензию. Для разрешения этой проблемы я обратился к авторам того набора уроков, но так и не смог добиться нормального ответа. По этой причине я связался с автором другого, не менее (а возможно даже и более) крутого, набора уроков по OpenGL: Joey de Vries. И он дал полное разрешение на перевод его набора уроков. Его уроки гораздо более обширные, чем прошлый набор, поэтому эти переводы растянутся на долго. И я обещаю, будет интересно. Заинтересовавшихся прошу под кат.
Также я встал на распутье: либо я опишу все основы вроде создания окна и контекста в одной статье, чтобы не плодить статьи, но в таком случае такую огромную статью не всякий осилит; либо я также как и раньше буду переводить, опираясь на иерархию оригинала. Я решил выбрать второй вариант.
На счет уроков по Vulkan: к сожалению мне тяжело сейчас написать уроки по данному API по причине скудной видеокарты на данный момент, которая просто не поддерживает Vulkan API, поэтому уроки по данному API будут только после обновления видеокарты.
Функция печати информации о контексте
Следуя “правилу трёх ударов”, можно отрефакторить этот код:
Вступление
Прежде чем мы начнем наше путешествие нам стоило бы разобраться что такое OpenGL. В основном под OpenGL понимают API (Интерфейс Программирования Приложений), который предоставляет большой набор функций, которые мы можем использовать для управления графикой и изображениями. Но на самом деле OpenGL это скорее спецификация, разработанная и поддерживаемая Khronos Group.
Спецификация OpenGL описывает каким будет результат выполнения каждой конкретной функции и что она должна делать. А уже реализация этих спецификаций лежит на плечах разработчиков. И поскольку спецификация не описывает детали реализации, соответственно имеют право на существование различные реализации OpenGL, по крайней мере пока они соответствуют спецификациям.
Люди, разрабатывающие OpenGL библиотеки, зачастую, являются производителями видеокарт. Каждая видеокарта, которую вы покупаете, поддерживает конкретные версии OpenGL из набора библиотек, разработанных для данной серии видеокарт. При использовании Apple системы, OpenGL библиотеки поддерживаются Apple, под Linux существуют комбинации версий от поставщиков и пользовательских адаптаций этих библиотек. Это также означает, что если используемая вами версия OpenGL показывает странное поведение, значит, с большой вероятностью — это ошибка производителей видеокарт.
Так как большинство реализаций разрабатываются производителями видеокарт, для исправления багов требуется обновить драйвера видеокарты. Это одна из причин, почему почти все уроки рекомендуют обновлять драйвера на видеокарту.
Khronos выложила в публичный доступ все спецификации для всех версий OpenGL. Заинтересовавшийся читатель может найти спецификации OpenGL 3.3 (именно эту версию OpenGL мы будем использовать) здесь. Спецификации отлично показывают правила работы всех функций.
Основные возможности OpenGL.
- Геометрические и растровые примитивы. На основе геометрических и растровых примитивов строятся все объекты. Из геометрических примитивов библиотека предоставляет: точки, линии, полигоны. Из растровых: битовый массив(bitmap) и образ(image)
- Использование В-сплайнов. B-сплайны используются для рисования кривых по опорным точкам.
- Видовые и модельные преобразования. С помощью этих преобразований можно располагать обьекты в пространстве, вращать их, изменять форму, а также изменять положение камеры из которой ведётся наблюдение.
- Работа с цветом. OpenGL предоставляет программисту возможность работы с цветом в режиме RGBA (красный-зелёный-синий-альфа) или используя индексный режим, где цвет выбирается из палитры.
- Удаление невидимых линий и поверхностей. Z-буферизация.
- Двойная буферизация. OpenGL предоставляет как одинарную так и двойную буферизацию. Двойная буферизация используется для того, чтобы устранить мерцание при мультипликации, т.е. изображение каждого кадра сначала рисуется во втором(невидимом) буфере, а потом, когда кадр полностью нарисован, весь буфер отображается на экране.
- Наложение текстуры. Позволяет придавать объектам реалистичность. На объект, например шар, накладывается текстура(просто какое-то изображение), в результате чего наш объект теперь выглядит не просто как шар, а как разноцветный мячик.
- Сглаживание. Сглаживание позволяет скрыть ступенчатость, свойственную растровым дисплеям. Сглаживание изменяет интенсивность и цвет пикселей около линии, при этом линия смотрится на экране без всяких зигзагов.
- Освещение. Позволяет задавать источники света, их расположение, интенсивность, и т.д.
- Атмосферные эффекты. Например туман, дым. Всё это также позволяет придать объектам или сцене реалистичность, а также "почувствовать" глубину сцены.
- Прозрачность объектов.
- Использование списков изображений.
Получение информации о версии OpenGL
Один и тот же видеодрайвер может создать разные констексты с разными версиями OpenGL и разными наборами расширений. Поэтому получать версионную информацию следует уже после создания контекста.
- константа с именем GL_VERSION возвращает строку версии OpenGL, причём в начале строки обязательно стоит ". " , а остальная часть строки не определена. Например, строка "3.0 Mesa 10.3.2" обозрачает “OpenGL версии 3.0, реализуемый подсистемой графики Mesa версии 10.3.2”.
- константа с именем GL_VENDOR возвращает имя поставщика реализации OpenGL. Например, строка "Intel Open Source Technology Center" обозначает “Видеодрайвер предоставлен OpenSource-подразделением корпорации Intel”.
- константа с именем GL_EXTENSIONS содержит полный список расширений, разделённый пробелами. Список обычно насчитывает свыше ста расширений.
Дополнительные библиотеки OpenGL
Несмотря на то, что библиотека OpenGL (сокращённо GL) предоставляет практически все возможности для моделирования и воспроизведения трёхмерных сцен, некоторые из функций, которые требуются при работе с графикой, отсутствуют в стандартной библиотеке OpenGL.. Например, чтобы задать положение и направление камеры, с которой будет наблюдаться сцена, нужно самому рассчитывать модельную матрицу, а это далеко не все умеют. Поэтому для OpenGL существуют так называемые вспомогательные библиотеки.
Первая из этих библиотек называется GLU. Эта библиотека уже стала стандартом и поставляется вместе с главной библиотекой OpenGL. В состав этой библиотеки вошли более сложные функции, например для того чтобы определить цилиндр или диск потребуется всего одна команда. Также в библиотеку вошли функции для работы со сплайнами, реализованы дополнительные операции над матрицами и дополнительные виды проекций.
Следующая библиотека, также широко используемая - это GLUT. Это также независимая от платформы библиотека. Она реализует не только дополнительные функции OpenGL, но и предоставляет функции для работы с окнами, клавиатурой и мышкой. Для того чтобы работать с OpenGL в конкретной операционной системе (например Windows или X Windows), надо провести некоторую предварительную настройку и эта предварительная настройка зависит от конкретной операционной системы. С библиотекой GLUT всё намного упрощается, буквально несколькими командами можно определить окно, в котором будет работать OpenGL, определить прерывание от клавиатуры или мышки и всё это не будет зависеть от операционной системы. Библиотека предоставляет также некоторые функции, с помощью которых можно определять некоторые сложные фигуры, такие как конусы, тетраэдры, и даже можно с помощью одной команды определить чайник!
Есть ещё одна библиотека похожая на GLUT, называется она GLAUX. Это библиотека разработана фирмой Microsoft для операционной системы Windows. Она во многом схожа с библиотекой GLUT, но немного отстаёт от неё по своим возможностям. И ещё один недостаток заключается в том, что библиотека GLAUX предназначена только для Windows, в то время как GLUT поддерживает очень много операционных систем.
Существуют и другие дополнительные библиотеки для OpenGL. Все они добавляют что-то своё или ориентированы на какую-то платформу. Например существует такая библиотека как GLX - это расширение для X Windows, позволяющее использовать в X Windows OpenGL. GLX предоставляет не только локальный рендеринг, но и рендеринг по сети.
Заключение
Заканчивая вводный рассказ про OpenGL хочется подвести некоторые итоги. Итак OpenGL представляет собой единый стандарт для разработки трёхмерных приложений, сочетает в себе такие качества как мощь и в то же время простоту. Мультиплатформенность позволяет без труда переносить программное обеспечение с одной операционной системы в другую. OpenGL предоставляет вам в распоряжение всю мощь аппаратных возможностей, которые вы имеете на данном компьютере и при написании программ вам не нужно будет беспокоится о конкретных деталях используемого оборудования, за вас побеспокоится драйвер OpenGL. OpenGL прекрасно подходит как для профессионалов так и для новичков в области компьютерной графики.
В статье глубже описана структура API OpenGL, обработка ошибок, работа с расширениями и получение информации о возможностях драйвера.
Обработка ошибок
OpenGL старательно обрабатывает ошибки, такие как “недопустимый аргумент”, “неправильная константа enum”, “несвоевременный вызов команды”. Узнать о наличии общей ошибки в одной из предыдущих функций-команд можно функцией-запросом GLenum glGetError() .
- Если функция возвращает GL_NO_ERROR , ошибок не было
- В противном случае код ошибки обозначает категорию ошибки без конкретных указаний
- Функция не только возвращает код ошибки, но и очищает флаг ошибки в драйвере
Условно, код может выглядеть так:
Функцию можно улучшить, если учесть следующее:
- Распечатать строку ошибки можно в поток ошибок std::cerr
- Любую ошибку можно считать фатальной, вызывая std::abort для аварийного завершения программы после вывода текста ошибки
- Функцию можно сделать статическим методом класса CUtils
Представим улучшенную версию:
После добавления этого метода можно улучшить основной цикл приложения:
Библиотека GLEW
Запрашивать функции и проверять расширения вручную не всегда удобно. Для решения этой типовой задачи создана библиотека GLEW (сокращение от “openGL Extensions Wrapper”). С помощью макросов и отложенной загрузки адресов функций эта библиотека позволяет использовать расширения так, как будто бы никаких расширений не существует:
- вы просто вызываете функции по имени; если функции нет, произойдёт разыменование нулевого указания
- также вы можете использовать модифицированное имя расширения (с префиксом “GLEW_” вместо “GL_”) как целочисленную переменную со значением 0 или 1; 1 означает, что расширение есть и доступно, 0 означает, что расширения нет или оно недоступно
- если расширение недоступно, вы не должны вызывать функции расширения, чтобы не получить разыменование нулевого указателя
- если при создании контекста OpenGL вы потребовали и получили контекст не ниже определённой версии, то можно даже не проверять расширения, вошедшие в эту версию: они есть.
Подключать заголовок glew.h следует до первого включения gl.h , иначе вы получите ошибку при компиляции.
Библиотека GLEW требует явного вызова функции glewInit для своей инициализации. Сделать вызов следует только один раз. Чтобы не накладывать на класс CAbstractWindow лишних ограничений, нужно гарантировать, что при первом конструировании объекта CAbstractWindow функция будет вызвана, а при последующих — уже нет. Также надо установить глобальную переменную-флаг glewExperimental , чтобы GLEW оборачивала функции из версий OpenGL 3.x и 4.x.
Для этой цели можно использовать два подхода
- взять из стандартного заголовка функцию std::call_once
- завести в функции статическую переменную типа bool, которая будет устанавливаться в false в инициализаторе (который для статических переменных внутри функции вызывается ровно один раз)
В многопоточной среде было бы правильным использовать call_once, чтобы исключить возможность повторного вызова инициализации во время выполнения “glewInit” в другом потоке. Однако, ни контекст OpenGL, ни GLEW не могут использоваться из нескольких потоков одновременно. Поэтому call_once нам не потребуется, и достаточно статической переменной типа bool:
Расширения OpenGL
В целях максимальной гибкости, все изменения в OpenGL вносятся в виде расширений. Расширение OpenGL — это задокументированная спецификация, которая описывает новые функции и их поведение, изменения в поведении старых функций и новые константы. Каждое расширение имеет имя, например, "GL_ARB_multitexture" . При выпуске новой версии OpenGL часть расширений попадает в новую версию и становится частью ядра OpenGL. Таким образом, в версии OpenGL 3.0 и выше вы автоматически получаете ряд возможностей, которые в OpenGL 1.2 были доступны только как расширения.
- В UNIX-системах и на мобильных устройствах доступны достаточно свежие версии OpenGL (обычно 3.0 и выше), где многие важные расширения уже стали частью ядра стандарта.
- В Windows версии старше OpenGL 1.1 напрямую недоступны, но разработчики драйверов дают доступ к ним через механизм расширений. Если видеодрайвер не установлен, будет доступен только OpenGL 1.1, обладающий весьма ограниченными возможностями.
Функция, описанная в расширении, может не существовать в конкретной реализации OpenGL (если она не поддерживает данное расширение). Поэтому программист должен
- либо запросить адрес функции и использовать её, только если адрес ненулевой
- либо проверить наличие поддержки расширения по его имени и потом смело запрашивать адреса описанных в расширении функций
В стандарте OpenGL не описан способ получения адреса, и каждая операционная система или мультимедийная библиотека предоставляет свой способ. В SDL2 есть функция void *SDL_GL_GetProcAddress(const char *proc) , которая по имени OpenGL-функции возвращает её адрес или nullptr , если функция недоступна.
Именования
Основы программы на OpenGL
- 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 — включает стерео-изображение
- 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) — задает функцию, вызываемую по таймеру
Конечный автомат
OpenGL по своей сути — это большой конечный автомат: набор переменных, определяющий поведение OpenGL. Под состоянием OpenGL в основном имеется ввиду контекст OpenGL. В процессе использования OpenGL, мы часто изменяем состояния, устанавливая некоторых опции, управляем буферами, а затем отрисовываем, используя текущий контекст.
Когда мы говорим OpenGL, что мы хотим начать отрисовывать, к примеру, линии, вместо треугольников, то мы меняем состояние OpenGL, изменяя опцию, отвечающую за то как OpenGL должен рисовать. После изменения состояния OpenGL, на отрисовку линий, все последующие функции отрисовки будут отрисовывать линии вместо треугольников.
Во время работы с OpenGL мы будем проходить через несколько меняющих состояния функций, которые будут менять контекст, и через несколько меняющий состояния функций, выполняющие действия в зависимости от текущего состояния OpenGL. До тех пор, пока вы держите в голове тот факт, что OpenGL — это большой конечный автомат, большинство функционала будет вам понятна.
Что это за программа
И сразу же хочу уточнить, что это вовсе не программа в привычном понимании, не драйвер, не протокол и не служба.
OpenGL — спецификация, которой определяется программный интерфейс для написания приложений, использующих 2D и 3D графику. По сути, это инструмент, который регулирует рендеринг изображения видеокартой.
Название расшифровывается как Open Graphics Library, то есть «Открытая графическая библиотека». Открытость инструмента означает, что им может воспользоваться любой разработчик без всякой маржи и лицензионных отчислений.
Инструмент кроссплатформенный: созданные с его помощью приложения будут работать в любой среде, которые осуществляют его поддержку.
При этом работать будут одинаково все в зависимости от мощности рабочей станции. Такая реализация освобождает разработчика от необходимости писать код под каждую конкретную платформу, что позволяет полностью сосредоточиться на графической составляющей.
Основные области применения OpenGL — видеоигры, системы автоматизированного проектирования, поддержка виртуальной реальности и визуализация различных проектов. На платформе Windows главным конкурентом технологии является DirectX.
О том, что такое DirectX и зачем он нужен, вы можете почитать вот тут.
Концепция OpenGL была разработана в 1982 году в университете Стэнфорда. Аппаратно прототип технологии впервые реализовала компания Silicon Graphics, создавшая конвейер для рендеринга. Ее разработки стали основой библиотек OpenGL.
Как работает OpenGL
Если смотреть с точки зрения разработчика, то OpenGL — программный интерфейс, который управляет работой видеокарты. Всего есть чуть более 150 команд, с помощью которых программист определяет, какие именно объекты будут отправлены на рендеринг.Этим же стандартом определяются более тонкие настройки: например, тройная буферизация, трассировка лучей или сглаживание в играх.
Нет необходимости создавать разные версии графических объектов для отображения в различных режимах качества графики: все подстраивается «на автомате», исходя из заданных программистов параметров.
Проще говоря, программист определяет отображаемые объекты в трехмерном пространстве, их взаимное положение и взаимодействие, масштабирование, угол обзора и т.д., а также цвет и текстуру, а OpenGL уже заботится об их рендеринге.
Можно утверждать, что этот инструмент только воспроизводит объекты, но не взаимодействует с устройствами ввода — мышью, клавиатурой, геймпадом или игровым рулем. За это, а также за работу менеджера окон, отвечают уже другие компоненты.
Несмотря на кажущуюся сложность, OpenGL имеет четко продуманную структуру и простой процедурный интерфейс. При этом с помощью этого инструмента можно создавать действительно сложные сцены, состоящие из множества компонентов. Вычислительных мощностей требуется меньше по сравнению с другими библиотеками.
Некоторые версии OpenGL поддерживают работу по сети: объекты рендерятся на сервере, а клиентское приложение получает только их отображение. Благодаря этому можно создавать мощные воспроизводящие комплексы, состоящие из множества компьютеров.
Следует отметить, что в отличие от главного конкурента OpenGL можно считать универсальным инструментом. Главный конкурент, DirectX, «заточен» именно под игры. Многие игры поддерживают обе технологии.
Нужно ли переключаться между ними? На мой взгляд, нет никакой разницы, что именно вы используете, Независимо от технологии существенной разницы в производительности не замечено, если речь идет о платформе Windows.
Если же вы используете эмулятор Андроид на ПК, в этом случае рекомендую переключиться OpenGL: для систем семейства Unix этот инструмент подходит больше.
Также рекомендую ознакомиться с публикациями «Что делать, если видеокарта не поддерживает DirectX» и «Как посмотреть параметры видеокарты». Буду признателен, если вы расшарите этот пост в социальных сетях. До скорой встречи!
Сейчас трёхмерные изображения можно увидеть везде, начиная от компьютерных игр и заканчивая системами моделлирования в реальном времени. Раньше, когда трёхмерная графика существовала только на суперкомпьютерах, не существовало единого стандарта в области графики. Все программы писались с "нуля" или с использованием накопленного опыта, но в каждой программе реализовывались свои методы для отображения графической информации. С приходом мощных процессоров и графических ускорителей трёхмерная графика стала реальностью для персональных компьютеров. Но в тоже время производители программного обеспечения столкнулись с серьёзной проблемой - это отсутствие каких-либо стандартов, которые позволяли писать программы, независимые от оборудования и операционной системы. Одним из первых таких стандартов, существующий и по сей день является OpenGL.
OpenGL - это графический стандарт в области компьютерной графики. На данный момент он является одним из самых популярных графических стандартов во всём мире. Ещё в 1982 г. в Стенфордском университете была разработана концепция графической машины, на основе которой фирма Silicon Graphics в своей рабочей станции Silicon IRIS реализовала конвейер рендеринга. Таким образом была разработана графическая библиотека IRIS GL. На основе библиотеки IRIS GL, в 1992 году был разработан и утверждён графический стандарт OpenGL. Разработчики OpenGL - это крупнейшие фирмы разработчики как оборудования так и программного обеспечения: Silicon Graphics, Inc., Microsoft, IBM Corporation, Sun Microsystems, Inc., Digital Equipment Corporation (DEC), Evans & Sutherland, Hewlett-Packard Corporation, Intel Corporation и Intergraph Corporation.
OpenGL переводится как Открытая Графическая Библиотека (Open Graphics Library), это означает, что OpenGL - это открытый и мобильный стандарт. Программы, написанные с помощью OpenGL можно переносить практически на любые платформы, получая при этом одинаковый результат, будь это графическая станция или суперкомпьютер. OpenGL освобождает программиста от написания программ для конкретного оборудования. Если устройство поддерживает какую-то функцию, то эта функция выполняется аппаратно, если нет, то библиотека выполняет её программно.
Что же представляет из себя OpenGL? С точки зрения программиста OpenGL - это программный интерфейс для графических устройств, таких как графические ускорители. Он включает в себя около 150 различных команд, с помощью которых программист может определять различные объекты и производить рендеринг. Говоря более простым языком, вы определяете объекты, задаёте их местоположение в трёхмерном пространстве, определяете другие параметры (поворот, масштаб, . ), задаёте свойства объектов (цвет, текстура, материал, . ), положение наблюдателя, а библиотека OpenGL позаботится о том чтобы отобразить всё это на экране. Поэтому можно сказать, что библиотека OpenGL является только воспроизводящей (Rendering), и занимается только отображением 3Д обьектов, она не работает с устройствами ввода (клавиатуры, мыши). Также она не поддерживает менеджер окон.
OpenGL имеет хорошо продуманную внутреннюю структуру и довольно простой процедурный интерфейс. Несмотря на это с помощью OpenGL можно создавать сложные и мощные программные комплексы, затрачивая при этом минимальное время по сравнению с другими графическими библиотеками.
В некоторых библиотеках OpenGL (например под X Windows) имеется возможность изображать результат не только на локальной машине, но также и по сети. Приложение, которое вырабатывает команды OpenGL называется клиентом, а приложение, которое получает эти команды и отображает результат - сервером. Таким образом можно строить очень мощные воспроизводящие комплексы на основе нескольких рабочих станций или серверов, соединённых сетью.
Читайте также: