У меня есть некоторый код для загрузки файлов изображений DDS в текстуры OpenGL, и я хотел бы расширить его для поддержки сжатых форматов BC6 и BC7, представленных в D3D11. Поскольку DirectX и OpenGL расходятся во мнениях относительно того, находится ли источник текстуры в верхнем левом или нижнем левом углу, мой загрузчик DDS переворачивает пиксели каждого изображения вдоль оси Y перед передачей пикселей в OpenGL.
Переворачивание сжатых текстур представляет дополнительную складку: в дополнение к переворачиванию каждой строки блоков 4x4 пикселей, вам также необходимо перевернуть пиксели внутри каждого блока. Я нашел здесь код для переворачивания блоков BC1 / BC2 / BC3, и из блок-схем на MSDN было легко адаптировать переворачивающий код BC3 для обработки BC4 и BC5. В Bc6 и BC7 форматы значительно выглядеть устрашающе, хотя. Есть ли похожий трюк с переворотом, чтобы перевернуть эти форматы, или мне придется полностью распаковывать и перепаковывать каждый блок?
ОБНОВЛЕНИЕ: оказывается, что переворот текстуры был необходим только потому, что мои координаты текстуры были неправильно инвертированы во время экспорта. Удаление обоих сальто сделало код более простым и быстрым (спасибо Humus!). Переворачивание блоков BC6 / BC7 может все еще быть интересной проблемой, но это больше не относится к моему первоначальному сценарию.
Ответы:
Я подозреваю, что действительно возможно перевернуть блоки BC6-7 с гораздо меньшим количеством работы, чем полное распаковывание и повторное сжатие, но это все еще не пикник и намного сложнее, чем переворачивание блоков BC1-5.
Прежде всего, BC6-7 имеют множество режимов, которые можно выбрать для каждого блока. Режимы имеют совершенно разные бинарные макеты, поэтому вам в значительной степени придется написать разные подпрограммы для каждого режима (всего их ~ 20, IIRC).
Другая сложность заключается в режимах разделения, в которых пиксели в блоке делятся на 2 или 3 подмножества, каждое из которых имеет собственный сегмент линии RGB. Раздел должен быть выбран из предопределенного набора; те для BC6 можно увидеть здесь . Проблема в том, что этот набор разделов не является симметричным при вертикальных переворотах. Тем не менее, я подозреваю , что это симметрично относительно некоторой комбинации вертикальных переворачиваются и перестановка два подмножества. Например, если посмотреть на раздел № 22 (6-я строка, 3-й столбец) по этой ссылке, то в таблице нет его версии с вертикальным переворотом, но если вы перевернете ичередуя 0 и 1, вы получите раздел № 9 (3-й ряд, 2-й столбец). Я не проверял, что каждый раздел можно перевернуть таким образом, и я не проверял те разделы для BC7 (который также включает разделы с 3 подмножествами).
Даже если это работает, вы все еще не свободны дома. В BC1-5 порядок двух конечных точек линейного сегмента RGB использовался для переключения режимов, но в BC6-7 порядок конечных точек выбирается для фиксации одного бита индексов на пиксель в каждом подмножестве разделов. Поэтому, если вы меняете раздел вокруг, вам также может потребоваться поменять местами порядок конечных точек.
И наконец, что не менее важно, в BC6-7 конечные точки часто сжимаются дельтой (т. Е. Одна конечная точка сохраняется с полной точностью, а другие хранятся как дельты с более низкой точностью от нее). Замена подмножеств разделов и порядка конечных точек переключит, какая конечная точка является высокоточной, так что вам придется перетасовывать биты низкой точности и сводить на нет некоторые дельты.
В общем, не похоже, что есть какой-то фундаментальный showtopper (хотя я на самом деле не написал код), но наверняка было бы много работы, чтобы перевернуть или повернуть эти форматы. Если возможно, я бы порекомендовал перевернуть изображения в вашем конвейере, прежде чем они будут сжаты.
(Кстати, самая полная спецификация BC6-7, которую я нашел, - это спецификация ARB_texture_compression_bptc ; я также написал пост в блоге о форматах BCn некоторое время назад.)
источник
Переворот только по умолчанию на двух форматах. Вы можете пойти против по умолчанию.
Это, вероятно, лучше делать на стороне OpenGL, потому что OpenGL находится на более низком уровне и, следовательно, с меньшей вероятностью теряет оптимизацию при выполнении подобных вещей.
источник