Поговорим о 2D-играх. Независимо от платформы, на которой они разрабатываются — почти всегда они будут использовать 3D-акселлераторы для вывода 2D-спрайтов (iOS, Android, PC… даже Flash уже это учится делать).
И все будет хорошо, пока вы не захотите смасштабировать вашу картинку. И тогда вы обнаружите, что до этого идеально стыковавшиеся тайлы приобретут швы, а по краям спрайтов появятся непонятные черточки.
Вы попытаетесь наложить тайлы внахлест, но швы все равно останутся… И вы начнете ломать голову.
А дело все в злосчастных прозрачных пикселях! Оказывается, у них тоже есть цвет.
Для того, чтобы понять, почему это происходит, вы должны понять, каким образом GPU масштабирует текстуры. Он это делает не совсем так, как это делают графредакторы. И дело тут касается прозрачности.
Оно и понятно, это простительно для 3D игр и тамошних текстур, но это будет вызывать артефакты в случае, если у вас на спрайтах будет ситуация, когда полностью непрозрачный пиксель будет соседствовать с полностью прозрачным (что с великой долей вероятности появится в случае пиксель-арта и т.п.).
О прозрачности и PNG.
Допустим, у нас есть картинка синего квадрата, где присутствует условие бага — непрозрачные пиксели соседствуют с полностью прозрачными:
Это изображение состоит из двух каналов — канал цвета (RGB) и альфа-канал (прозрачность). Вся загвоздка в том, что полностью прозрачные пиксели все равно имеют какое-то значение в канале цвета. И какое именно это будет значение — известно только софтине, которая сжимала PNG. По сути, эти цвета могут быть любыми.
В ситуации с изображением выше запросто может получиться такая картина:
Т.е. прозрачные пиксели будут иметь белый цвет. Но т.к. они полностью прозрачны — мы этого никогда не увидим и все будет ок.
Прозрачность, GPU и масштабирование.
Теперь давайте посмотрим, как видеокарта масштабирует текстуры с прозрачностью.
Для упрощения этого дела, она масштабирует отдельно канал цвета и отдельно — альфа-канал. Например, при масштабировании вышеупомянутой текстуры на 80% (баг проявится при любом скейле), мы получим такую картину:
Видите?
GPU смешал пограничные синие пиксели с теми, что за границей прозрачности (т.к. он скейлил канал цвета отдельно от альфы и ему было все равно, прозрачные они или нет). В результате пограничные пиксели смешались с белым цветом и приобрели совсем непонятный цвет.
Очевидно, если попытаться затайлить такой спрайт, мы явно увидим швы.
И, думаю, очевидно, почему от таких артефактов избавлены спрайты, граница которых постепенно сходит в прозрачность, а не резко скачет с 1 до 0.
Как бороться?
Теперь, когда мы знаем в чем дело, мы знаем, как с этим бороться. Нам нужно, чтобы прозрачные пиксели, прилегающие к границам, имели цвет, схожий с пограничными. При чем, если мы будем уменьшать мастштаб спрайта более чем в 2 раза, то нужно позаботиться об «окантовке» изображения шириной в несколько пикселей. Но как это сделать?
Самый простой способ, который я нашел — это создать второй слой в фотошопе, положить его под основной, размыть его blur'ом и выставить прозрачность в 1%. В результате, пиксели вокруг нашего изображения будут почти невидимыми (1% прозрачности), но гарантировано иметь цвет, схожий с пограничными. Конечно, эффект блюра подойдет не для каждого спрайта. Где-то можно создать 4 таких (1%) слоя, но не блюрить их, а просто сдвинуть в разные стороны…
В общем, надеюсь, кому-то эта информация окажется полезной.
Автор: soulburner