acombine.ru
← все заметки

Спрайт-атлас: почему один PNG лучше сотни

Первую свою игру я собирал наивно: каждый кадр анимации — отдельный файл. Персонаж бежит — двенадцать PNG. Взрыв — шестнадцать. К релизу в папке лежало под тысячу картинок, а игра на старом телефоне заметно проседала именно на сценах, где на экране много разной мелочи.

Причина оказалась не в размере картинок, а в их количестве. Каждый отдельный PNG — это отдельная текстура, а каждая смена текстуры при отрисовке — это команда видеокарте «переключись». Такие переключения дешёвые поодиночке, но их сотни за кадр, и на слабом GPU они складываются в потерянные миллисекунды.

Что такое атлас

Атлас — это один большой лист, на который упакованы все мелкие кадры, плюс табличка «какой кадр в каком прямоугольнике лежит». Игра держит в памяти одну текстуру, а рисуя спрайт, просто берёт из неё нужный кусок по координатам. Переключений текстуры больше нет — все спрайты с одного листа рисуются подряд.

Практическое правило: одна текстура на экран — почти всегда быстрее, чем сто маленьких, даже если суммарно пикселей столько же.

Как я его собираю

Для упаковки я написал маленькую утилиту на Python (spryte). Она делает три вещи:

{
  "run_00": { "x": 0,  "y": 0,  "w": 34, "h": 48, "ox": 3, "oy": 0 },
  "run_01": { "x": 34, "y": 0,  "w": 33, "h": 48, "ox": 3, "oy": 0 },
  "boom_00":{ "x": 0,  "y": 48, "w": 64, "h": 64, "ox": 0, "oy": 0 }
}

Пара граблей

Первая — «протекание» соседних кадров. Если рисовать спрайт с билинейной фильтрацией, по краю прямоугольника подхватывается пиксель соседа. Лечится полем в 1–2 пикселя между кадрами (padding), а лучше — дублированием крайнего пикселя наружу (extrude).

Вторая — соблазн запихнуть в один атлас вообще всё. Не стоит: если атлас перерос лимит текстуры устройства (часто 2048 или 4096 пикселей по стороне), движок молча порежет его или откажется грузить. Я держу тематические листы: отдельно персонажи, отдельно интерфейс, отдельно фоны.

С тех пор атлас — первое, что я делаю в любом новом проекте. Скучная механическая работа, которую один раз автоматизировал и забыл, а кадры на слабых телефонах перестали пропадать.

← все заметки