Всех приветствую! В прошлом году я начинал цикл статей на тему разработки моей инди – игры. Hail to the Rainbow. С тех пор прошло немало времени, и игра уже успела выйти в релиз на трех платформах: Steam, VK Play и GOG. К сожалению, тяжело одновременно вести работу над игрой и готовить при этом материалы или дневники разработчика. Всегда поражаюсь способностям тех, кто умудряется находить на это силы и время. Однако, темы статей я запланировал давно, поэтому очень хотелось бы рассказать о нюансах и тонкостях работы, пусть даже после выхода игры.

Для начала стоит, пожалуй, поделиться некоторой общей информацией о релизе. Игра вышла в ноябре 25 года. Работа велась на момент релиза уже около шести лет. Очень большой срок и очень большая усталость накопилась от работы за это время. Публикой проект в целом был принят достаточно тепло, релиз прошёл без глобальных проблем. Критических ошибок и багов на старте не обнаружилось, хотя в течение нескольких последующих месяцев было выпущено семь апдейтов с правками и доработками. На момент релиза число вишлистов было примерно 85 тысяч. На сегодняшний день статистика такова, что игру приобрело примерно 43 тысячи человек. В моей практике это, пожалуй, лучший результат за такой срок.

Теперь по основной теме, которую мне давно хотелось разобрать. Так сложилось, что в работе с движком Unity я во многом использую олдскульные и кустарные методы, в том числе и в графике. Сейчас большинство разработчиков пересаживается на новые технологии, HDRP рендер, глобальное реалтайм освещение, RTX и тд. Я же по-прежнему сижу в Unity built-in render и пытаюсь выжать максимум классическими техниками, использую статичный лайтмаппинг и некоторые самописные хитрости. Кстати, последние новости от Unity по поводу будущего выпиливания старого рендера меня очень огорчили. У меня есть некоторый опыт работы в новом HDRP, и честно говоря, он вызывает лишь разочарование своей топорностью и низкой производительностью. На мой взгляд, классический рендер визуально мало чем уступает благодаря своей гибкости и дополнительным расширениям. Впрочем, допускаю, что в новой среде у меня пока еще мало опыта для окончательных выводов.

Старый добрый лайтмаппинг.

Как я наверно уже указывал в ранних статьях, на проекте я использую лайтмаппер Bakery. Очень качественный инструмент, который за эти годы очень хорошо себя зарекомендовал. Печёт быстро при адекватных настройках, в Preview экране позволяет увидеть предварительный результат.

Предпросмотр в Bakery.
Предпросмотр в Bakery.

В сценах Hail to the Rainbow я активно миксую две основных категории объектов. Крупные объекты с запеченным светом, здания, трубы, крупногабаритные пропсы с более-менее простой uv развёрткой для запечки. Развертку для лайтмаппинга я чаще всего делаю самостоятельно, не доверяю автоматике. Порой для тех же зданий удобно регулировать качество карт в зависимости от важности элемента. К примеру, для фасада развертка делается плотной для достижения высокой детализации. Для крыш, боковых стен, которых игрок почти не увидит или увидит издалека, развертку можно сделать менее плотной, то есть выделить для этих зон низкий Texel Density.

Плотность UV2 развертки.
Плотность UV2 развертки.

Второй категорией объектов можно назвать мелкие пропсы и элементы со сложной развёрткой, запекание которых слишком затратно по времени и ресурсам. Такие объекты обычно используют Light Probes – световые зонды, позволяющие накладывать мягкий свет окружения, имитировать цветовые, световые рефлексы и затенения. На мелких объектах нет особого смысла запекать карты света и проще их окрашивать пробами. Иногда для оптимизации и более эффективного батчинга нескольким одинаковым и повторяющимся пропсам я назначал одну и ту же позицию лайт проб.

Назначение позиции лайт проб для объектов без лайтмаппинга.
Назначение позиции лайт проб для объектов без лайтмаппинга.

Вообще построение сцен в играх мне очень нравится тем, что они содержат в себе огромное количество фейковых приёмов и фокусов. К примеру, на некоторых локациях определённые удалённые от игрока объекты, вроде зданий или деревьев я исключал из реалтайм освещения Directional light, при этом использовал для их подсветки либо лайтмапы, либо лайт пробы. В целом, основной принцип работы со светом и оптимизацией – чем меньше реалтайм света и теней, тем лучше. Это позволяет значительно снижать полигонаж в кадре и количество Draw Calls – вызовов отрисовки.

Полностью запеченный свет на объекте за пределами карты.
Полностью запеченный свет на объекте за пределами карты.
Готовая сцена с запеченным светом + реалтайм освещение солнца.
Готовая сцена с запеченным светом + реалтайм освещение солнца.
Сама запечка с рефлексами. Некоторые объекты не отображаются, поскольку используют Light Probes.
Сама запечка с рефлексами. Некоторые объекты не отображаются, поскольку используют Light Probes.

Глобально я использовал во всех сценах режим Distance Shadowmask. На расстоянии до 50-80 метров объекты отбрасывают реальные тени + к поверхностям применяется запеченный мягкий Global Illumination свет, с помощью лайтмаппинга, либо Light Probes.  Далее отрисовываются уже полностью запечённые тени. Это позволяет не терять художественную выразительность и затенения на больших расстояниях.  В некоторых случаях для экономии я полностью запекал свет, к примеру в некоторых комнатах со слабой освещенностью. Но там, где свет должен создавать качественный акцент, обращать на что-то внимание, подчёркивать детали, я использовал реалтайм светильники. При этом, очень жаль, что в Unity (по крайней мере в версии 2019) нет встроенного метода отсечения светильников на расстоянии, из-за чего отрисовка некоторых лампочек в помещениях после 40-60 метров становится бессмысленной тратой ресурсов. Для решения этого вопроса пришлось сделать свой контроллер, который хранил в списке источники света, раз в 2-3 секунды пробегался по списку и активировал, или дезактивировал лампы для экономии.

Переход от реалтайм теней к запеченным
Переход от реалтайм теней к запеченным

Terrain Lightmapping.

Поскольку процесс запекания не быстр и каждый раз после каких-либо изменений пересчитывать свет на уровне слишком утомительно, я применил для некоторых природных объектов один интересный приём. Для декора на террейне я достаточно часто использовал объекты в виде детализированных сугробов, заснеженных веток, комков снега и камней. Как правило, эти объекты имели несколько уровней лодов. Чтобы не тратить время и текстурное лайтмап-пространство я написал шейдер, использующий лайтмапу террейна и проецирующий её сверху на объекты (для этого необходимо было, чтобы лайтмапа содержала в себе именно карту террейна, и ничего более). Это позволило отключить у объектов Light Probe режим, зачастую создающий дополнительные Draw Calls. В нашем случае шейдер и карта освещения имитировали амбиент для всех этих многочисленных объектов без особой нагрузки. Поскольку карта света у террейна и объектов одна, в тёмных областях и более светлых, сугробы достаточно гармонично сливались со снежной поверхностью, создавая ощущение цельной структуры.  Дополнительно в данном шейдере использовалась и система блендинга с террейном, при максимальном сближении с поверхностью террейна нижняя часть объектов плавно миксовалась (переходила к тем же картам, альбедо, нормал и тд., что и у самого террейна). В совокупности данный метод вполне неплохо себя показал и позволил создавать дополнительную более сложную геометрию на поверхности снега, смешивая ее и избегая грубых жёстких рёбер и переходов. Эта же техника оказалась подходящей и для создания снежно-морозного налета нижней части объектов, находящихся в снегу.

Сцена с террейном и запеченным светом. Деревья, прочая растительность, мелкие объекты в запечку не входят.
Сцена с террейном и запеченным светом. Деревья, прочая растительность, мелкие объекты в запечку не входят.
Блендинг террейна с природными элементами.
Блендинг террейна с природными элементами.
Налет снега на нижней части объекта передается от террейна.
Налет снега на нижней части объекта передается от террейна.

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

Прокачка теней.

Для тех, кто знаком с движком Unity или играл в игры на нём, не секрет, что стандартные тени из коробки выглядят достаточно уныло. Тень от солнца (Directional Light) одинаково чёткая по всей протяжённости, либо размытая и мерцает, если снизить качество Shadow map resolution. Тени от Point или Spot светильников также весьма грубы и не поддаются модификациям. В таких условиях, например, сложно сделать мягкий свет в пасмурную погоду или от рассеянных источников (можно сделать запечкой, но я имею в виду именно реалтайм светильники).

В первую очередь для Hail to the Rainbow я решил прокачать тени от солнца. На реальной местности тени весьма разнообразны, они имеют разную степень чёткости. Тень у основания объектов, всегда чёткая, но по мере удаления всё больше размывается. К примеру, тень на стене от рядом стоящего человека будет чёткой, а от здания, расположенного вдалеке - значительно размытой. Благодаря этому тени не превращаются в однообразную кашу, а несут в себе информацию, придают объем. Это очень здорово отражено в Half - life Alyx. Основной свет и тени там также запечены в лайтмапы, видно, насколько тени от далёких источников мягкие и плавные. Однако, отдельные объекты, динамические в том числе, отбрасывают чёткие реалтайм тени.

Пример освещения в Half - life Alyx.
Пример освещения в Half - life Alyx.

Помимо запечки, создающей правильный эффект и размытие статичных теней на расстоянии, схожий эффект именно в реалтайм тенях позволяет достичь специальный алгоритм, смешивание разных каскадов теней и размытие. Для Unity 2019 мне удалось найти отличный ассет NGS Shadows. Он позволил создать подобный эффект для теней от солнца без ощутимой потери производительности. В новых Unity HDRP  есть аналогичный метод, но на мой взгляд, по сравнению с указанным выше ассетом он значительно уступает по степени производительности.

Размытие теней при удалении от объектов в Hail to the Rainbow.
Размытие теней при удалении от объектов в Hail to the Rainbow.
Регулировка степени размытия.
Регулировка степени размытия.

Немного прокачать я решил и тени от Spot освещения. Мне хотелось достичь наибольшей мягкости и иметь возможность использовать размытые тени низкого разрешения. Тогда мне на глаза попалась статья, где описывался метод смешивания  Shadow maps в базовом шейдере обработки теней Shadow Library. Степень размытия я так же, как в примере привязал к параметру Range. В результате мне стала доступна более мягкая и ненавязчивая версия теней.

Размытие тени низкого разрешения.
Размытие тени низкого разрешения.

Рисуем светом.

Интересный подход в этот раз я решил использовать для акцентов освещения от Directional Light. Поскольку локации зимние и снег в основном однородный, изначальный вариант освещения солнца мне показался слишком скучным: заснеженные поля были однообразными, не было световых контрастов, художественных затенений и вообще какого-либо разнообразия.

На помощь пришла карта cookie, а также изменённый шейдер для отрисовки этих самых куки. В шейдере я добавил возможность использовать несколько разных каналов текстуры. На канале R я изобразил хаотичные пятна для подчёркивания контрастов в нужных местах. Какие-то участки локации я подсветил, где-то напротив затемнил.

Пример локации с движущимися тенями от облаков и световыми акцентами.
Пример локации с движущимися тенями от облаков и световыми акцентами.

В канале G я нарисовал несколько рандомных пятен для имитации движущихся теней от облаков. В шейдере отрисовки Cookie к этому каналу добавлено смещение во времени, для анимации движения.

Пример Cookie карты для Directional Light.
Пример Cookie карты для Directional Light.

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

Еще один пример сцены с акцентами освещения.
Еще один пример сцены с акцентами освещения.

Volumetric Light.

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

У меня в проекте с этой техникой были непростые отношения. В арсенале у меня был неплохой постэффект для объемного освещения, который я ранее использовал в проекте The Light Remake. Однако, он не всегда выглядел так, как мне было нужно, он заполнял все небо, заслоняя скайбокс. К тому же данный эффект накидывал немалую дополнительную нагрузку для просчетов, особенно это было критично в некоторых сложных сценах. Поэтому я решил применять полноценный волюметрик лишь в некоторых случаях и там, где не было особой нагрузки. В остальных случаях я использовал фейковые приемы.

Сцены с полноценным (честным) волюметрик светом.
Сцены с полноценным (честным) волюметрик светом.

Наиболее ходовым стали обычные процедурные конусы с Soft Additive шейдером (тот же тип шейдеров, который обычно используется для мягких Particles). Также я использовал иногда и плоские спрайты, если эффект располагался далеко от игрока. Меши с мягким шейдером оказались достаточно простыми с точки зрения производительности, не имели артефактов и шумов, какие иногда дает постэффект при низких настройках.

Фейковый конус-волюметрик.
Фейковый конус-волюметрик.

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

Яркий свет за пределами здания.
Яркий свет за пределами здания.

Особенно активно я использовал простейшие спрайты, а именно компонент Sprite Renderer с мягким шейдером, в кат-сценах игры. Практически во всех заставках присутствуют спрайты для подчеркивания контрастов и придания глубины: на задних планах, за персонажем, иногда в качестве засветов на переднем плане и т.д.

Пример кат-сцены с использованием световых спрайтов.
Пример кат-сцены с использованием световых спрайтов.

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

Комментарии (11)


  1. yadobr
    17.04.2026 14:35

    Спасибо за статью, вопрос к автору.
    Что больше всего было сложнее в разработке? Код или создание 3d моделей, текстур, музыки и т.д.?
    Какой бы совет вы себе дали, вернувшись на 6 лет назад?


    1. NoskovSS Автор
      17.04.2026 14:35

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