0,0
рейтинг
16 ноября 2012 в 20:05

Разработка → Избавление от артефактов сжатия PVRTC текстур из песочницы tutorial

Проблематика


При разработке мобильных игр многие сталкиваются с необходимостью уменьшения занимаемой оперативной памяти или размера дистрибутива. Чаще всего самые тяжеловесные ассеты в проекте это текстуры. Несжатая текстура размером 1024х1024 занимает в районе 4 Мб. А в сцене обычно таких текстур не мало. И если мы хотим, чтобы сцены нашей игры загружались быстрее и не занимали слишком много оперативной памяти, мы вынуждены подвергать текстуры компрессии. В unity3d для мобильных устройств существует несколько типов сжатия. Думаю, описанный здесь подход для повышения качества результата компрессии текстур будет справедлив для всех алгоритмов, но рассматривать мы будем на примере PVRTC. У него есть один большой плюс, и один большой минус. Размер текстур уменьшается в восемь раз, но при этом появляются ужасные артефакты, особенно на прозрачных текстурах. Данная тема призвана помочь в борьбе с последними.

Алгоритм


Суть алгоритма заключается в постобработке текстур перед сжатием. Для этого нам понадобится графический редактор, умеющий работать со слоями. Я использовал Adobe Photoshop. Рассмотрим алгоритм подробно:

1) Открываем текстуру в фотошопе, и создаем новый слой поверх существующего.
2) Заливаем его средним оттенком серого.





3) Далее на этот слой накладываем шум с настройками как на рисунке:



4) Выставляем режим наложения «Soft Light» и прозрачность от 30 до 50 процентов таким образом, чтобы шум не очень бросался в глаза, но все же был виден.



5) Сохраняем и импортируем текстуру.



Если текстура полупрозрачная – то просто выделите пиксели с исходного слоя, инвертируйте выделение и удалите пиксели из зашумленного слоя.

После импорта осталось только указать сжатие RGBA Compressed PVRTC 4bit. Очень советую во вкладках импортера iOs и Android поставить галочку Override и указать Best в Compression Quality. Если ваша текстура будет использована для GUI, снимите галочку Generate Mip Maps. Это избавит вас от эффекта «замыления», если элемент UI будет расположен достаточно далеко от камеры.

Результаты



Как видим, все артефакты благополучно ушли. Обратите внимание на зеленый камень и шестеренку вокруг таймера вверху.

Заключение


До использования этого нехитрого способа мне приходилось оставлять текстуры для GUI несжатыми, из-за чего приложение зачастую занимало в памяти очень много места. Но с данным подходом получается сжать почти все текстуры для интерфейсов. Кроме очень мелких деталей, которые все же приходится выносить на отдельные атласы и оставлять в RGBA TrueColor. Но экономия памяти колоссальная. Данный подход был успешно применен в совместном проекте Heyworks Unity Studio и iFree InnovationsDragonIt. Весь предоставленный в статье графический материал сделан на основе текстур из этого проекта.
Никита Захарченко @Nick_Field
карма
16,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (26)

  • 0
    А других утилит сжатия, которые не дают артефактов, нету?
    • 0
      Есть отличная утилита — PVRTexTool. На высоких настройках качества выдает значительно лучший результат, чем компрессор в unity3d. Но артефакты все же могут присутствовать. PVRTC — очень жесткий алгоритм сжатия.
      • 0
        Статья полезная безусловно НО, компрессор в unity3d и есть утилита PVRTexTool.
        • 0
          Да, посмотрел в интернете, теперь вижу. Меня сбили с толку статьи, где сравнивали результаты PVRTexTool с результатами компрессии в Unity3D. Все дело в том, что некоторые версии unity3d выходили со старой версией данного инструмента.
      • 0
        Почитал описание алгоритма. Теперь понятно откуда такие артефакты. Видно, что формат поддерживает специальный режим, который позволяем с ними бороться. Видимо по умолчанию он не задействован.
  • 0
    А какой 2D фреймворк используете в Unity?
    • 0
      В данном проекте мы используем EZ GUI
      • 0
        А с 2D Toolkit работали?
  • 0
    Зачем портить текстуру шумом?
    Есть такой метод: doom2d.org/forum/viewtopic.php?f=16&t=180

    Кратко говоря, подкладываем под альфу цвета спрайта.
    • 0
      На всякий случай: это работает в PNG и в TGA, с PVRTC не пробовал.
      • 0
        Да, я тоже не пробовал такой подход. Но, при использовании EZ GUI в Unity все текстуры собираются в атласы, причем не ручками, а программно. И править их не только не желательно, но и трудоемко. Первый, кто перебилдит атлас, убьет все твои старания. А шум наложить можно очень быстро. Я использую экшен для фотошопа и применяю шум сразу ко все выбранным текстурам.
      • 0
        Только сейчас я понял, что в Unity уже реализован такой подход.
        Но проблема артефактов остается в силе, т.к. данный алгоритм практически не работает с атласами интерфейсов, где между элементами обычно расстояние в пару пикселей.
        Вот превью уже импортированной в статью текстуры:
        • +1
          Этот прием делается за считанные секунды, можно использовать и экшен. Так что никто ничего не убьет.
          Дай мне попробовать такой атлас интерфейсов, я попробую обработать тем же методом и посмотрим, что получится.

          А текстура из твоего примера обработана не так.
          Вот как надо:


          • 0
            Собери из этих солдат атлас 512х512, объедени все слои (т.к. атлас UI генерируется програмно и все пишется в один слой) и попробуй свой метод. Если действительно так можно сделать быстро, то стоит попробовать пожать этот атлас PVRTC. Если несложно, выложи результат.
            А текстура из моего примера — это превью уже заэкспортированного PNG файла в Unity. Этот процесс конролировать я не могу ровно так же, как и ручаться за тамошний алгоритм.
            • 0
              Процесс точно такой же, как и с одиночным спрайтом.

              rghost.ru/41640158
              C юнити я не работал, PVRTC жать не умею. Так что там тарга.

              Покажи, что получится, интересно.
              • 0
                Попробовал. Проблема в том, что PVRTC жмет и альфу. И артефакты все равно вылазят. Твой подход можно наверно испозовать с шейдером, где альфа отдельно от дифуза. И альфу не сжимать.
                Вот результаты.
                Difuse:

                Alpha:
                • 0
                  Печальное зрелище. А если альфу 1-бит?
                  • 0
                    Я не совсем Вас понял про «альфу 1-бит»
                    • 0
                      Если взять исходную картинку в формате RGBA 5551?
                      • 0
                        Unity3D не поддерживает RGBA 5551
  • 0
    Спасибо за инфу. Сами сейчас думаем, как пожать атласы покомпактнее…
  • +1
    спасибо за статью )
  • 0
    В утилитах от PowerVR почему-то отсутствует опция с наилучшим качеством компрессии (4), которая тем не менее, есть в SDK. Я написал себе простейшую программу, которая использует их SDK, и получил намного лучшее качество. Время работы алгоритма тоже сильно увеличилось, но красота требует жертв.
    • 0
      подЕлитесь?)
      • 0
        Код «встроен» в достаточно большой фреймворк для работы с изображениями, и я не уверен, что могу его выложить целиком без согласования с работодателем. Опишу в общих словах, и таки дам ключевой кусок кода. Там все просто на самом деле.

        1) Для начала изображение нужно прочитать из файла в память. Если это png, то его надо раскодировать в формат ARGB (32 bit). Для этого можно использовать любые средства, какие под руку подвернутся — хоть любимый игровой движок, хоть Qt, хоть libpng и ему подобные.
        2) Затем изображение нужно «добить» до квадрата со стороной равной степени двойки — это требование формата pvrtc. Если вам не повезло, и у вас изображение 129 х 257, то будьте любезны сделать его 512 x 512 (квадрат нужен!).
        3) Дальше вам понадобится сама библиотека libPVRTC. Скачать её можно здесь: www.imgtec.com/powervr/insider/powervr-sdk-docs.asp, но для этого придётся реально зарегистрироваться. Библиотека у них есть под Линукс, Мак и Винду.
        4) И, наконец, немного кода: pastebin.com/y2xWqs7X

        Будут вопросы — задавайте.

        P.S. Забавный момент — для компрессии в PVRTC требуется изображение в формате ARGB. Несмотря на то, что в документации чётко написано RGBA. При этом декомпрессия из PVRTC осуществляется функцией pvrtc_decompress в формат RGBA, а не ARGB. Странно, да? Я спросил об этом на форуме разработчиков библиотеки, и мне ответили что-то вроде «ну это такая мелочь, всё равно мы на эту библиотеку уже давно забили». Как-то так. =)
  • 0
    Огромное спасибо автору за этот замечательный метод! Вы спасли меня от нервного срыва, а проект — от использования костыля в виде PNG-ткустур, которые в рантайме распаковывались бы в RGBA 16-bit и отжирали б кучу памяти.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.