Считаете ли вы хорошей идеей избегать абсолютной абстракции и писать ее непосредственно в OpenGL ES 2.0?
Ваши основные трудности с этим будут связаны с теми частями спецификации ES 2.0, которые на самом деле не совпадают с OpenGL 2.1.
Например, вы просто не сможете пропихнуть шейдеры ES 2.0 через десктопный компилятор GLSL 1.20. В ES 2.0 вы используете такие вещи, как указание точности; это недопустимые конструкции в GLSL 1.20.
Однако вы можете #define
обойти их, но для этого потребуется небольшое ручное вмешательство. Вам нужно будет вставить #ifdef
в исходный файл шейдера. Есть трюки с компиляцией шейдеров, которые вы можете сделать, чтобы сделать это немного проще.
Действительно, поскольку GL ES использует совершенно другой набор расширений (хотя некоторые из них являются зеркалами и подмножествами расширений GL для настольных компьютеров), вы можете захотеть сделать это.
Каждый шейдер GLSL (настольный или ES) должен иметь «преамбулу». Первой вещью без комментариев в шейдере должно быть объявление #version
. К счастью для вас, версия GL 2.1 для настольных ПК и GL ES 2.0 одинакова: #version 1.20
. Проблема в том, что будет дальше: список #extension
(если есть). Это включает расширения, необходимые шейдеру.
Поскольку GL ES использует расширения, отличные от настольных GL, вам потребуется изменить этот список расширений. А поскольку велика вероятность, что вам потребуется больше расширений GLSL ES, чем расширений GL 2.1 для настольных компьютеров, эти списки будут не просто сопоставлением 1:1, а совершенно другими списками.
Я предлагаю использовать возможность задавать шейдерам GLSL несколько строк. То есть в ваших реальных файлах шейдеров нет каких-либо преамбул. Они только имеют фактические определения и функции. Основная часть шейдера.
При работе на GL ES у вас есть глобальная преамбула, которую вы прикрепите к началу шейдера. У вас будет другая глобальная преамбула в настольной GL. Код будет выглядеть так:
GLuint shader = glCreateShader(/*shader type*/);
const char *shaderList[2];
shaderList[0] = GetGlobalPreambleString(); //Gets preamble for the right platform
shaderList[1] = LoadShaderFile(); //Get the actual shader file
glShaderSource(shader, 2, shaderList, NULL);
Преамбула может также включать #define
для конкретной платформы. Определяется пользователем, конечно. Таким образом, вы можете #ifdef
кодировать для разных платформ.
Есть и другие различия между ними. Например, хотя действительные вызовы функций загрузки текстур ES 2.0 будут нормально работать в настольной версии GL 2.1, они не обязательно будут оптимальными. Вещи, которые будут нормально загружаться на машинах с обратным порядком байтов, таких как все мобильные системы, потребуют некоторой настройки драйвера на настольных машинах с прямым порядком байтов. Таким образом, вы можете захотеть указать разные параметры передачи пикселей в GL ES и настольной GL.
Кроме того, в ES 2.0 и настольной версии GL 2.1 есть разные наборы расширений, которыми вы захотите воспользоваться. Хотя многие из них пытаются зеркально отразить друг друга (OES_framebuffer_object является подмножеством EXT_framebuffer_object), вы можете столкнуться с похожими проблемами «не совсем подмножества», подобными упомянутым выше.
person
Nicol Bolas
schedule
19.01.2012