Как мне поддерживать разные версии OpenGL? - PullRequest
10 голосов
/ 21 июня 2011

У меня есть две разные системы: одна с OpenGL 1.4 и одна с 3. В моей программе используются шейдеры, которые являются частью OpenGL 3 и поддерживаются только как расширение ARB в реализации 1.4.

Поскольку я не могу использовать функции OpenGL 3 с OpenGL 1.4, есть ли способ поддерживать обе версии OpenGL без написания одного и того же кода OpenGL дважды (ARB / EXT и v3)?

Ответы [ 3 ]

10 голосов
/ 21 июня 2011

Если вам действительно не нужна поддержка 10-летних видеокарт по какой-то причине, я настоятельно рекомендую использовать OpenGL 2.0 вместо 1.4 (на самом деле, я бы даже пошел до версии 2.1).

Поскольку использование «шейдеров с ядром в 3.0» обязательно означает, что видеокарта должна быть способной, по крайней мере, к какой-либо версии GLSL, это исключает любое оборудование, которое не способно обеспечить, по крайней мере, OpenGL 2,0. Это означает, что если кто-то с OpenGL 1.4 и может запускать ваши шейдеры, он использует драйверы 8-10 лет. От этого мало что можно извлечь (кроме кошмара поддержки).

Целенаправленное использование OpenGL 2.1 является разумным, в настоящее время практически нет систем, которые не поддерживают это (даже если предположить, что минимум OpenGL 3.2 может быть вполне разумным выбором).

Рыночная цена на карту начального уровня, совместимую с OpenGL 3.3, примерно в 1000 раз превышающую вычислительную мощность карты высокого класса OpenGL 1.4, составляла около 25 долларов два года назад. Если вы когда-нибудь намереваетесь продать свое приложение, вы должны спросить себя, будет ли тот, кто не может себе позволить (или не хочет позволить себе), быть тем, кого вы разумно ожидаете заплатить за ваше программное обеспечение.

Сказав, что одновременная поддержка OpenGL 2.x и OpenGL> 3.1 - это кошмар, потому что в языке затенения есть нетривиальные изменения, выходящие далеко за пределы #define in varying и регулярно кусающие вас.

Поэтому я лично выбрал 1017 *, чтобы никогда больше не нацеливаться на что-либо ниже версии 3.2 с массивами экземпляров и шейдерными объектами. Это работает со всем аппаратным обеспечением, которое можно разумно ожидать, имея вычислительную мощность для запуска современного приложения, и включает в себя пользователей, которые были слишком ленивы, чтобы обновить свой драйвер до 3.3, предоставляя те же функции в одном пути кода. Функции OpenGL 4.x загружаются как расширение, если доступно, и это хорошо.
Но, конечно, каждый должен сам решить, какой ботинок подходит лучше всего.

Достаточно моего бла-бла, вернемся к актуальному вопросу:
Чтобы не дублировать код для расширений / ядра, во многих случаях вы можете использовать одинаковые имена, указатели функций и константы. Тем не менее, будьте осторожны: Как общее утверждение, это незаконно, неопределенно и опасно.
На практике большинство (не все!) Расширений идентичны соответствующим основным функциям и работают точно так же. Но как узнать, какие из них вы можете использовать, а какие съедят вашу кошку? Посмотрите на gl.spec - функция с записью alias идентична и неотличима от своего псевдонима. Вы можете безопасно использовать их взаимозаменяемо.
Расширения, которые являются проблематичными, часто также содержат пояснительный комментарий (например, "Это не псевдоним PrimitiveRestartIndexNV, поскольку он устанавливает сервер вместо состояния клиента." ), но не полагайтесь на них, полагайтесь в поле alias.

5 голосов
/ 21 июня 2011

Как уже сказал @Nicol Bolas, создание двух путей кода для ядра OpenGL-3 и OpenGL-2 неизбежно. Ядро OpenGL-3 сознательно ломает совместимость. Однако ставки не так плохи, как может показаться, потому что большую часть времени код будет отличаться только нюансами, и оба пути кода могут быть записаны в одном исходном файле с использованием методов условной компиляции.

Например

#ifdef OPENGL3_CORE
    glVertexAttribPointer(Attribute::Index[Position], 3, GL_FLOAT, GL_FALSE, attribute.position.stride(), attribute.position.data());
    glVertexAttribPointer(Attribute::Index[Normal], 3, GL_FLOAT, GL_FALSE, attribute.position.stride(), attribute.position.data());

#else
    glVertexPointer(3, GL_FLOAT, attribute.position.stride(), attribute.position.data());
    glNormalPointer(GL_FLOAT, attribute.normal.stride(), attribute.normal.data());
#endif

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

#ifdef USE_CORE
#define gl_Position position
#else
#define in varying
#define out varying
#define inout varying

vec4f gl_Position;
#endif

Обычно в коде управления шейдерами вашей программы есть набор стандартных заголовков для построения окончательного исходного кода, передаваемого в OpenGL, разумеется, снова в зависимости от используемого кодового пути.

3 голосов
/ 21 июня 2011

Зависит от того, хотите ли вы использовать функциональность OpenGL 3.x?Не просто используйте API, но используйте реальные аппаратные функции, лежащие в основе этого API.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...