OpenGL имеет четыре основные версии, не считая версий для мобильных устройств и встраиваемых систем (OpenGL | ES) и Интернета через JavaScript (WebGL). Так же, как Direct3D 11 работает по-другому, чем Direct3D 8, так и OpenGL 3 отличается от OpenGL 1. Большим отличием является то, что версии OpenGL в основном являются дополнениями к старым версиям (но не целиком).
Помимо различных выпусков и версий OpenGL, основной OpenGL также добавил концепцию профилей. А именно Профиль совместимости (который обеспечивает поддержку API из более старых версий) и Основной профиль (который отключает эти старые API). Такие вещи glBegin
просто не работают, когда вы используете профиль Core, но будут работать, когда вы используете профиль совместимости (который используется по умолчанию).
Еще одним серьезным осложнением является то, что некоторые реализации OpenGL (как, например, Apple) будут включать новые функции OpenGL только при использовании Core Profile. Это означает, что вы должны прекратить использование старых API, чтобы использовать более новые API.
Затем вы получите несколько очень запутанных сценариев для уроков:
- Учебник старый и использует только устаревшие API.
- Учебное пособие является новым и хорошо написанным и использует только Core-совместимые API.
- Учебное пособие является новым, но допускает ошибку, предполагая, что вы работаете с драйвером, который включает все API в режиме совместимости и свободно смешивает как новые, так и старые API.
- Учебное пособие предназначено для другой редакции OpenGL, такой как OpenGL | ES, которая вообще не поддерживает ни один из старых API, ни в какой версии.
Подобные вещи glBegin
являются частью того, что иногда называют API непосредственного режима. Это также очень запутанно, потому что в OpenGL не существует такого понятия, как режим сохранения, а в «немедленном режиме» уже есть другое определение в графике. Гораздо лучше называть их API-интерфейсами OpenGL 1.x, поскольку они устарели с OpenGL 2.1.
OpenGL 1.x API немедленно отправит вершины графическому конвейеру в старые времена. Это работало хорошо, когда скорость аппаратного обеспечения, которое отображало вершины, была примерно на уровне скорости процессора, генерирующего данные вершин. Тогда OpenGL просто разгрузил растеризацию треугольника и больше ничего.
В наши дни графический процессор может прожирать огромное количество вершин на очень высоких скоростях, в то же время выполняя расширенное преобразование вершин и пикселей, а процессор просто не может даже удаленно идти в ногу. Кроме того, интерфейс между процессором и графическим процессором был разработан с учетом этой разницы в скорости, что означает, что невозможно даже передавать вершины в графический процессор по одному за раз.
Все драйверы GL должны эмулировать glBegin
, внутренне выделяя буфер вершин, помещая вершины, отправленные с, glVertex
в этот буфер, а затем отправляя весь этот буфер в одном вызове отрисовки при glEnd
вызове. Затраты на эти функции намного больше, чем если бы вы только что обновили буфер вершин самостоятельно, поэтому в некоторой документации (очень ошибочно!) Ссылки на буферы вершин называются «оптимизацией» (это не оптимизация; это единственный способ на самом деле поговорить с ГПУ).
Существуют различные другие API, которые устарели или устарели в OpenGL на протяжении многих лет. Так называемый конвейер с фиксированной функцией является еще одним таким элементом. Некоторая документация может все еще использовать этот конвейер или смешиваться с программируемым конвейером. Конвейер с фиксированными функциями появился в былые времена, когда графические карты жестко кодировали всю математику, используемую для рендеринга трехмерных сцен, а API OpenGL ограничивался настройкой некоторых значений конфигурации для этой математики. В наши дни аппаратное обеспечение имеет очень мало жестко запрограммированной математики и (так же, как ваш процессор) вместо этого запускает пользовательские программы (часто называемые шейдерами).
Еще раз, драйверы должны эмулировать старый API, поскольку функции с фиксированными функциями просто отсутствуют на аппаратном обеспечении. Это означает, что в драйвер встроено несколько совместимых шейдеров, которые выполняют старую математику из дней с фиксированными функциями, которые используются, когда вы не поставляете свои собственные шейдеры. Старые функции OpenGL, которые изменяют это старое состояние с фиксированными функциями (например, старый API освещения OpenGL), фактически используют современные функции OpenGL, такие как унифицированные буферы, для передачи этих значений в шейдеры совместимости драйвера.
Драйверы, поддерживающие совместимость, должны выполнять большую часть закулисной работы, чтобы выяснить, когда вы используете эти устаревшие функции, и убедиться, что вы можете плавно сочетать их с современными функциями, что увеличивает издержки и значительно усложняет драйвер. Это одна из причин того, что некоторые драйверы заставляют вас активировать Core Profile для получения новых функций; это значительно упрощает внутреннюю структуру их драйверов, поскольку не требует одновременной поддержки старого и нового API.
Во многих документах может быть рекомендовано начинать со старых API просто потому, что с ними проще начать работу. Direct3D решил эту проблему для новичков, предложив сопутствующую библиотеку ( DirectX Tool Kit ), которая предоставляет более простые API рисования и предварительно написанные шейдеры, которые можно свободно смешивать с использованием Direct3D 11 по мере роста вашего опыта. Более широкое сообщество OpenGL в основном придерживалось профиля совместимости для начинающих, к сожалению, это проблематично, поскольку опять-таки существуют системы, которые не позволяют смешивать старые API OpenGL с более новыми. На новом OpenGL есть неофициальные библиотеки и инструменты для более простого рендеринга с различными уровнями функций и целевыми вариантами использования и языками ( MonoGame для пользователей .NET, например), но ничего официально не одобрено или не согласовано.
Документация, которую вы находите, может даже не относиться к OpenGL, но может относиться к одному из других подобных API. OpenGL | ES 1.x имел рендеринг с фиксированной функцией, но не имел API OpenGL 1.x для представления вершин. OpenGL | ES 2.x + и WebGL 1+ вообще не имеют функций с фиксированными функциями, и для этих API нет режимов обратной совместимости.
Эти API выглядят очень похоже на основной OpenGL; они не совсем совместимы, но существуют официальные расширения для OpenGL, которые поддерживаются некоторыми (не всеми) драйверами, чтобы стать совместимыми с OpenGL | ES (на котором основан WebGL). Потому что вещи не были достаточно запутанными раньше.