Введение.


Для начала, немного справки:

  • что такое ландшафт (terrain), можно посмотреть тут;
  • что же до игр (грубо говоря) — то в них terrain — это объект (как правило, плоскость, с довольно плотным разрешением полигональной сетки), который способен выстраивать свою геометрию в соответствие с определённым изображением (heightmap), а также окрашиваемый определённым заданным набором текстурных карт и карт весов (splatmaps), это в классическом понимании: воксельные ландшафты, увы, мы пока рассматривать не будем;
  • как обстоят дела с ландшафтом в движке Unity3d — можно посмотреть тут, опять же — стандартный ландшафтный движок в Unity3d — не воксельный.

Итак, передо мной встала задача — создать довольно большой участок ландшафта, достаточно похожего на настоящий, достаточно хорошо выглядящий и приблизительно соответствующий заданному наброску:

первый набросок ландшафта

первый набросок ландшафта

Разбор задачи.


Выбор программного обеспечения.


Честно говоря, даже не смотря на то, что движок Unity3d и предлагает нам набор инструментов для создания и редактирования ландшафта, оперировать этими средствами — себя не уважать. Тем более, если необходим ландшафт хоть в какой-то степени похожий на реальный.

В итоге, поскитавшись по сети, выбор свой мы уронили на WorldMachine, из-за её не слишком кусачей цены, довольно мощного функционала (особенно при такой цене) и того факта, что нашему художнику (т.е. мне) сильно понравился её интерфейс.

Определение рабочего процесса.


Как было сказано, участок ландшафта должен быть довольно большой, а это значит, что одним объектом в Unity3d это сделать не получится, в силу того, что не хватит максимального разрешения управляющих карт (высоты, веса) — их максимум — 4096×4096 (для высот ещё +1 пиксель). Следовательно, ландшафт нам нужен составной — из нескольких стыкующихся фрагментов. К счастью, WorldMachine pro такую возможность нам предоставляет. Было принято решение — создать ландшафт из 16 фрагментов — 4 в длину и 4 в ширину. В WM есть прекрасная опция Tiled Build, которое сама всё собирает.

Примечание: будьте внимательны — в режиме Tiled Build недоступен инструмент Flipper, который позволяет перевернуть изображение либо по вертикали, либо по горизонтали. При учёте того факта, что после экспорта в Unity ландшафт получается перевёрнутым по одной оси, необходимо иметь это в виду. Есть работающий инструмент Inverter, но он инвертирует ландшафт сразу по обеим осям (если быть точнее — он просто инвертирует цвет пикселя на карте высот).

На ландшафте должно присутствовать:

  • равнинные местности;
  • горные местности;
  • плоскогорья;
  • реки;
  • озёра;
  • море;
  • пара островов.

Приступаем к веселью. Подготовка формы.


Принцип работы с ландшафтами в WorldMachine основан на графах, а это означает, что в конце получается вот такой страх:

страх

страх

Ну что, давайте разбирать, что за что там отвечает (пойдём слева направо). Сразу предупрежу, что сильно расписывать настроек всех узлов (или устройств, как их называет сама WM, но мне привычнее называть их узлами) не буду — в конце данной записи будет лежать исходный проект ландшафта (бесплатная версия программы без проблем его прочитает).

Генерация гор.


За генерацию высоких гор отвечает следующий участок графа:

генерация высоких гор.

генерация высоких гор, граф

Основной узел здесь, определяющий форму — Advanced Perlin, ко входу Distortion Guide которого подключен ещё один генератор — Voronoi — он задаёт небольшое искривление формы наших гор. Далее следует узел Simple Transform, усиливающий разницу в высотах (участвует только его параметр Glaciate, установленный приблизительно на 75%). Результат работы этого набора узлов выглядит следующим образом:

генерация высоких гор, результат

генерация высоких гор, результат

Создание участков с плоскогорьями.


Следующий блок узлов генерирует плоскогорья и смешивает их с результатом работы предыдущего:

плоскогорья, граф

генерация плоскогорий, граф

Опять же, самый важный здесь узел — Advanced Perlin, создающий следующее:

генерация плоскогорий, результат узла Advanced Perlin

генерация плоскогорий, результат узла Advanced Perlin

Далее, с помощью узла Select Height выбираем низины с предыдущего этапа используем эту выборку как маску для узла Chooser (принцип работы будет описан чуть ниже), который смешивает результат предыдущей группы узлов с результатом генератора Advanced Perlin текущей группы. Затем результат подаётся на вход Erosion — данный узел симулирует воздействие на ландшафт погодных факторов. На выходе получается следующее:

генерация плоскогорий, результат

генерация плоскогорий, результат

Генерация равнинной местности.


Следующая группа узлов создаёт равнинную местность:

генерация равнинной местности, граф

генерация равнинной местности, граф

Происходит здесь следующее: всё тот же Advanced Perlin в режиме Billowy скармливается Erosion, которая немного его смягчает. Далее всё ещё смягчяется с помощью Blur (совсем незначительно), добавляется регулярный шум (Add Noise), и окончательный сигнал корректируется узлом Curves, который работает также, как и Curves в Photoshop, например. Результат этой цепочки выглядит следующим образом:

генерация равнинной местности, результат

генерация равнинной местности, результат

Генерация морского дна.


Здесь немного, а именно — один единственный узел Advanced Perlin, который настроен на следующий результат:

морское дно, результат

морское дно, результат

Подготовка масок для гор и моря.


Итак, мы имеем горную, равнинную местность и морское дно — пора это дело смешивать. Но для этого необходимо подготовить управляющие маски. Их на данном этапе будет две:

layouts, граф

layouts, граф

Layout Generator — особый узел, позволяющий пользователю создавать области с помощью многогранников и линии произвольной формы. У каждой фигуры/линии можно настроить высоту, область затухания, а также кривизну на каждой вершине. Но я использовал Blur, потому что очень ленивый и не хотел тратить время на настройку каждой вершины в каждой форме. Получившиеся маски выглядят следующим образом:

  • для гор:

    маска для гор

    маска для гор

  • для моря:

    маска для моря

    маска для моря

Смешивание.


Наконец-то. Начинаем совмещать всё то, что до этого создали. В плане самого графа тут ничего сложного нет — всего лишь два узла:

смешивание, граф

смешивание, граф

Теперь по порядку. Узел Chooser — выбирает сигнал между входом A и входом B по входу C (порядок выбора можно инвертировать). Первый Chooser — выбирает между нашими горами (на изображении — вход B) и равнинами (вход A) по первой маске с предыдущего пункта (вход C). Результат:

смешивание, этап 1

смешивание, этап 1

Второй Chooser — выбирает между выходом первого (подан на вход A) и морским дном (вход B) по второй маске с предыдущего пункта (вход C). Результат второго Chooser, он же и результат всего смешивания:

смешивание, этап 2

смешивание, этап 2

Прорезание рек и озёр.


Как было видно выше — Layout Generator использовался без входных значений, что давало нам набор форм на однородном нулевом (0 по высоте) фоне. Сейчас же Layout Generator будет использоваться следующим образом:

Layout Generator для рек/озёр

Layout Generator для рек/озёр

На вход этому узлу подан результат предыдущего этапа. В таком режиме Layout Generator способен изменять форму входного ландшафта, что и будет использоваться для рек и озёр.

Примечание: адекватного инструментария для создания рек и озёр в World Machine, увы, нет, поэтому вместо него используем всё те же кривые и формы, но с включенным фрактальным разбросом (Fractal Breakup), задающим случайное искривление фигурам.

Итак, наши формы для рек и озёр выглядят следующим образом:

реки/озёра, формы

реки/озёра, формы

Финальная эрозия.


Заключительный этап подготовки формы ландшафта, состоит всего из двух узлов:

эрозия, граф

эрозия, граф

Здесь участвует обычная эрозия (Erosion) и береговая (Coast Erosion), которая симулирует размывание рельефа под воздействием моря. Первому узлу Erosion скармливается выход предыдущего Layout Generator, настройки этого узла чуть более агрессивные, нежели у Erosion на этапе генерации равнинной местности. Затем полученный результат отправляется на вход Coast Erosion. Обращаем внимание на то, что на вход этому узлу приходит ещё кое-что (нижний вход фиолетового цвета — так обозначается вход маски), а именно та самая маска для моря. Тот факт, что с обоих узлов выходят по два результата, будет объяснён далее. Результат эрозии:

эрозия, результат

эрозия, результат

Раскраска ландшафта.


И вот, мы подобрались к сердцу чудовища. С этой точки начинается работа, по времени и сложности превосходящая все предыдущие пункты — раскраска. А точнее — выборка масок под каждую текстуру (коих всего шесть). Здесь рассказ пойдёт сразу о нескольких группах узлов. Первая из них:

входные данные текстур, граф

входные данные текстур, граф

Данный набор узлов File Input загружает в проект следующие текстуры:

 

Гравий, песок, скалы, тёмная трава, яркая трава и склон. Теперь необходимо для каждой текстуры определить маску. Происходит это в следующей группе узлов:

формирование карт весов, граф

формирование карт весов, граф

Давайте разбираться. Начнём, пожалуй, с того большого прямоугольника справа, похожего на процессор. Сей узел зовётся Splat Converter, и занимается он тем, что принимает в себя несколько входов (до 16) и отдаёт столько же выходов, только особым способом урегулированных так, чтобы не возникало перекрытий друг другом (не знаю, как объяснить это понятнее, когда начнёте работать с ландшафтом в игровом движке — станет яснее). Почему в узле 8 входов, а текстур всего 6? А потому, что одна карта весов — это обычное изображение на 4 канала (красный, синий, зелёный и альфа), а 6 текстур не описать с помощью четырёх каналов — поэтому используем два таких изображения по 4 канала — итого 8. Можно заметить, что на изображении с графом есть узел, именуемый Zero height (Constant) — он генерирует нулевой сигнал (т.е. сигнал с нулевой высотой) и отдаёт его как раз в те два входа Splat Converter, которые нам не понадобятся. Также, узлы Erosion и Coast Erosion помимо основного выхода дополнительно возвращают несколько полезных карт, которые будут активно использоваться далее (такие карты, как карта потоков грунта или карта пляжа и подобные). Теперь пойдём по текстурам.

Песок.


маска для песка, граф

маска для песка, граф

В первый Combiner на вход приходят Beach Map из узла Coast Erosion группы финальной эрозии и маска для морского дна, второму — результат первого и, внимание, второй выход узла Layout Generator с этапа создания рек и озёр. Второй выход этого узла называется Shape Mask и представляет собой только следы воздействия на входной ландшафт (в данном случае — это как раз маска рек и озёр). Оба узла установлены в режим суммы (Add).

Гравий.


маска для гравия, граф

маска для гравия, граф

Первый узел здесь — Select Convexity, который выбирает наиболее выпуклые участки ландшафта. На вход ему приходит результат узла Coast Erosion. Далее следует размытие и Combiner в режиме вычитания (Substract). На второй вход ему подаётся инвертированная маска для гор (в режиме вычитания Combiner вычитает из первого входа второй). Затем его результат отправляется в ещё один Combiner в режиме складывания, на второй вход которого приходит Flow map с узла Erosion с этапа финальной эрозии. Затем его результат отправляется в ещё один Combiner в режиме вычитания, где от него отнимается маска для песка, описанная выше.

Склоны.


маска склонов, граф

маска склонов, граф

Тут не очень много. Узел Select Slope промышляет тем, что формирует с входного ландшафта маску, отображающую склоны под заданным диапазоном градусов. На вход идёт результат финальной эрозии. Затем из этой маски просто вычитается маска для песка, описанная выше.

Скалы.


маска для скал, граф

маска для скал, граф

Узел Select Height — если знаем английский, то несложно догадаться, что данный узел выбирает нам высоту. Также ему можно указать разброс этой выборки. На вход узлу скармливается результат финальной эрозии, а в слот для маски приходит маска для гор с этапа подготовки масок. Далее из этой выборки вычитается результат генератора Perlin Noise — он необходим просто для внесения неоднородности.

Тёмная трава.


маска для тёмной травы, граф

маска для тёмной травы, граф

В узел Inverter (да, для инверсии) приходит результат узла Select Height с предыдущего этапа (маска для скал), а затем — отправляется в качестве маски в узел Perlin Noise. Для тёмной травы — это всё.

Светлая трава.


маска для яркой травы, граф

маска для яркой травы, граф

Здесь маска для тёмной травы приходит в Inverter и далее в Combiner, где из неё вычитается маска для гор (с этапа подготовки масок), при этом в слот маски в сам Combiner приходит тот самый Perlin Noise с этапа формирования маски для текстуры скал. Слишком много слов «маска», но ничего не поделать. Далее — ещё один Combiner, который прибавляет к предыдущему Flow map с узла Erosion этапа финальной эрозии, и ещё один Combiner, который из предыдущего вычитает маску для текстуры песка.

Сборка текстур.


раскраска ландшафта, граф

раскраска ландшафта, граф

Извиняюсь за столь вульгарное название данной группы узлов — к этому моменту я подходил, пребывая в состоянии кочана капусты или садовой лопаты, уже плохо вспоминается. Итак, что тут творится: узел Zero color (Color Generator) формирует нам простой чёрный цвет и является подложкой для всего остального, своего рода ключ зажигания (на самом деле, цвет может быть любым). Что делает Chooser, уже рассказывалось, поэтому просто скажу, что в эти узлы в качестве второго входа поочерёдно подаются текстуры, а в качестве третьего — ранее созданные маски для них — в следующем порядке:

  • тёмная трава;
  • светлая трава;
  • скалы;
  • склоны;
  • песок;
  • гравий.

Куда отправляется результат шестого узла Chooser — смотрим ниже.

Финишная прямая.


Итак, мы почти у цели — осталось собрать выходные данные проекта:

вывод, граф

вывод, граф

Узел Overlay View — просмотр данных ландшафта, полученных на этапе финальной эрозии, и совмещённых с ними данными текстур с этапа раскраски. Данный узел никуда дальше WorldMachine не уходит и являет собой просто что-то вроде итогового предпросмотра. Два узла Bitmap Output — выводят из проекта данные по картам весов (RGBA-изображения). первый вход узла — RGB-данные, второй — опциональный альфа-канал, узлы Channel Combiner собирают по три монохромных входа (которые идут с Splat Converter) в те самые RGB-данные. Узел Height Output выводит из проекта карту высот получившегося ландшафта (он же — результат финальной эрозии). Итак, что мы имеем на выходе:

финальный результат, 3D-просмотр

финальный результат, 3D-просмотр

финальный результат, плоский рендер

финальный результат, плоский рендер

Новый двигатель и покраска! И полиция не узнает Вас!

Послесловие.


Ну вот и подошло к концу моё сражение с WorldMachine. Не знаю, кто из нас победил — я всего лишь поделился тем опытом, который набирал в течение примерно полугода. Надеюсь, кому-нибудь этот опыт поможет. Как и обещал — предоставляю Вам исходный проект с описанным выше ландшафтом (на момент создания, версия WM была 2.3.7) — truckers_terrain

Благодарю за внимание.

Filed under:

JUMP TO TOP
SHARE THIS POST
Apologies, for this post the comments are closed.
512 Studio
TAKING TOO LONG?
CLICK/TAP HERE TO CLOSE LOADING SCREEN.