Загрузка несжатой текстуры DDS в GL

У меня есть этот файл DDS. Я написал простую программу чтения DDS для чтения заголовка DDS и вывода сведений о нем на основе спецификации MSDN. В нем говорится, что это RGB DDS с битовой глубиной 32 байта на пиксель, а альфа игнорируется, т. Е. Формат пикселя - X8R8G8B8 (или A8R8G8B8). Чтобы убедиться в этом, я также открыл этот файл в шестнадцатеричном редакторе, который показывает первые (т.е. от начала данных) 4 байта как BB GG RR 00 (замените их правыми шестнадцатеричными значениями цвета первого пикселя). Я читал, что копия текстуры OpenGL функции воздействуют на байты (по крайней мере, концептуально) и, таким образом, с их точки зрения, эти данные являются B8G8R8A8. Пожалуйста, поправьте меня, если мое понимание здесь неверно.

Теперь к glTexImage2D внутреннему формату я передаю RGBA8, а к внешнему формату и типу я передаю BGRA и UNSIGNED_BYTE. Это приводит к синему оттенку в визуализируемом выводе. В моем фрагментном шейдере, просто для проверки, я сделал swizzle, чтобы поменять местами R и B, и он отображается правильно.

Я изменил код шейдера, а затем заменил type с UNSIGNED_BYTE на UNSIGNED_INT_8_8_8_8_REV (на основе этого предложения ), и он по-прежнему отображает синий оттенок. Теперь изменив внешний формат на RGBA и с любым типом (UNSIGNED_BYTE или UNSIGNED_INT_8_8_8_8_REV), все отображается нормально!

  • Поскольку OpenGL не поддерживает ARGB, использование BGRA понятно. Но почему RGBA здесь работает правильно? Это кажется неправильным.
  • Почему тип не влияет на порядок каналов?
  • Имеет ли значение GL_UNPACK_ALIGNMENT? Я оставил его по умолчанию (4). Если я правильно прочитал руководство, это не должно повлиять на чтение памяти клиента.

Подробнее

  • OpenGL версии 3.3
  • Intel HD Graphics с поддержкой до OpenGL 4.0
  • Используется GLI для загрузки файла DDS и получения указателя данных.

person legends2k    schedule 29.11.2014    source источник
comment
Могу я взглянуть на ваш ридер?   -  person elect    schedule 28.07.2015
comment
Когда я спросил об этом, я написал что-то одноразовое. Спасибо за вопрос, в итоге я написал кое-что заново: поделился здесь! Как говорится в ответе, вышеупомянутая проблема возникла из-за ошибки в GLI, которая была недавно исправлена.   -  person legends2k    schedule 31.07.2015


Ответы (1)


Наконец-то я сам нашел ответы! Разместите его здесь, чтобы он мог помочь кому-то в будущем.

Поскольку OpenGL не поддерживает ARGB, использование BGRA понятно. Но почему RGBA здесь работает правильно? Это кажется неправильным.

Изучив память, на которую указывает void* data, которую GLI возвращает, когда запрашивается указатель на двоичные данные изображения, можно увидеть, что GLI уже переупорядочил байты при передаче данных из файла в память клиента. Окно памяти показывает, от младшего к старшему адресу, данные в форме RR GG BB AA. Это объясняет, почему передача GL_RGBA работает. Однако ошибка со стороны GLI заключается в том, что при запросе внешнего формата он возвращает GL_BGRA вместо GL_RGBA. Была обнаружена ошибка для решения этой проблемы.

Почему тип не влияет на порядок каналов?

Нет, эффект есть. Машина, на которой я провожу этот эксперимент, — это машина Intel x86_64 с прямым порядком байтов. В OpenGL Wiki четко указано, что данные клиентских пикселей всегда находятся в клиентском порядке байтов. Теперь, когда передается GL_UNSIGNED_BYTE или GL_UNSIGNED_INTunsigned int8unsigned int8_REV, базовый базовый тип (а не тип компонента) является unsigned int для обоих; таким образом, чтение int из data на машине с прямым порядком байтов будет означать, что переменная в регистре окажется с переставленными байтами, то есть RR GG BB AA в ОЗУ достигнет VRAM как AA BB GG RR; при обращении к текстуре типа RGBA (RR GG BB AA) чтение AA на самом деле даст RR. Чтобы исправить это, реализация OpenGL меняет местами байты, чтобы нейтрализовать порядок байтов машины, в случае GL_UNSIGNED_BYTE type. В то время как для GL_UNSIGNED_INT_8_8_8_8_REV мы явно указываем OpenGL поменять порядок байтов, и поэтому он отображается правильно. Однако, если type передается как GL_UNSIGNED_INT_8_8_8_8, то рендеринг испорчен, так как мы указываем OpenGL копировать байты, как они были прочитаны на машине.

Имеет ли отношение к этому GL_UNPACK_ALIGNMENT? Я оставил его по умолчанию (4). Если я правильно прочитал руководство, это не должно повлиять на чтение памяти клиента.

Это имеет отношение к распаковке данных текстуры из памяти клиента в память сервера. Однако это необходимо для того, чтобы учесть байты заполнения, присутствующие в строках изображения, для правильного вычисления шага (шага). Но конкретно к этой проблеме он не имеет отношения, поскольку его флаг шага равен 0, то есть в рассматриваемом файле DDS нет битов заполнения.

Материалы по теме: https://www.opengl.org/wiki/Pixel_Transfer#Pixel_type

person legends2k    schedule 29.11.2014
comment
Этот ответ, надеюсь, правильный, но я не уверен в нем на 100%, так как сделал некоторые предположения в своем выводе. Если это неправильно, некоторые из мастеров opengl могут вывести меня из моего невежества. Спасибо! - person legends2k; 29.11.2014
comment
Просто чтобы вы знали, формат файла DDS может иметь отступы для выравнивания. В мире D3D такие вещи называются высотой тона. Вы можете прочитать раздел dwPitchOrLinearSize здесь. - person Andon M. Coleman; 29.11.2014
comment
Спасибо за совет! Я обновил ответ; Я прочитал документацию наспех, мой плохой. Надеюсь, в остальном все верно. - person legends2k; 29.11.2014