С текстурами вечно какие-то проблемы! То оказывается, что нельзя взять любую фотку и налепить на модельку. То на стыке текстур появляются швы, которые замучаешься заглаживать. То вроде уже и загладил всё, но глаз, этакий проказник, всё равно замечает повторяющиеся узоры и рушит иллюзию.
Можно сделать текстуру побольше, чтобы повторяющиеся куски дальше отстояли друг от друга и были не так заметны. Можно даже сделать её совсем огромной, на пару сотен тысяч пикселей, чтобы она накрывала всю сцену целиком без швов и повторений. Подобную технику называют мегатекстурой. Но мегатекстуры и близкие к ним виртуальные текстуры усложняют работу с памятью, для работы с ними требуются особые инструменты, да и в целом это ещё молодая технология.
Как же быть? Есть один трюк — непериодические мозаики. Они лишены проблемы повторяемости и достаточно просты в реализации. Одну из таких мозаик придумал математик Ван Хао. Элементы этой мозаики можно представить в виде прямоугольников с разноцветными гранями. Но чтобы понять принцип её работы, надо сначала разобраться в классическом методе заполнения площадей текстурами.
А классический метод таков: берем понравившуюся картинку, мостим ею небольшую площадь для теста и сразу видим все плохие пограничные места. После этого переделываем картинку так, чтобы правая сторона совпадала с левой, а верхняя с нижней. Готово, текстурой можно пользоваться.
Иными словами, нужно добиться того, чтобы горизонтальные и вертикальные края соседних текстур плавно перетекали друг в друга. Получается некий контейнер для картинки, который хорошо укладывается рядом с другими контейнерами.
Развиваем мысль дальше. Внутреннее наполнение контейнеров может быть каким угодно. Можно наделать много разных вариантов одной текстуры и мостить площадь случайными плитками из набора. Но как ни крути, даже при таком подходе остаётся повторяющаяся сетка от граней плитки. Следовательно, нужно придумать способ для перемешивания граней.
На самом деле, правая и левая сторона одной плитки не обязательно должны сочетаться друг с другом, главное, чтобы они сочетались с соседними плитками. Можно сделать несколько вариантов текстуры с разными краями и упаковать их в атлас. Затем, во время укладывания текстур, просто брать случайную плитку с краем, который подходит к соседним уложенным плиткам.
К сожалению, размер атласа для полного набора плиток очень быстро растёт с количеством вариаций граней. Расчёт ведётся по следующей формуле: N2*M2, где N — количество горизонтальных граней, M — количество вертикальных граней. Например, для двух вариантов на горизонталь и вертикаль выходит шестнадцать разных плиток. Если просто нужна гарантированная возможность продолжить мозаику, то формула будет попроще: 2*N*M.
Плитками из атласа можно замостить сколь угодно большое пространство. Берётся одна случайная плитка, сбоку к ней прикладывается вторая с подходящей гранью, ко второй плитке — третья, и так далее до конца ряда. При выборе плитки во втором ряду дополнительно учитываются соседи из первого ряда. На картинке выше слева изображён атлас, а справа мозаика.
Как создать атлас плиток? Можно взять одну большую картинку и наложить на неё сверху сетку из цветных граней. Затем выбрать подходящий шов для каждого цвета и размножить его по сетке. Либо пойти от обратного: сначала сделать сетку, потом заполнить пустые места. Ниже есть ссылки на более подробную инструкцию.
На иллюстрации сверху слева — простое повторение созданного атласа, справа — мозаика Вана, собранная из него. У получившейся мозаики нет заметных повторений, она выглядит случайной и текучей.
Разумеется, мозаика Вана не идеальна, у неё есть проблема с углами плиток. Мозаика решает проблему горизонталей и вертикалей, но остаются ещё диагонали, из-за которых на стыке четырёх плиток могут появляться артефакты. Зато эта мозаика проста и может использоваться не только для текстурирования, но и для процедурной генерации планов помещений или подземелий.
Я набросал нехитрый код на C# для Unity3d для работы с мозаикой Вана, можете посмотреть на него по ссылккам ниже.
Unity Web Player | Windows | Linux | Mac | Исходники на GitHub
Пробел — новая случайная текстура, 1, 2, 3 — выбор атласа, Esc — выход.
Для пользователей Linux: Сделайте файл WangTiles исполняемым с помощью «chmod +x WangTiles» и запускайте.
Полезные ссылки по теме:
Инструкция по созданию атласов
Процедурная генерация подземелий
Подробнее про создание атласов разных размеров
Автор: BasmanovDaniil