В OpenGL привязывается текстура и делается визуализация, затем привязывается другая текстура и делается еще дополнительная визуализация и так далее. Привязывание текстуры является относительно дорогим, поэтому идеальным считается хранение большого числа маленьких изображений на одном большом изображении, привязывание один раз большой текстуры, а затем многократная визуализация отдельных частей. libGDX имеет класс TexturePacker
, который представляет собой приложение командной строки для упаковки множества маленьких изображений в одно большое. Он хранит местоположение маленьких изображений, так что в приложении на них можно легко сослаться по имени, используя класс TextureAtlas
.
TexturePacker использует несколько алгоритмов запаковки, но самый важный основан на алгоритме максимальных прямоугольников. TexturePacker так же использует подбор грубой силой, запаковку с многочисленными эвристиками различных размеров и затем выбирает наиболее эффективный результат.
Запуск TexturePacker
Класс TexturePacker
находится в проекте gdx-tools. Он может быть запущен из исходного кода с помощью Eclipse:
import com.badlogic.gdx.tools.texturepacker.TexturePacker; public class MyPacker { public static void main (String[] args) throws Exception { TexturePacker.process(inputDir, outputDir, packFileName); } }
Если вы используете gradle и класс TexturePacker
не найден, добавьте gdx-tools в ваш build.gradle файл.
Его также можно запустить из nightly сборки:
// OS X / Linux java -cp gdx.jar:extensions/gdx-tools/gdx-tools.jar com.badlogic.gdx.tools.texturepacker.TexturePacker inputDir [outputDir] [packFileName] // WINDOWS java -cp gdx.jar;extensions/gdx-tools/gdx-tools.jar com.badlogic.gdx.tools.texturepacker.TexturePacker inputDir [outputDir] [packFileName]
Производительность TexturePacker
TexturePacker выполняется значительно быстрее используя Java 1.7+, особенно при упаковке сотни входных изображений.
Структура директорий
TexturePacker может запаковать все изображения для приложения за один раз. Указывая директорию, он будет рекурсивно сканировать файлы изображений. Для каждой директории с изображениями, он запаковывает изображения в одну большую текстуру, называемою страницей. Если изображения в директории не помещаются в максимальных размер одной страницы, то тогда используется несколько страниц.
Изображения в той же директории будут в том же наборе страниц. Если все изображения помещаются на одну страницу, тогда не будут использоваться поддиректории, потому что с одной страницей приложение выполнит только одну привязку текстуры. В противном случае, поддиректории могут быть использованы для разделения взаимосвязанных изображений и уменьшения привязок текстур. Например, приложение может захотеть поместить все игровые изображения в отдельную директорию, от изображений для меню паузы, так как существует два набора изображений, то визуализируются они последовательно: все игровые изображения визуализируются (одна привязка), затем меню паузы визуализируется сверху (другая привязка). Если изображения были бы в одной директории, что привело к более чем одной странице, тогда каждая страница могла содержать смесь игровых изображений и меню паузы. Это может привести к нескольким привязкам текстур для визуализации игры и меню паузы, вместо одной привязки для соответствующих изображений.
Поддиректории также полезны для группировки изображений с соответствующими настройками текстуры. Настройки вроде формата памяти (RGBA, RGB и так далее) и фильтрации (nearest, linear и так далее) для текстуры. Изображения, нуждающиеся в различных текстурных настройках должны быть в отдельных страницах, следовательно, должны быть в отдельных директориях.
Чтобы использовать поддиректории для организации вывода TexturePacker без набора страниц для каждой директории, смотрите настройку combineSubdirectories
.
Чтобы избежать использования путей поддиректорий в именах изображений в файле атласа, смотрите настройку flattenPaths
.
Конфигурация
Каждая директория может содержать "pack.json" файл, который является JSON представлением TexturePacker.Settings
класса. Каждая поддиректория наследует все параметры настроек родительской директории. Любые настройки параметров в поддиректории переопределяют параметры, наследованные от родительской директории.
Ниже пример JSON со всеми доступными параметрами настройки и значениями по умолчанию для каждого из них. Не нужно указывать все настройки, некоторые или даже все настройки могут быть опущены. Если для директории или любой родительской директории настройки не указаны, то используется значения по умолчанию.
{ pot: true, paddingX: 2, paddingY: 2, bleed: true, edgePadding: true, duplicatePadding: false, rotation: false, minWidth: 16, minHeight: 16, maxWidth: 1024, maxHeight: 1024, square: false, stripWhitespaceX: false, stripWhitespaceY: false, alphaThreshold: 0, filterMin: Nearest, filterMag: Nearest, wrapX: ClampToEdge, wrapY: ClampToEdge, format: RGBA8888, alias: true, outputFormat: png, jpegQuality: 0.9, ignoreBlankImages: true, fast: false, debug: false, combineSubdirectories: false, flattenPaths: false, premultiplyAlpha: false, useIndexes: true, limitMemory: true, grid: false, scale: [ 1 ], scaleSuffix: [ "" ] }
Формат JSON в libGDX
JSON формат в libGDX минимальный, так что двойные кавычки в большинстве случаев являются необязательными.
Настройки
Поле | Описание | Значение по умолчанию |
---|---|---|
pot | Если true, то страницы будут иметь размер степени двойки. | true |
paddingX | Число пикселей между упакованными изображениями на оси X. | 2 |
paddingY | Число пикселей между упакованными изображениями на оси Y. | 2 |
bleed | Если true, RGB значения для прозрачных пикселей устанавливаются на основе RGB значений ближайших непрозрачных пикселей. Это предотвращает артефакты фильтрации, когда RGB значения подобранны для прозрачных пикселей. | true |
edgePadding | Если true, то половина paddingX и paddingY будет использована вокруг краев упакованной текстуры. | true |
duplicatePadding | Если true, то пиксели краев копируются в отступы. Отношение paddingX/Y должно быть больше или равно 2. | true |
rotation | Если true, TexturePacker будет пытаться упаковать более эффективно, вращая изображения на 90 градусов. Приложение должно особым образом позаботиться о правильной визуализации таких регионов. | false |
minWidth | Минимальная ширина выходных страниц. | 16 |
minHeight | Минимальная высота выходных страниц. | 16 |
maxWidth | Максимальная ширина выходных страниц. Значение 1024 является безопасным для всех устройств. Очень старые устройства могут иметь пониженную производительность при ширине более 512. | 1024 |
maxHeight | Максимальная высота выходных страниц. Значение 1024 является безопасным для всех устройств. Очень старые устройства могут иметь пониженную производительность при высоте более 512. | 1024 |
square | Если true, выходных страницы будут иметь одинаковую ширину и высоту. | false |
stripWhitespaceX | Если true, пустые пиксели на левой и правой границе входного изображения будут удалены. Приложение должно особым образом позаботиться о правильной визуализации таких регионов. | false |
stripWhitespaceY | Если true, пустые пиксели на верхней и нижней границе входного изображения будут удалены. Приложение должно особым образом позаботиться о правильной визуализации таких регионов. | false |
alphaThreshold | От 0 до 255. Альфа ниже данных значений будет рассматриваться как ноль. | 0 |
filterMin | Фильтр минимизации для текстуры. | Nearest |
filterMag | Фильтр увеличения для текстуры. | Nearest |
wrapX | Настройки обертывания в X направлении для текстуры. | ClampToEdge |
wrapY | Настройки обертывания в Y направлении для текстуры. | ClampToEdge |
format | Формат текстуры, который будет использован в памяти. | RGBA8888 |
alias | Если true, тогда два изображения, совпадающие попиксельно будут упакованы только один раз. | true |
outputFormat | Тип изображения для выходных страниц, "png" or "jpg". | png |
jpegQuality | От 0 до 1. Настройка качества, если выходной формат "jpg. | 0.9 |
ignoreBlankImages | Если true, TexturePacker не будет добавлять регионы для совершенно пустых изображений. | true |
fast | Если true, TexturePacker будет выполняться значительно быстрее, но без эффективной упаковки. | false |
debug | Если true, тогда на выходных страницах рисуются линии, показывающие границы упакованных изображений. | false |
combineSubdirectories | Если true, тогда директория содержащая файл настроек и все поддиректории будут упакованы, как если бы они были в одной директории. Любые файлы настроек в поддиректориях игнорируются. | false |
flattenPaths | Если true, префиксы поддиректорий удаляются из имен изображений. Имена изображений должны быть уникальны. | false |
premultiplyAlpha | Если true, RGB будет умножено на альфу. Смотрите об умножении на альфу. | false |
useIndexes | Если false, имена изображений будут использованы без удаления суффикса индекса изображения. | true |
limitMemory | Если true, в любой момент времени только одно изображения будет в памяти, но каждое изображение будет читаться дважды. Если false, все изображения будут храниться в памяти во время упаковки, но читаться только один раз. | true |
grid | Если true, тогда изображения в порядке упаковываются в равномерную сетку. | false |
scale | Изображения масштабируются с заданным значением, и на выходе получается весь атлас. | [1] |
scaleSuffix | Для каждого масштаба и выходных файлов используется суффикс. Если значение опущено, файлы с несколькими масштабами будут выводиться с тем же именем в директории для каждого масштаба. | [""] |
9-Patch
Если имя файла изображения оканчивается на ".9" перед расширением, то изображение рассматривается как 9-patch. 9-patch изображения можно создать с помощью данного инструмента. Изображение должно иметь границу в одни прозрачный пиксель. Верхняя и левая граница могут иметь одну линию черных пикселей, определяющею информацию для разделения, то есть какие части будут растягиваться. Нижняя и правая граница тоже могут иметь линию черных пикселей, определяющею информацию об отступах, то есть, как будет размещен контент. Когда такое изображение запаковано, граница в 1 пиксель удаляется, а информация о разделении и отступах сохраняется в запакованный файл. TextureAtlas
позволяет создать NinePatch
экземпляр для региона, используя информацию о разделении.
Индексы изображений
Если имя файла изображения оканчивается подчеркиванием и затем числом (например, animation_23.png), то число считается "индексом" и хранится отдельно. Имя изображения храниться без подчеркивания и индекса. TextureAtlas
допускает извлечение списка всех изображений с одинаковым именем, упорядоченных по индексу. Это позволяет легко упаковать анимацию без потери порядка кадров.
Упаковка
Класс TexturePacker
находиться в gdx-tools.jar
, который расположен в директории расширений в nightlies/releases zip файлах. Вам понадобиться TexturePacker в лишь в качестве инструмента для обработки файлов изображений для вашего приложения, вам не нужно иметь его в качестве зависимости для запуска приложения. Для запуска запаковщика вам необходимо оба gdx.jar
и gdx-tools.jar
файла.
// OS X / Linux java -cp gdx.jar:gdx-tools.jar com.badlogic.gdx.tools.texturepacker.TexturePacker inputDir outputDir packFileName // WINDOWS java -cp gdx.jar;gdx-tools.jar com.badlogic.gdx.tools.texturepacker.TexturePacker inputDir outputDir packFileName
inputDir
является корневой директорией, содержащей изображения. outputDir
является директорией, где будет размещены упакованные изображения. packFileName
это имя файл упаковки, используется префикс для выходных упакованных файлов изображений.
Если опустить outputDir
, файлы будет размещены в новой директории, рядом с inputDir
и суффиксом "-packed". Если опустить packFileName
, то используется имя "pack".
В то время как упаковка текстур предназначена быть полностью автоматической, существует пользовательский интерфейс, предоставленный Obli (хотя немного устарел): TexturePacker GUI. Также существует коммерческий продукт на сайте texturepacker.com, который совершенно не связан с упаковщиком текстур из libGDX, имеющий пользовательский интерфейс, множество функций и хорошую документацию.
Автоматическая упаковка
Во время разработки может быть удобным иметь настольное приложение для запуска TexturePacker до начала игры:
public class DesktopGame { public static void main (String[] args) throws IOException { Settings settings = new Settings(); settings.maxWidth = 512; settings.maxHeight = 512; TexturePacker.process(settings, "../images", "../game-android/assets", "game"); new LwjglApplication(new Game(), "Game", 320, 480, false); } }
Каждый раз, когда игра запускается, все изображения будут упакованы. Это может быть особенно удобно, когда художникам предоставляется сборка приложения, и они могут попробовать использовать новые изображения, даже не зная об упаковки. Если запаковывается много изображений, настройки быстрой работы могут быть полезны для избегания долгого ожидания.
При загрузки файлов из classpath, Eclipse как правило не отражает изменения файлов, которые обновляются внешне. Проект с измененными файлами в Eclipse должен быть обновлен вручную. Напротив, во время разработки файлы могут быть загружены через файловую систему, где нет такой проблемы.
TextureAtlas
TexturePacker в результате своей работы выдает директорию страниц изображений и текстовый файл, описывающий все изображения запакованные в страницы. Ниже показано, как использовать изображения в приложении:
TextureAtlas atlas; atlas = new TextureAtlas(Gdx.files.internal("packedimages/pack.atlas")); AtlasRegion region = atlas.findRegion("imagename"); Sprite sprite = atlas.createSprite("otherimagename"); NinePatch patch = atlas.createPatch("patchimagename");
TextureAtlas
читает файл упаковки и загружает все изображения страницы. Можно получить TextureAtlas.AtlasRegions
, являющиеся TextureRegions
, которые предоставляют дополнительную информацию о запакованном изображении, такую как индекс кадра или пустую область, которая была удалена. Также могут быть созданы спрайты и 9-patch. Если пустая область была удалена, созданный спрайт будет являться TextureAtlas.AtlasSprite
, который позволяет спрайту быть использованным как если бы была пустая область.
Метод findRegion()
не очень быстрый, так что возвращаемое значение следует хранить, вместо вызова данного метода при каждом кадре. Также обратите внимание, что методы createSprite()
и createNinePatch()
создают новый экземпляр.
TextureAtlas
содержит все текстуры страниц. Высвобождение TextureAtlas
высвободит все текстуры страниц.
Комментариев нет:
Отправить комментарий