понедельник, 3 декабря 2012 г.

Увеличение скорости загрузки и уменьшение размера изображений на примере .Xna Framework.


Речь пойдет об улучшении игр и других проектов использующих большое количество растровой графики, а точнее об уменьшении объёма приложения, ресурсов оперативной памяти, а также увеличением скорости загрузки.

Как правило разработчики помимо того, что сделать красивый и качественный продукт преследуют и другие цели:
  • Уменьшить размер установочного пакета (для Windows Phone 7 он составляет 225 Мб).
  • Увеличить скорость загрузки ресурсов.
  •  Объем оперативной памяти занимаемой приложением (который не должен превышать 100 Мб).

 У нас имеется 256 изображений размером 128х128 пикселей, для игрового уровня, скажем таких игровых уровней много и тут мы сразу начинаем упираться во все три пункта описанные выше.
Подгружать 256 изображений накладно, давайте их объединим в одну текстуру размером 2048х2048. Тут следует напомнить, что эксперименты мы ставим на XNA под WP7, а она использует Rich профиль, что дает нам право загружать до 2048х2048 пикселей.
Это увеличит скорость загрузки.
Ходят слухи о том, что быстрее подгружаются текстуры размер которых кратен степени двойки, для эксперимента изменим немного оригинальную текстуру, срезав один пиксель, доведя ей размер 2048*2047.
Большинство современных графических карт позволяют хранить текстуры в различных сжатых форматах, которые будут распакованы в режиме реального времени во время растеризации. Одним из таких форматов поддерживаемых большинством графических карт, является S3TC – также известный как DXT сжатие.
Сжатые текстуры не только требуют значительно меньше памяти видеокарты, но и вообще оказывать быстрее, чем несжатые текстуры, за счет снижения требований к пропускной способности.  Но некоторые качества изображения могут быть потеряны из-за сжатия.  Тем не менее, снижение объема памяти позволяет увеличить разрешение текстур, которые будут использоваться, что действительно может дать существенный выигрыш в качестве.
Dxt компрессия уже реализована в .XNA Frameworke, будем использовать ее реализацию, но это не мешает Вам сделать свою оптимизировав её под Ваши нужны.
Для того чтобы использовать её, Вам необходимо в свойствах текстуры переключить параметр «Texture Format» с «Color» в «DxtCompressed», как показано на рисунке 1.  Текстура обязательно должна быть кратна степени двойка (возможно оттуда слух и идет).

 Рисунок 1. Изменение Texture Format.

Резать ее не обязательно, в одной из перегрузок метода SpriteBatch.Draw уже содержится необходимый функционал, мы указываем прямоугольник из оригинальной текстуры с необходимыми координатами.
Чтобы показать действенность описанных методов сделаем контрольные замеры. Проводить их будем на телефоне Nokia Lumia 800. Для большей точности сделаем для каждого метода 10 замеров.
Сведем получившиеся результаты в таблицу 1 и подведем итог.

 Таблица 1. Скорость загрузки изображений.

256 текстур по 128*128
1 dxt 2048*2048

1 origin 2048*2048
1 origin 2048*2047
1
00:00:00.6460000
00:00:00.0330000
00:00:00.1510000
00:00:00.1200000
2
00:00:00.6440000
00:00:00.0330000
00:00:00.1510000
00:00:00.1180000
3
00:00:00.6470000
00:00:00.0410000
00:00:00.1870000
00:00:00.1570000
4
00:00:00.6400000
00:00:00.0330000
00:00:00.1490000
00:00:00.1190000
5
00:00:00.6420000
00:00:00.0330000
00:00:00.1500000
00:00:00.1200000
6
00:00:00.6340000
00:00:00.0470000
00:00:00.1320000
00:00:00.1610000
7
00:00:00.6340000
00:00:00.0470000
00:00:00.1560000
00:00:00.1790000
8
00:00:00.6300000
00:00:00.0500000
00:00:00.1590000
00:00:00.1790000
9
00:00:00.6330000
00:00:00.0480000
00:00:00.1580000
00:00:00.1790000
10
00:00:00.6210000
00:00:00.0470000
00:00:00.1650000
00:00:00.1820000
Средне время загрузки
00:00:00.6371000
00:00:00.0412000
00:00:00.1558000
00:00:00.1514000


Рисунок 2. График зависимости различных методов загрузки от времени.

Как видим скорость загрузки у текстуры с размером 2048х2048 и с использование dxt компрессии значительно меньше.
Размеры .xnb (бинарный файл созданный XNA Game Studio) файлов приведены в таблице 2.

Таблица 2. Размеры .xnb файлов.


Методы
Размеры, Мб
1
Размер 256 текстур по 128*128
16
2
Размер  текстуры 2048*2048 без сжатия
16
3
Размер  текстуры 2048*2048 с сжатием
4

Использование оперативной памяти (занимаемое приложением) для каждого приложения сведены в таблице 3.

Таблица 3. Использование оперативной памяти.

Методы
Размеры, Мб
Дивайс
Эмулятор
1
Размер 256 текстур по 128*128
24
23
2
Размер  текстуры 2048*2048 без сжатия
39
38
3
Размер  текстуры 2048*2048 с сжатием
15
30


Как показывают проведенные опыты наиболее эффективно использование больших текстур с использованием dxt компрессии. Следует разобраться более подробно с этим типом сжатия.

                                         
DXT сжатия (также иногда известный как сжатие S3 ) на самом деле очень простое.  Вот как это работает:
  • Изображение делится на блоки 4х4
  • Для каждого блока, находится два самых важных цвета
  • Получившиеся два цвета хранятся в 16 битах, в формате RGB 5.6.5
  • Для каждого из 16 пикселей в блоке, хранится 2 бита значения, указывающее, как далеко он находится между двумя основными цветами


Когда я впервые прочитал об этом, я думал, как такое может работать.  Что только два уникальных цвета на блок, как это вообще возможно?! Но эта простая схема, оказывается, работают удивительно хорошо для многих реальных изображений мира.
Есть пять вариантов DXT сжатия:
  • DXT1  работает, как я описал выше, плюс некоторая дополнительная магия для кодирования альфа-канала.
  • DXT3 цвет кодируется также как и DXT1, а также хранит 4 бита значения альфа-канала в пикселе.
  • DXT5 цвет кодируется также как и DXT1, а также подобная схема используется для кодирования альфа-канала.
  • DXT2 и DXT4 были не очень-хорошо продуманная попытка стандартизации и не чего дельного не вышло. Вы должны делать вид, что они не существуют.  :-)


DXT1 использует 64 бита на блоке 4x4.  По сравнению с 32-битной несжатой текстурой, это 8x кратная степень сжатия.  DXT2-5 использует 128 бит в блоке 4x4, которая дает 4х кратная степень сжатия.

А теперь плохая новость :-)
DXT сжатие – это сжатие с потерями.  Иногда это могут быть очень большие. На самом деле это работает очень хорошо для некоторых изображений и совсем не подходит для других.
Итак когда вы устанавливаете процессор Texture Формат параметра DxtCompressed, Content Pipeline автоматически выбирает между DXT1 и DXT5, в зависимости от того, имеет ли ваша текстура альфа-канал.  Если она не содержит альфа-канал или содержит однородный альфа-канал будет использовать DXT1, чтобы получить наилучшую степень сжатия, но если текстура содержит дробные значения альфа-канала, он выберет DXT5 вместо этого.

Рассмотрим более подробно каждый из способов сжатия:
DXT1
DXT1 формат предназначен для декомпрессии в реальном времени аппаратными средствами на видеокарте во время рендеринга.  DXT1 является форматом сжатия с потерями, с фиксированным коэффициентом сжатия 8:1.  DXT1 сжатие является одной из форм кодирования блока усечениями (BTC), где изображение разбивается на непересекающиеся блоки, и пикселей в каждом блоке квантуются на ограниченное число значений.  Значения цвета пикселей в блоке 4x4 пиксель аппроксимируются с равноудаленных точек на линии, проходящей через цветовое пространство RGB.  Эта линия определяется двумя конечными точками, и для каждого пикселя в блоке 4x4 2-битный индекс хранится в одном из равноудаленных точек на линии.  Концы линии, проходящей через цветовое пространство, кодируются в 16-битный формат 5:6:5 RGB и одна или две промежуточные точки генерируется за счет интерполяции.  Формат позволяет хранить 1-битный альфа-канал, путем переключения на другой режим, основанный на порядке конечных точек, где создается только одна промежуточная точка и один вывод дополнительного цвета указывает, что он черный и полностью прозрачный.

Посмотрим на рисунок 3 представленный ниже:
Левое изображение является оригиналом. Правое иллюстрирует сжатие в формате DXT1.

 Рисунок 3. Пример Dxt1 сжатия.

Визуально сжатое изображение не отличается от оригинала, что делает результаты сжатия приемлемыми для большинства пользователей. Сжатие, однако, значительно уменьшает размер текстуры.
В данном случае с 256 КБ ​​до 32 КБ.

Однако все не так радужно с этой текстурой (рисунок 4):

Рисунок 4. Пример Dxt1 сжатия.

Основное проблемой является появление шума внутри текста.
А также видны отчетливые полосы на фоне градиента.



Рисунок 5. Шумы внутри текста.

На рисунке 6 показано, как сжатие влияет на цвет. Слева вы видите 16 оттенков красного, от чистого красного до чисто черного. Справа вы видите четыре цвета, которые в результате сжатия DXT выбрать, чтобы представить эти 16 пикселей.

Рисунок 6. Влияние сжатия на цвет.

Рисунок 7 показывает, что происходит, когда разные цвета не находятся на линии линейной в цветовом пространстве. В этом случае все крайности (красный, зеленый и синий) были использованы. Очевидно, в результате интерполированные цвета не совпадают с оригиналами. Обычно область пикселей 4x4 бы не так широкий выбор цветов, но это показывает, что текстура с различными цветами страдают больше.

Рисунок 7. Влияние сжатия на цвет.

DXT1 сжатия обычно хорошо работает для шумных текстур и не так хорошо для чистых изображений, а также градиентов.  Хитрость заключается в том, чтобы использовать его везде, где это возможно и не использовать его только на тех текстурах, где артефакты сжатия слишком нежелательны.

DXT5
DXT5 формат, отличается от DXT3 формата, тем что он хранит информацию об альфа канале подобно тому как хранить информацию о цвете.
Для информации об альфа-канале он использует палитру подобную той, как как храниться цифровая информация. Эта палитра содержит минимальное и максимальное значение альфа-канала. Различают два варианта с 6 и 4 опорными точками.
6 других значений альфа интерполируются между этим минимумом и максимумом. Таким образом, это позволяет более постепенные изменения значения альфа.
Второй вариант делает интерполяцию только для 4 других значений альфа-канала между минимальной и максимальной величиной, но также добавляет альфа-значения 0 и 1 (для полностью прозрачными и не прозрачными). Для некоторых текстур это может дать лучшие результаты.

Рисунок 8. Пример Dxt5 сжатия.

Как видим, края не очень хорошо обрабатываются в некоторых частях.

Рисунок 9. Рванные края при использовании Dxt5 сжатия.

Размер текстуры при этом уменьшился с  256 КБ ​​до 64 КБ.
Как же еще можно использовать эту столь интересную вещь:

  • Область проходимости
  • Карта высот и тд.

Тогда возникает необходимость распаковать получившуюся текстуру.
Один очень хороший человек, а точнее Дмитрий Тимофеев, уже написал об этом в своем блоге как это можно сделать применительно к dxt1.

Вывод:
  • Становится возможной загрузка изображений с высоким разрешением, что приводит к повышению качества контента.
  • Ускоряет скорость «отрисовки» изображений.  
Эффект достигается посредством непосредственной передачи данных видеокарте в сжатом формате.  Видео карта получает меньшее количество битов из памяти, что важно в ограниченной ресурсами среде, каковой является Windows Phone.
  • Использования алгоритма сжатия не приводит к заметной потере качества изображения, но значительно уменьшая его объемы.
Становится возможной загрузка изображений с высоким разрешением, что приводит к повышению качества контента.











Комментариев нет:

Отправить комментарий