Ваш вопрос, кажется, сбивает с толку определенные концепции, поэтому давайте рассмотрим все с самого начала. Это определение функции glTexImage2D
:
void glTexImage2D( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, void *data );
Есть две вещи, которые вы можете назвать «форматы текстур». Первый internalformat
параметр. Это реальный формат изображения, поскольку OpenGL хранит его. format
Параметр описывает часть формата пиксельных данных вы обеспечиваете с data
параметром.
Другими словами, format
и type
определите, как будут выглядеть ваши данные. internalformat
это то, как вы говорите OpenGL для хранения ваших данных. Давайте назовем format
и type
«формат передачи пикселей», пока internalformat
будет «формат изображения».
Формат изображения текстуры никогда не может быть "bgr8". Нет перечислителя формата изображения GL_BGR8. Там есть GL_BGR перечисление, но это для формата передачи пикселей, а не формат изображения.
Или, другими словами, ваши данные пикселей, которые вы предоставляете OpenGL, могут храниться в порядке BGR. Но реализация OpenGL сама решает, как на самом деле хранить эти данные пикселей. Возможно это хранит это в порядке с прямым порядком байтов. Может быть, он хранит это в порядке байтов. Может быть, это просто произвольно переставляет байты. Вы не знаете, и OpenGL не предоставляет способ выяснить это.
Невозможно определить, соответствует ли конкретный набор параметров формата передачи пикселей, как реализация OpenGL будет хранить их с учетом формата изображения.
Есть способ сказать сейчас. И под «сейчас» я имею в виду OpenGL 4.3 и / или ARB_internalformat_query2. Подходим к видеокарте рядом с вами:
GLenum format, type;
glGetInternalformativ(texture_target, GL_RGBA8, GL_TEXTURE_IMAGE_FORMAT, 1, &format);
glGetInternalformativ(texture_target, GL_RGBA8, GL_TEXTURE_IMAGE_TYPE, 1, &type);
format
и type
теперь есть предпочтительная реализация format
и type
для использования glTex(Sub)Image
вызовов к GL_RGBA8
изображениям. Есть отдельные format
и type
запросы на glReadPixels
скачивание.
Есть и другие вопросы, которые вы можете задать .
Если у вас нет доступа к ним, вы можете использовать некоторые общие правила, которых придерживается большинство аппаратных средств:
- будет хранить данные пикселей для данных 8 бит на канал в порядке BGRA. Поэтому, если вы хотите сопоставить формат с вашими пиксельными данными, чтобы быстрее загружать данные текстуры, вы хотите использовать
GL_BGRA
для format
, и GL_UNSIGNED_INT_8888
или GL_UNSIGNED_BYTE
для type
.
- фактически не будет хранить 24-битные цвета как 24-битные. Он всегда будет дополнять их до 32 бит; альфа будет просто игнорироваться при чтении данных. Так что если вы хотите , чтобы соответствовать форматам, всегда использовать
GL_BGRA
format
с GL_RGB8
форматами изображений, даже если вы должны поместить фиктивные данные в альфа - компоненте.
Как правило, большинство аппаратных средств не поддерживает 3-компонентные форматы текстур, поэтому в этом конкретном примере вы можете сделать достаточно безопасное предположение о том, что он преобразован. Трехкомпонентная текстура OpenGL на самом деле является четырехкомпонентной в аппаратном обеспечении, но альфа-компонент игнорируется / устанавливается на 255 / что угодно.
https://www.khronos.org/opengl/wiki/Common_Mistakes#Texture_upload_and_pixel_reads (Эта страница "распространенных ошибок" - золотая жила - добавьте ее в закладки сейчас!)
В более общем случае производительность glTexSubImage2D может дать вам хорошее представление о том, должна ли загрузка проходить через путь преобразования программного обеспечения. Вы должны сделать это во время запуска программы - просто создайте пустую текстуру (через glTexImage2D с данными NULL), затем выполните несколько вызовов glTexSubImage2D, каждый из которых следует за glFinish, чтобы убедиться, что она завершена. Не обращайте внимания на первый, потому что для него настраиваются кэши / состояния / и другие, а время остальное. Повторите это для нескольких разных форматов и выберите самый быстрый.
Другой вариант - если вы пометили этот вопрос как «Windows», - это создать устройство D3D при запуске (сразу после того, как вы создали окно, но перед тем, как запустить OpenGL), а затем использовать D3D для проверки поддержки формата. В то время как OpenGL допускает преобразование программного обеспечения в допустимый внутренний формат, D3D не делает этого - если это не поддерживается аппаратным обеспечением, вы не сможете это сделать. Затем уничтожьте D3D и откройте OpenGL. (Этот метод также может быть использован для запроса других вещей, которые OpenGL не позволяет вам делать запросы напрямую).
Это действительно полезное правило для перекрестной проверки того, что вы делаете в OpenGL с документацией D3D. Если D3D не может что-то сделать, это может быть хорошим признаком того, что данное устройство не поддерживается аппаратно. Не всегда правда, но полезная отправная точка.
источник