Стенограмма:

Minecraft, Spelunky, Civilization — что общего у всех этих игр? Это все игры с, казалось бы, безграничным количеством контента, и вы можете играть сотни часов, не повторяясь. Почему? Потому что во всех этих играх используется процедурная генерация — использование компьютерных алгоритмов для создания контента, который каждый раз разный, а не проектирование всего вручную. Процедурная генерация — это мощный инструмент, который при правильном использовании может превратить игру из хорошей в великолепную и заставить игроков возвращаться к ней снова и снова.

В сегодняшнем видео мы начнем изучение темы процедурной генерации с рассмотрения генерации 3D ландшафта — как это работает и для чего используется. Для этого мы фактически будем кодировать процедурно сгенерированный 3D-ландшафт полностью с нуля.

Чтобы сделать наш 3D-ландшафт, я буду использовать программу Processing, которая представляет собой среду программирования, позволяющую очень легко рисовать объекты на экране. Хотя я буду объяснять, что я делаю по мере продвижения, это не видео о том, как программировать в обработке, и моя цель здесь скорее продемонстрировать некоторые инструменты и методы, лежащие в основе создания 3D-ландшафта, а не пошаговое руководство. Без дальнейших церемоний, давайте начнем.

Начнем с настройки нашего проекта. Проекты обработки называются «эскизами», и каждый эскиз требует двух функций. Первая функция — это функция настройки, которая вызывается один раз при первом запуске нашей программы. Главное, что нам нужно сделать в функции настройки, это установить наш размер — это определяет, насколько большим будет наш экран. Мы также можем выбрать наш рендерер — поскольку это будет 3D-проект, я буду использовать P3D.

Вторая функция — это функция рисования, которая вызывается снова и снова. Давайте начнем с выбора случайного цвета фона, и я покажу вам, как выглядит наше окно.

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

Мой экран, как и большинство экранов, включая тот, на котором вы это смотрите, состоит из пикселей. Для этой демонстрации я собираюсь просмотреть каждый из этих пикселей один за другим и назначить ему случайный цвет между черным и белым. Когда я говорю «случайный», я имею в виду, что существует равная вероятность того, что любой пиксель будет иметь любое значение от черного до белого и всех промежуточных оттенков серого. Мне просто нужно перебрать горизонтальные пиксели, перебрать вертикальные пиксели и вуаля! Солено-перцевая буря. Я просто собираюсь установить «noLoop», чтобы мы могли посмотреть на это. Вот как выглядит случайность — все пиксели полностью отсоединены от всего остального вокруг. Случайность, как правило, НЕ то, что вам нужно для процедурной генерации.

Давайте посмотрим, что произойдет, если я заменю «случайную» функцию на «шумовую». Шум дает только значение от 0 до 1, а яркость изменяется от 0 до 255, поэтому давайте просто умножим наш шум на 255, чтобы получить полный диапазон яркости. Давайте взглянем. Мы получаем этот гораздо более структурированный, повторяющийся паттерн, чем раньше. Однако это все еще не то, что нам нужно — давайте немного «приблизим». Для этого я создам новую переменную под названием «инкремент», которая определяет, насколько быстро мы движемся сквозь шум. Я установлю это значение на 0,05 и использую его, чтобы умножить мои X и Y, и давайте посмотрим, что мы получим. Намного лучше! Хорошо, теперь, когда у нас есть на что посмотреть, давайте поговорим о функции шума.

Сначала поговорим о том, что такое шум. Шум — это в основном контролируемая случайность. Как вы можете видеть, цвета варьируются от черного до белого со всеми различными оттенками серого между ними, но это не так резко, как если бы оно было чисто случайным. Вместо этого он плавно переходит через различные оттенки. Конкретный тип шума, который Processing использует для своей функции шума, называется Perlin Noise, и если вам интересно узнать особенности того, как он работает, я бы порекомендовал Coding Train, в котором есть серия, в которой гораздо более подробно рассматривается, как это работает. работает. Однако для целей этого видео все, что нам действительно нужно знать, это то, что он создает своего рода плавную случайность, которая гораздо полезнее для процедурно сгенерированного ландшафта, текстур и т. д.

Еще одна приятная особенность шума заключается в том, что он повторяем. Шум основан на специальном числе, называемом начальным числом — разные начальные значения дадут вам разные модели шума, но использование одного и того же начального значения каждый раз будет давать один и тот же результат. Давайте установим наше семя на что-нибудь хорошее — 10052014.

Существует множество различных алгоритмов шума, которые можно использовать в зависимости от того, какой вид вы хотите получить, но для этого видео мы собираемся придерживаться шума Перлина. При этом одним из других основных преимуществ алгоритмов шума является то, что они легко настраиваются. Мы уже показали, что происходит, когда вы увеличиваете шум Перлина, но есть много других вещей, которые мы можем сделать, чтобы изменить его внешний вид. Например, мы можем изменить уровень детализации нашего шума с помощью функции NoiseDetail(). Эта функция принимает два числа — первое определяет, сколько слоев шума Перлина мы хотим сгенерировать, а второе определяет, как слои складываются вместе. Чем больше слоев шума мы добавляем, тем «жестче» получается результат. По умолчанию 4 слоя — давайте посмотрим, что произойдет, если мы уменьшим его до одного.

Результат выглядит намного более гладким — он почти выглядит размытым. Теперь давайте попробуем провернуть его до 8 и посмотреть, что произойдет. Теперь у него гораздо больше мелких, грубых деталей. Для наших целей давайте используем 3 слоя. Есть много других способов, которыми мы можем поиграть с результатами, но мы рассмотрим их подробнее после того, как заработаем наш ландшафт. В конце концов, все, что у нас есть на самом деле, — это какие-то нечеткие формы в 2D, что далеко от 3D-ландшафта. Верно, но что, если вместо того, чтобы использовать шум для получения цветов, мы использовали его для получения значения высоты? 2D-изображение, используемое для создания 3D-поверхности, называется картой высот, а карты высот уже несколько десятилетий используются для создания 3D-ландшафта.

Итак, давайте быстро изменим наш проект, чтобы превратить нашу поверхность в карту высот. Первое, что нам нужно сделать, это создать плоскую сетку. Все виртуальные 3D-объекты состоят из сеток, которые в основном представляют собой точки, ребра и треугольники, составляющие объект. Все сетки в основном состоят из треугольников, потому что треугольники — самая простая форма, поэтому для нашей сетки нам сначала нужно создать группу треугольников. Для этого я создам то, что Processing называет «треугольной полосой», и я просто создам набор строк и столбцов треугольников.

Для этого я создам коэффициент масштабирования, который в основном определяет, насколько большими будут наши треугольники. Затем я буду использовать этот масштабный коэффициент, чтобы определить, сколько строк и столбцов нам нужно — мы хотим заполнить весь экран, поэтому я просто возьму ширину и высоту, разделенные на масштаб, и это даст нам количество строк и столбцы. Теперь вместо того, чтобы перебирать пиксели на экране, мне просто нужно прокручивать строки и столбцы и создавать треугольную полосу по ходу дела. Давайте посмотрим на это. Фантастика — теперь у нас есть очень регулярная сетка точек, которую мы можем использовать для создания нашего ландшафта. Прямо сейчас каждая из наших точек имеет одинаковое значение высоты 1 — следующий шаг — изменить значение z на основе нашей функции шума.

Для каждой точки нам просто нужно получить значение шума наших координат X и Y, умноженное на переменную приращения, которую мы создали ранее. Помните, что шум дает нам значение только между 0 и 1 — это совсем не изменит нашу высоту, поэтому давайте умножим это на большое значение — 200. Теперь мы используем эти переменные для нашей высоты и получим кое-что гораздо более интересное. . На самом деле это уже наша трехмерная местность, но ее сложно сказать, потому что мы в основном смотрим на нее сверху. Возможно, было бы легче увидеть, что происходит, если бы мы наклонили его и вместо этого посмотрели на него сбоку.

Для этого все, что нам нужно сделать, это добавить несколько быстрых строк кода — мы сначала сдвинем изображение немного вниз, а затем повернем его на 60 градусов. Поздравляем — у нас есть 3D пейзаж! И это заняло всего несколько минут и пару строк кода. Однако мы еще не закончили. Теперь, когда у нас есть готовый ландшафт, я собираюсь немного схитрить и добавить немного кода из проекта, который я подготовил ранее. Это поможет продемонстрировать проблему с нашим ландшафтом.

Хорошо, я вернулся, и я в основном сделал 2 вещи для своего проекта. Во-первых, добавьте немного цвета — я изменил цвет фона, чтобы он выглядел как небо, и изменил цвет каждой точки в зависимости от ее высоты. Эта часть была довольно простой — все, что мне нужно было сделать, это проверить, насколько высоко находится точка, и назначить ей цвет.

Второе, что я сделал, это добавил код, который позволяет мне «летать» в нашем виртуальном пространстве. Этот код в основном проверяет, нажимаю ли я клавишу со стрелкой, и обновляет смещение в направлении x или y, которое перемещает нас в пространстве. Давайте немного осмотримся, хорошо?

Не наполовину плохо! Тем не менее, это подчеркивает проблему простой генерации ландшафта на основе шума. Конечно, это довольно убедительная горная местность, но поскольку все использует одну и ту же функцию шума, все в мире будет выглядеть вот так. Кроме того, как мы видели при уменьшении масштаба, функция шума в конечном итоге будет повторяться, а это означает, что наш мир будет просто бесконечно повторяющимся набором одинаковых гор. Я думаю, мы можем добиться большего.

Один из способов добавить больше разнообразия в наши виртуальные ландшафты — это иметь несколько разных «шумов», которые контролируют разные аспекты мира. Одно значение шума может управлять смещением поверхности, а другое — такими вещами, как температура. Давайте продолжим и добавим второе значение шума, которое определяет, какой тип ландшафта мы будем создавать. В частности, если этот второй шум имеет высокое значение, у нас будет неровная гористая местность, но если значение низкое, у нас будет более плоский ландшафт с более пологими холмами.

Для этого мы добавим к нашему шуму третье измерение по оси Z. До сих пор наш шум был двухмерным, но на самом деле шум может быть трехмерным, четырехмерным или любым другим. Наш старый шум будет использовать значение Z, равное 0, а наш необходимый шум будет использовать значение Z, равное 10. Кроме того, хотя используемое нами приращение подходит для отдельных гор, мы хотим, чтобы наши различные ландшафты были больше, поэтому я собирается создать второй, меньший шаг. Я также отключу текущий цвет, чтобы мы могли лучше видеть местность.

Теперь, когда мы двигаемся, вы можете видеть, что по мере того, как земля становится темнее, она также становится более плоской, а по мере того, как становится светлее, она становится более холмистой. Это все еще не очень впечатляет — в конце концов, это просто разная высота холмов, но вы можете использовать эту технику для определения таких вещей, как растительность, количество осадков и много других вещей. Кроме того, поскольку теперь у нас есть два разных вида шума, наложенных друг на друга, повторение паттерна займет гораздо больше времени. Добавляя все больше и больше слоев шума, вы можете создавать еще более разнообразные ландшафты, причем бесконечные. Разнообразие.

Есть еще один последний прием, который я хочу показать вам, а затем я хочу обсудить некоторые слабые стороны этого подхода. До этого момента мы в основном использовали значения шума как есть, но, изменяя сами значения, вы можете получить гораздо более интересные результаты. Один простой пример, который я хочу показать, — это использование абсолютного значения шума вместо самого шума. Для этого нам нужно удвоить диапазон нашего шума, чтобы он охватывал от -1 до 1, а не только от 0 до 1. Я просто умножу наш шум на 2, а затем вычту 1, чтобы получить этот диапазон. Затем нам просто нужно взять абсолютное значение нашего нового числа. Я также собираюсь добавить цвет обратно.

Давайте просто быстро напомним себе, как выглядел наш мир раньше. Теперь давайте посмотрим, что мы можем сделать с помощью небольшого количества математики. Теперь у нас есть эти острые пики и долины с реками и озерами между ними. Это вызвано переходом между положительными и отрицательными числами — поскольку мы используем функцию абсолютного значения, это создает «складку» всякий раз, когда значение пересекает 0, что создает острые долины, которые мы видим здесь. И это только один из многих различных эффектов, которые вы можете получить, возясь с вашей функцией шума. Изменяя уровень детализации шума, увеличивая и уменьшая масштаб, накладывая разные шумы друг на друга и применяя к шуму различные математические функции, вы можете создать бесконечное количество различных эффектов.

Однако эта техника имеет некоторые ограничения. Поскольку вы просто регулируете высоту вашего ландшафта, вы не можете получить такие вещи, как выступы, пещеры и тому подобное. Однако есть способы обойти это. В основном мы имели дело с 2-мерным шумом, но можно создать пейзаж и с использованием 3-мерного шума, который позволяет использовать такие детали. Однако написание кода для рендеринга 3D-шума займет намного больше времени, чем это видео.

Второй способ обойти это — сгенерировать карту высот, превратить ее в сетку, а затем добавить отдельный «проход» для добавления трехмерных деталей. Этот второй проход можно использовать для удаления частей вашей сетки для пещер и выступов или даже для добавления к ней таких вещей, как естественные арки.

До скорого!

В этой теме есть о чем еще поговорить, но я думаю, что этого достаточно для этого видео. Если вам понравилось это видео, не забудьте поставить лайк и подписаться, чтобы не пропустить будущие видео о генерации ландшафта. Если вы нашли это видео интересным, посмотрите другие видео на моем канале — я освещаю широкий круг тем в области дизайна и разработки игр. Вы также можете проверить блог RemptonGames, где у меня есть более 150 статей по ссылке в описании ниже. И присоединяйтесь ко мне на следующей неделе, где мы будем применять то, что узнали сегодня, чтобы исследовать, как Minecraft генерирует свой ландшафт! А пока, большое спасибо за просмотр, и увидимся в следующий раз.

Первоначально опубликовано на https://remptongames.com 31 января 2021 г.