Под Капотом Graveyard Keeper: Как Реализованы Графические Эффекты

Всем привет! Я не писал на Хабре целых 4 года.

Мой последний серия постов речь шла о различных инструментах и методах, которые мы использовали в нашей последней игре (разрабатывая ее в Unity).

С тех пор мы успешно выпустили эту игру, а также выпустили новую.

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



Под капотом Graveyard Keeper: как реализованы графические эффекты

Сегодня я хочу поговорить о графических приемах и приемах, которые мы использовали для создания картинки, которую вы видите на гифке выше.

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

Возможно, кто-то найдет для себя что-то полезное.

Для начала кратко перечислю, из чего сделана картинка в нашей игре:

  1. Переменный рассеянный свет — банальное изменение освещенности в зависимости от времени суток.

  2. Цветокоррекция LUT – отвечает за изменение тона картинки в зависимости от времени суток (или типа зоны).

  3. Динамические источники света – факелы, печи, лампы.

  4. Карты нормалей отвечают за добавление объема объектам, особенно при движении источников света.

  5. Математика 3D светораспределения – отвечает за то, чтобы источник света в центре экрана правильно освещал объект, который находится вверху, но не освещал объект, который находится внизу (то есть неосвещенная сторона повернута к камере) .

  6. Тени — созданы спрайтами, вращаются и реагируют на положение источников света.

  7. Имитация высоты объекта — для корректного отображения тумана.

  8. Прочие декорации: дождь, ветер, анимации (в том числе шейдерная анимация листвы и травы) и т.д.
Теперь – более подробно.



Изменяемое окружающее освещение

В принципе, ничего особенного здесь нет. Ночью темнее, днем светлее.

Цвет света задается градиентом в зависимости от времени суток.

Ночью источник света не только темнеет, но и приобретает синий оттенок.

Это выглядит так:

Под капотом Graveyard Keeper: как реализованы графические эффекты



ЛУТ-коррекция цвета

LUT (Look-up table) — таблицы замены цветов.

Грубо говоря, это трехмерный RGB-массив, где каждый узел содержит значение цвета, на которое следует заменить соответствующее.

То есть, если в координатах (1, 1, 1) стоит красная точка, это означает, что весь белый цвет на картинке будет заменен красным.

Если координаты (1, 1, 1) содержат белый цвет (R=1, G=1, B=1), то никаких изменений не происходит. Соответственно, ЛУТ без изменений имеет цвет для каждой координаты, соответствующий этим самым координатам.

Те.

в точке (0,4, 0,5, 0,8) есть цвет (R=0,4, G=0,5, B=0,8).

Ну и стоит отметить, что для удобства 3D-текстура представлена как двухмерная.

Например, так выглядит «дефолтный» LUT (который никак не меняет цветопередачу):

Под капотом Graveyard Keeper: как реализованы графические эффекты

Реализуется просто, работает быстро и удобно.

Настройка тоже очень простая — вы даете художнику любую картинку из игры и говорите «настройте цвета так, чтобы было похоже на вечер».

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

Вот как выглядит их установка:

Под капотом Graveyard Keeper: как реализованы графические эффекты

В результате в зависимости от времени суток одна и та же локация выглядит по-разному:

Под капотом Graveyard Keeper: как реализованы графические эффекты

Здесь прозрачность спрайтов света из окон тоже меняется в зависимости от времени суток.



Динамическое освещение и карты нормалей

Источники света использованы абсолютно обычные, от Unity. Кроме того, для каждого спрайта рисуются карты нормалей, что позволяет получить ощущение объёма.



Под капотом Graveyard Keeper: как реализованы графические эффекты

Рисуются такие нормали достаточно просто.

Художник примерно рисует кистью свет с 4-х сторон:

Под капотом Graveyard Keeper: как реализованы графические эффекты

А затем скрипт собирает это в нормальную карту:

Под капотом Graveyard Keeper: как реализованы графические эффекты

Если вы ищете шейдер (и программное обеспечение), который делает это, вы можете обратить внимание на Sprite Lamp.

3D-симуляция света

Здесь немного сложнее.

Вы не можете просто подсветить спрайты.

Нам нужно учитывать, находится ли спрайт «за» источником света или «перед».

Обратите внимание на эту картинку:

Под капотом Graveyard Keeper: как реализованы графические эффекты

Оба дерева находятся на одинаковом расстоянии от источника света, но самое дальнее дерево освещено, а ближайшее — нет (поскольку его неосвещенная часть повернута к камере).

Я решил эту проблему достаточно просто.

Шейдер вычисляет расстояние по вертикальной оси Y между источником света и спрайтом.

И если оно положительное (источник света находится перед спрайтом), то мы освещаем спрайт как обычно, а если отрицательное (спрайт перекрывает источник света), то интенсивность освещения очень сильно затухает с расстояния с помощью очень большой коэффициент. Коэффициент был сделан, а не просто «не освещать», чтобы при движении источника света и внезапном появлении за спрайтом спрайт не сразу становился черным, а постепенно.

Но все равно довольно быстро.



Под капотом Graveyard Keeper: как реализованы графические эффекты



Тени

Тени создаются спрайтами, вращающимися вокруг точки.

Я попробовал добавить к ним больше сжатия (перекоса), но это оказалось излишним.

Всего у каждого объекта может быть максимум 4 тени.

Один — от Солнца, а три — от динамических источников света.

На рисунке ниже показан принцип:

Под капотом Graveyard Keeper: как реализованы графические эффекты

Задачу «найти ближайшие 3 источника света и рассчитать расстояние/угол теней до них» решает скрипт, запускаемый в Update. Да, очень быстро это не получится, потому что… приходится много заниматься математикой.

Если бы я писал сейчас, я бы использовал новомодную систему параллельных заданий в Unity. Но тогда этого еще не было, поэтому я просто максимально оптимизировал обычные скрипты.

Единственное, что важно, это то, что я вращал спрайты не с помощью трансформации, а внутри вершинного шейдера.

Те.

вращение не влияет. В спрайте просто задается параметр (я для этого использовал цвет, потому что все тени все равно черные), а за вращение спрайта отвечает шейдер.

Так получается быстрее, потому что… не нужно возиться с геометрией в Unity. Еще одним недостатком этого подхода является то, что тени приходится настраивать (а иногда и рисовать) индивидуально для каждого объекта.

Правда, мы обошлись, наверное, десятком разных более-менее универсальных спрайтов (тонких, толстых, овальных и т. д.).

Второй недостаток заключается в том, что иногда сложно создать тень для объекта, пятно контакта которого с землей очень вытянуто.

Например, посмотрите на тень забора:

Под капотом Graveyard Keeper: как реализованы графические эффекты

Не идеально.

Вот как это будет выглядеть, если сделать сам спрайт забора полупрозрачным:

Под капотом Graveyard Keeper: как реализованы графические эффекты

Здесь, однако, стоит отметить, что спрайт по-прежнему сильно деформируется по вертикали (исходный теневой спрайт выглядит почти как круг).

Именно поэтому его поворот выглядит не столько как поворот, сколько как искажение.



Моделирование тумана и высоты

Также в игре присутствует туман.

Выглядит это так (вверху — обычный вариант, внизу — экстремальный 100% туман, для демонстрации эффекта).



Под капотом Graveyard Keeper: как реализованы графические эффекты

Как видите, из тумана торчат верхушки домов и деревьев.

На самом деле добиться такого эффекта было довольно просто.

Туман состоит из множества горизонтальных облаков, которые распределены по всей глубине сцены.

В результате верхняя часть всех спрайтов покрыта меньшим количеством туманных спрайтов:

Под капотом Graveyard Keeper: как реализованы графические эффекты



Ветер

Ветер в пиксельной графике — это совсем другая история.

Здесь не так много вариантов.

Либо анимировать вручную (что практически невозможно, учитывая количество имеющегося у нас арта), либо писать деформирующий шейдер, но тогда придется терпеть порой некрасивые искажения.

Можно, конечно, вообще не анимировать, но тогда картинка будет выглядеть безжизненной.

Мы выбрали вариант искажения с помощью шейдера.

Это выглядит так:

Под капотом Graveyard Keeper: как реализованы графические эффекты

Если вы примените этот шейдер к клетчатой текстуре, вы увидите, что происходит:

Под капотом Graveyard Keeper: как реализованы графические эффекты

Также стоит отметить, что мы анимируем не всю крону, а только отдельные листья:

Под капотом Graveyard Keeper: как реализованы графические эффекты

Еще у нас есть пшеница, колышущаяся на ветру, но здесь все просто — вершинный шейдер деформирует координаты x с учетом y-компоненты.

Чем выше точка, тем больше она колеблется.

Это делается для того, чтобы шаталась только верхушка, а корень – нет. Плюс — фаза покачивания меняется от координат x/y, так что разные спрайты на экране покачиваются в разное время.



Под капотом Graveyard Keeper: как реализованы графические эффекты

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



Под капотом Graveyard Keeper: как реализованы графические эффекты

Пожалуй, это пока все.

Я намеренно не затронул вопрос построения сцены и ее геометрии, потому что.

Это материал для отдельной статьи.

В остальном он рассказал об основных решениях, которые использовались при разработке.

ПС: Если кого-то интересуют какие-либо технические аспекты, пишите в комментариях.

Возможно, я расскажу вам в отдельной статье.

Если, конечно, это необходимо.

ППС: Пользуясь случаем, скажу, что сейчас мы хотим найти в команду несколько компетентных людей (программист, ПМ, СМ, художник).

Подробности на сайте студии.

Надеюсь, этой фразой я не нарушил правила.

Теги: #Разработка игр #unity #шейдеры # картографирование нормалей #graveyard keeper

Вместе с данным постом часто просматривают: