Недавно, ковыряя с целью исследования один чужой проект, наткнулся на весьма любопытную и в то же время — очень простую технологию. Сразу скажу, что ковырял я флэшку, но данная технология может быть использована не только во флэше, а вообще — где угодно.
Если коротко, то технология позволяет иметь одну отрендеренную анимацию и накладывать на нее разнообразные скины, тем самым получая внешне различные объекты.
Суть в том, что в изучаемой мной игре есть большое количество анимированных спрайтов человечков (как я изначально считал — заранее отрендеренных). Человечки разные (по-разному одетые, разных цветов и т.п.).
Но посмотрев ресурсы, я увидел очень интересную штуку. Я увидел странного вида отрендеренные картинки:
А также, различные текстуры такого вида:
С текстурой все понятно. Но что за ерунда на первой картинке? Логика подсказывала, что это — какого-то рода карта искажений текстуры. Сначала я думал про какие-то искривления и карту нормалей… Но потом в голову пришла простая идея — displacement map. Это когда в картинке зашифрованы координаты сдвигов. Например, в красном канале — сдвиг по «x», а в синем — по «y».
Раскидав ее по каналам, я получил это:
И практически сразу все понял. Сразу видно, что синий канал — это явно альфа-канал.
Посмотрев на зеленый канал и увидев на нем явный вертикальный градиент, стало очевидно, что в нем зашифрована y-координата. Ну, а красному не оставалось быть ничем иным, как иксом.
Поползав «пипеткой» по картинке, подозрения подтвердились еще и тем, что каждая и R и G компонент менялась в диапазоне 0..127, в то время как картинка текстуры как раз и была размером 128х128 пикселей.
Довольно быстро я набросал код, который делал следующее для каждого пикселя:
color = map.getPixel(x, y);
tX = color.R;
tY = color.G;
alpha = color.B;
textureColor = texture.getPixel(tX, tY);
dest.setPixel(x, y, textureColor, alpha);
В результате получил почти то, что вижу в исходном проекте. Текстурированные фазы анимации человечка:
Правда, механизм не совсем displacement (в случает дисплейсмента речь идет об относительных изменениях наложения текстуры). Здесь скорее нужно назвать просто «placement map». :)
Можно еще накидать алгоритм сглаживания и использования соседних точек на текстуре — и все будет вообще шоколадно.
Стоит отметить, что во флэше есть встроенный механизм DisplacementMapFilter, но он не подошел, т.к. он работает с относительными координатами (как, в прочем, и положено дисплейсменту). Т.е. в нашем случае он бы делал
textureColor = texture.getPixel(x+tX, y+tY);
Итого.
Мне очень понравилась технология. Она позволяет получить кучу разноскиновых объектов высокого качества не применяя технологий 3D рендеринга и при этом иметь простую смену этих самых скинов.
Уже планирую использовать это в своем проекте.
Вопрос.
Остается только вопрос — с помощью какого софта можно получить вот такие текстуры, и что самое главное — рендер подобных карт искажений???
Был бы очень признателен хабрасообществу, если бы кто-нибудь поделился Знанием.
P.S.
Уже после публикации, понял, как можно получить подобный рендер даже без каких-то специальных плагинов и т.п.:
- Берем нашу модельку, делаем UV-развертку.
- Заливаем текстуру UV-развертки специальным градиентом, где R-компонента будет соответствовать координате «x», а G — координате «y».
- Ставим B-компоненту по всей текстуре в максимум.
- Рендерим получившуюся вещь без учета света, отражений и т.п., на черном фоне.
PS: Про экспорт альфа-канала в синий цвет помог додумать хабраюзер xanep.