У меня есть некоторый код для загрузки текстур, где я использую DevIL для загрузки изображений, а затем OpenGL создает текстуру из пикселей. Этот код работает нормально, и текстура отображается правильно, и это все хорошо.
Кроме того, я также могу создать массив из программы для непосредственного создания текстуры или внесения изменений в пиксели текстуры. Моя проблема здесь: при обработке пикселей их формат кажется ABGR, а не RGBA, как мне бы хотелось.
Я наткнулся на этот ТАК вопрос это относится к формату, который передается в функцию glTexImage2D:
(…) Если у вас есть GL_RGBA и GL_UNSIGNED_INT_8_8_8_8, это означает, что пиксели хранятся в 32-битных целых числах, а цвета в таком целом числе находятся в логическом порядке RGBA, например, красный находится в старшем байте, а альфа — в младшем байте. Но если машина работает с прямым порядком байтов (как с процессорами Intel), из этого следует, что фактический порядок в памяти — ABGR. Принимая во внимание, что GL_RGBA с GL_UNSIGNED_BYTE будет хранить байты в порядке RGBA независимо от того, является ли компьютер прямым или старшим. (…)
Действительно у меня есть процессор Intel. Изображения загружаются просто отлично, как сейчас, и я на самом деле использую режим GL_RGBA и тип GL_UNSIGNED_BYTE.
GLuint makeTexture( const GLuint* pixels, GLuint width, GLuint height ) {
GLuint texture = 0;
glGenTextures( 1, &texture );
glBindTexture( GL_TEXTURE_2D, texture );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glBindTexture( GL_TEXTURE_2D, NULL );
GLenum error = glGetError();
if ( error != GL_NO_ERROR ) {
return 0;
}
return texture;
}
Эта функция используется в моих двух методах загрузки текстур: метод, который загружает изображение из файла, и метод, который создает текстуру из массива.
Допустим, я хочу создать массив пикселей и создать текстуру,
GLuint pixels[ 128 * 128 ];
for ( int i = 0; i < 128 * 128; ++i ) {
pixels[ i ] = 0x800000FF;
}
texture.loadImageArray( pixels, 128, 128 );
Подбирая пиксели этим значением, я ожидаю увидеть слегка темно-красный цвет.
red = 0x80, green = 0x00, blue = 0x00, alpha = 0xFF
Но вместо этого я получаю прозрачный красный,
alpha = 0x80, blue = 0x00, green = 0x00, red = 0xFF
Вместо того чтобы использовать необработанные целые числа без знака, я создал структуру, которая поможет мне обрабатывать отдельные каналы:
struct Color4C {
unsigned char alpha;
unsigned char blue;
unsigned char green;
unsigned char red;
...
};
Я могу легко заменить массив беззнаковых целых на массив Color4C, и результат будет таким же. Если я инвертирую порядок каналов (красный сначала, альфа последний), то я могу легко передать 0xRRGGBBAA и заставить его работать.
Простое решение — просто обрабатывать эти значения в формате ABGR. Но мне также легче работать со значениями RGBA. Если я хочу использовать жестко закодированные значения цвета, я бы предпочел записывать их как 0xRRGGBBAA, а не 0xAABBGGRR.
Но допустим, я начал использовать формат ABGR. Если бы я запускал свой код на другой машине, вдруг я увидел бы странные цвета, где бы я ни менял пиксели / каналы напрямую?
Есть ли лучшее решение?
Задача ещё не решена.