Vlad Ivanov

Карта, Ландшафт, Тени,
Level Design - Часть 1
На данной странице я расскажу о создании оптимизированной
безграничной и живой карты
...
Карта, как основа левел дизайна
Основа левел дизана - карта, ландшафт с размещенными на нем объектами, на основе которого создается атмосфера окружения и происходят все события. Карта в нашем Игровом Мире отличается двумя особенностями - она живая и она безгранична!
Живая карта
имеет четыре свойства:
1 - карта живет своей бурной жизнью, даже во время отсутствия игрока. Все события происходят не только локально вокруг игрока, а в 99% случаев вне его локации.
2 - Нелинейность и незаскриптовасть событийной логики. События, происходящие с игроком, когда он заходит а данную локацию, происходят с ним незапланированно (незаскриптованно), не по щелчку триггера, а по тому, что они должны были произойти, даже если бы игрок не пришел.
3 - развитие событий во времени. Например: если вы построили дом на одном конце карты и поехали на другой конец добывать ресурсы, то зайдя через пару дней на сервер и вернувшись на свою локацию, вы застанете свой дом, который подвергся ветшанию, а возможно захвату рейдеров.
4 - игрок вносит свой вклад в изменения карты. Допустим: наш Игровой Мир - это Battlefield. Вы участвуете в операции по захвату большой области на карте, эта операция длится несколько дней. Вы являетесь участником группы, тактическая задача которой - взорвать стратегически важный мост, тем самым изменить ход сражения крупных подразделений. Если в один из дней вы зашли на сервер и выполнили эту задачу, то остальные дни вы будете жить с пониманием того, что стратегическая карта военных действий на целом государстве выглядит так именно благодаря вам.
Безграничная карта
Безграничная - это значит, что карта реально на столько огромна, что игрок, занимаясь своими делами на одной из локаций, даже не представляет, что происходит на другом конце карты и как это место вообще выглядит.
К нашей безграничной карте применяется два условия:
  • она должна быть действительно безграничной, т.е. ее размер в квадратных игровых километрах должен соответствовать пониманию игрока того, что карту невозможно пробежать насквозь за раз и это вызывает чувство неизведанного и стимулирует дух исследователя.
  • карта, при всей своей "огромности", должна наименьшим образом нагружать компьютер. Минимальная нагрузка на видеокарту за счет пререндера, системы лодов и других механик, исключающих просчет визуализации в реальном времени. Минимальная нагрузка на процессор и оперативную память за счет небольшого количества низкополигональных повторяющихся модульных объетов.
Итак: наша карта стоит на трех китах:

  • 01 “Модульноть прокси-объектов”
  • 02 “Система привязок Пиксель-Вертекс”
  • 03 “Многоадресность одного объекта” "DoSi_Multy_Visa"
“Модульноть прокси-объектов”
Прокси — это заменитель реального объекта, у которого есть право выступать от имени и в интересах этого объекта. Прокси-объект ссылается на другой объект-оригинал, обладающий определенными свойствами, при этом способен изменять свойства объекта, на который ссылается.

Наша карта состоит из квадратных кусков ландшафта, плотно прилегающих друг к другу, соединенных по пронципу “Пазла”.
Как мы видим, звенья пазла плотно соединяются в единый пазл, образуя “Замки” в местах соединения и если замки не совпадут - звенья не соединятся. Так и куски нашей карты смогут соединиться, если их замки совпадут.
Рельефные замки
Допустим, вот наша двухуровневая карта, состоящая из 9-ти квадратов. Одни из них являются плоскими поверхностями первого (нижнего) уровня №5, другие - плоские поверхности второго (верхнего) уровня №1, а третьи - вляется переходными соединителями между первыми и вторыми уровнями №2-3-4.
Причем, как и в пазле, зеленый квадрат сможет соединиться только если своим левым краем примкнет к правому краю синего квадрата, образуя замок изгибами рельефа.
“Рельефные замки” - на стыках они неизменны и совпадают, не образовывая стыков, внутри же квадрата может быть любой скульптинг поверхности.

Причем, как и в пазле, зеленый квадрат сможет соединиться только если своим левым краем примкнет к правому краю синего квадрата, образуя замок изгибами рельефа.
Прокси-объект (далее мы будем называть его “Подставной Объект”) ссылается на другой объект-оригинал, обладающий определенными свойствами, демонстрирует себя от имени этого объекта, при этом способен изменять свойства объекта, на который ссылается.
В нашем случае прокси-объект будет заменять во время подстановки следуюшие свойства объекта-оригинала:
  • Текстура нанесенная на поверхность
  • Скульптинг рельефа
  • Какие объекты-локации будут размещены на каждом участке кластера
  • В каких порталах в данный кластер будут заходить и выходить дороги
На рисунке ниже наш двухуровневый квадрат, он состоит из 9-ти кластеров. Сейчас вместо пустого черного пятого кластера мы подставим прокси-объект, ссылающийся на смоделированный кластер.
Наш пятый кластер объект-оригинал имеет главное свойство (он является внутренним углом склона рельефа, соединяющим нижний и верхний уровни). Также наш пятый кластер имеет второстипенные свойства (скульптинг рельефа, порталы где входит и выходит дорога, размещение объектов на участках кластера, текстура рельефа). Эти второстепенные свойства и будет менять Подставной прокси-объект, тусовать их рандомно во время генерации карты.
Если рассмотреть наш пятый кластер отдельно, он тоже подразделяется на 9 квадратов (локаций). То, какие объекты будут стоять на каком квадрате и какая текстура и скульптинг будет у поверхности, все это второстепенные свойства объекта-оригинала, которые будут изменяться прокси-объектом при генерации карты.

Допустим наш пятый кластер имеет Тип рельефа "Внутренний угол склона", то есть он соединяет нижний и верхний уровень карты п представляет собой угол. Такой объект в нашей базе данных один и подставляя его несколько десятков раз, формируя наш ландшафт, мы не будем нагружать память и процессор.
На рисунке ниже слева показана сетка нашего кластера. Там есть шестой синий участок.

Допустим у нашего кластера есть три варианта объектов, размешенных на шестом участке (домик, мельница, замок) и три варианта текстур ландшафта. При формировании карты один из этих вариантов подставляется рандомно.
Теперь вид нашего кластера будет зависеть от того, какой объект наш Proxy подставит на 6-й участок.
При этом каждый объект, размещенный на шестом участке (например домик с деревом) существует в четырех вариантах (повернутый на север, юг, запад, восток). Это дает вариативность и делает нашу карту на порядок разнообразнее.

Наша локация состоит из домика, дерева и камня. В первом варианте локация повернута так, что камень смотрит на запад, во второй на север и т.д.
При этом каждый объект, размещенный на шестом участке (например домик с деревом) существует в четырех вариантах (повернутый на север, юг, запад, восток). Это дает вариативность и делает нашу карту на порядок разнообразнее.

Наша локация состоит из домика, дерева и камня. В первом варианте локация повернута так, что камень смотрит на запад, во второй на север и т.д.
Для того, чтобы локация не нагружала систему, все тени запекаются. Затененные стен дома запекаются на текстуру дома. Тени на камне и заборе запекаются на текстурах этих объектов. Тень на земле не запекается на текстуре земли, а ложится поверх карты цвета поверхности земли (diffuse map) дополнительным слоем shadow map.
Система генерации теней

Как известно, при визуализации освещения в сцене, в процессе трассировки, луч выпущенный из камеры, ударяется в определенный полигон объекта и отражаясь (в соответствии с нормалью этого полигона) улетает в определенный участок небесной сферы. И если на пути к небу луч не встретит преград, то диффузная текстура этого полигона будет подсвечена определенным образом. Если же на пути к небу луч встретит преграду в виде полигона другого объекта, то он будет затемнен. Примерно как Ambient occlusion. Таким образом в реальном времени ведется обсчет и геометрии полигона, в который направлен луч и геометрии полигона-преграды, в который луч ударяется при отражении.
Поэтому на спине человека, стоящего под деревом виден детальный рисунок тени от дерева (вплоть до отдельного листочка). И эта детальная тень смещается, в зависимости от передвижения человека. И все это время идет обсчет тысяч полигонов (отражающих и затеняющих).
Это очень ресурсозатратная система генерации динамических теней.
В нашем Игровом Мире нет просчета этих сотен и тысяч полигонов, при создании системы освещении в сцене для каждого объекта создается так называемая теневая фигура "shadow mesh".

Допустим солнце на нашей карте - это прожектор в кинотеатре, проходя через подвешенный в кинозале предмет (например дом), свет проецирует на экран силуэт. С точки зрения прожектора - это двухмерная фигура.
Применяем к ней 3D-выдавливание (extrude) в направлении солнечного света, до пересечения с поверхностью земли и мы получим нашу 3D теневую фигуру "shadow mesh". Попадая в такой теневой объем объект (например розовый куб) становится затененным, то есть не отдельные точки текстуры объекта, а цельные полигоны, погруженные в теневой объем становятся затемненными.
На рисунке ниже около дома находятся три солдата, самый правый из них находится прямо у стены дома. Этот солдат - это динамический объект, но он полностью погружен в теневой меш, поэтому каждый тик, при рендере сцены его модель не подвергается постобработке, просто все его текстуры затемняются на определенное значение.
Второй солдат по центру частично погружен в теневой меш, срез тени прошел по его талии, поэтому полигоны ниже среза затеняются, а выше нет. Никаких отраженных лучей и просчетов объектов-приград. Просто нижняя часть солдата попала в теневую окклюзию и была затемнена.
Чтобы отрисовать нашего полузатененного содлата каждый тик (игровой момент, отведенный на отрисовку кадра) из глаза игрока (камеры) вылетают несколько лучей, часть из них (зеленый луч) попадают на руки солдата не погруженные в теневой меш, при этом луч не летит дальше отражаясь от поверхности руки, он останавливается, получая сигнал, что все полигоны рук, плеч и головы не нужно затенять.
Другие лучи (красный луч) поподают на ноги, погруженные в тень, дают сигнал о затемнении. На большом расстоянии генерация теней будет работать не с отдельными полигонами солдата, а с целыми частями модели (кисть, предплечие и т.д.), тем самым еще более разгружая видеокарту.
Что касается травы - здесь интереснее. В современных играх большие площади травы на ландшафте нагружают железо и отключение травы в визуальных настройках повышает производительность. Понятно, что есть дальность прорисовки и процедурная генерация травы в определенном радиусе.
Но мы решаем вопрос кардинально! Об этом чуть ниже.
Наша трава это particle system, которая размножает определенный объект (по типу hair в blender) с определенными условиями для этого объекта.
Размножаемым объектом может быть 3D-многополигональный объект пучок травы.
Размножаемым объектом может быть спрайт с прозрачностью по Alpha-каналу и этот спрайт своей нормалью всегда повернут к игроку. При движении игрока спрайт вращается, поворачиваясь к нему нормалью, что создает эффект лода.
Предположим, создавая наш ландшафт мы размножаем 3D-многополигональный объект пучок травы, получая целые поляны. Мы используем particle system и у каждого нашего пучка травы есть центр вращение (origin), он находится в центре пучка снизу в месте прилегания к земле.

Есть два варианта генерации теней на траве:
1.. Трассировка лучей. Каждая травинка подвергается постобработке, от каждого полигона отражается луч и т.д., что говорилось выше. Это очень нагружает систему.
2.. Привязка origin-вертекса к карте теней. Давайте посмотрим на картинку ниже. Представим, что дома, дерева и камня в сцене нет, а тени от них есть и это отдельная текстура. Эта текстура ложится отдельным слоем поверх diffuse map нашей земли. Здесь начинает работать “Система привязок Пиксель-Вертекс. То есть объекты касаются своими origin-вертексами земли, на которую нанесена текстура теней, состоящую из черных и белых пикселей. И в том месте, где origin-вертекс объекта касается черного пикселя - свойства этого объекта определенным образом изменяются. То есть тень от дома запекается в карту теней нашего ландшафта. Поляна травы состоит из отдельных пучков и там где пучок травы касается темного пикселя карты теней - весь пучок становится затененным. Это разгружает видеокарту.
Оптимизированная генерация теней деревьев
Тень кроны дерева имеет очень много деталей (веточек, листочков). Допустим игрок зашел в тень дерева и тень кроны падает на его спину, при этом при перемещении игрока тень тоже двигается.

Есть два варианта генерации теней деревьев:
1.. Трассировка лучей. Луч от солнца проходит через листву (прослитывая текстуру прозрачности листьев и сложную геометрию веток) и оставляет теневой рисунок на спине человека. Это очень нагружает систему.
2.. На рисунке ниже показан наш вариант генерации тени дерева. По принципу, описанному выше с домиком, у дерева генерируется теневой меш с очень простой геометрией (шар вместо кроны), а на землю ложится или запекается детализованная текстура тени кроны. Модель человека, который зашел в этот теневой меш начинает взаимодействовать с плоской тектурой, которая просто перемещается по его силуэту в зависимости от его передвижения.
Это разгружает видеокарту.
На рисунке ниже показана плоская прозрачная по Alpha-каналу текстура тени кроны, которая не прилипла к спине человека повторяя ее изгибы, а просто стоит между человеком и камерой в виде прямоугольного фрейма. Для контроля на текстуру поставили красную точку. Человек делает шаг вправо, а текстура смещается влево, это видно по контрольной точке. Причем силуэт человека является маской для текстуры тени (там, где человеческого тела нет, текстура не отрисовывается).
Это разгружает видеокарту.
Текстурные замки
Такие же замки есть и в текстурах на краях наших квадратов, по принципу того, как создаются тайлинговые бесшовные текстуры, паттерны.
По краю, по всему периметру наших квадратов ставим текстуреые замки, за тем закрашиваем таким образом, чтобы при соединении квадраты не образовывали стыков, внутреннюю оставшуюся площадь квадратов, можно закрашивать как угодно.

То же касается “Рельефных замков” - на стыках они неизменны и совпадают, не образовывая стыков, внутри же квадрата может быть любой скульптинг поверхности.

Это была 1-я Часть рассказа о генерации безграничной живой карты.

Чтобы перейти на следующую 2-ю Часть, нажмите кнопку ниже.

This site was made on Tilda — a website builder that helps to create a website without any code
Create a website