При создании пустой 3D-сцены в Godot редактор выставляет стандартные параметры освещения и окружения. Благодаря этому можно приступать к работе над сценой, не подбирая освещение и фон для чёрной, как ночь, сцены. Выглядит это примерно так:

screenshot_before.jpg

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

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

Наше простое фотореалистичное окружение с дневным освещением превратит показанный выше скриншот в следующую сцену:

screenshot.jpg

Проект с демо-сценой и environment.tres, которые вы можете при желании использовать, сохранены здесь: https://git.hexaquo.at/karl/realistic-godot-environment

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

  • Фон

  • Направленное освещение

  • Освещение окружающей среды

  • Непрямое освещение

  • Тональный корректор

  • Постобработку

Подготавливаем WorldEnvironment

Как говорилось в начале статьи, Godot по умолчанию использует стандартное окружение. Его можно увидеть в 3D-вьюпорте, но на самом деле оно нужно только для этого превью: оно отсутствует в дереве сцены, а потому не отображается при запуске игры. На самом деле, запуск игры без света и окружения выглядит вот так:

screenshot.jpg

Начать можно с одного из двух вариантов: во-первых, добавить в сцену ноды WorldEnvironment и DirectionalLight, а затем приступить к изменению их параметров. В этом случае мы начнём с нуля.

Однако если вас устраивает стандартное окружение, которое вы видите в редакторе, то можно использовать в качестве начальной точки его. Для этого нужно нажать на три точки рядом со значками солнца и окружения над 3D-вьюпортом, а затем нажать на кнопки для добавления окружения и солнца к сцене:

image.png

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

screenshot.jpg

Фон

Самая очевидная проблема пустого окружения заключается в том, что фон полностью серый. Вместо этого нам нужно синее небо с красивым градиентом горизонта и солнцем, примерно как это выглядит в стандартном окружении по умолчанию. Этого можно добиться, переключив режим фона на «Sky» и добавив новое солнце (Sky) со SkyMaterial. Для материала солнца можно использовать одну из трёх опций:

  • PanoramaSkyMaterial: обёртывает текстуру вокруг фона, как стандартный купол неба. Такие текстуры называются HDRI, их можно найти онлайн, например, здесь (с лицензией CC0): https://polyhaven.com/hdris

  • ProceduralSkyMaterial: по сути, это цветовые градиенты; вполне подходят для реалистичной сцены, но особенно практичны для стилизованных игр, в которых разработчику нужен удобный контроль за цветами горизонта и солнца.

  • PhysicalSkyMaterial: правильная физическая симуляция цвета атмосферы. Выглядит реалистичнее, чем ProceduralSky, и автоматически реагирует на угол солнца, создавая очень красивые горизонты на рассвете и закате.

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

Вы можете обратить внимание, что небо выглядит достаточно тёмным. На яркость его цвета влияют два аспекта: энергия неба и энергия солнца. Мы рассмотрим энергию солнца чуть ниже, но скажу, что люблю устанавливать для неба множитель энергии больше, чем 1.0; в данном случае я использовал 1.5.

screenshot.jpg

Бонус: добавление облаков

PhysicalSkyMaterial может симулировать только чистое небо. Если вам нужны облака, то их можно реализовать при помощи одного из двух вариантов:

  • процедурные объёмные облака clayjohn с ещё более физически корректной атмосферой и процедурными облаками с физическим рендерингом: https://github.com/clayjohn/godot-volumetric-cloud-demo-v2. Это специализированный шейдер Sky, то есть он заменяет встроенное физическое небо Godot в качестве фона окружения.

  • SunshineClouds разработчика Bonkahe: https://github.com/Bonkahe/SunshineClouds2. Это не просто другой фон, а реальные 3D-облака, в которых можно летать и пролетать их насквозь.

Рендеринг облаков и рендеринг объёмов в целом — очень интересная для исследований тема. У Bonkahe в репозитории SunshineClouds есть ссылка на видео с подробным объяснением; кроме того, существует огромное количество других видео и статей по этой теме (я и сам собираюсь написать статью о raymarching в Godot). Основой для большинства из них стала презентация Эндрю Шнайдера 2015 года о реализации объёмных облаков в Horizon: Zero Dawn при помощи raymarching: https://www.guerrilla-games.com/read/the-real-time-volumetric-cloudscapes-of-horizon-zero-dawn

Направленное освещение

Основной источник направленного освещения в этой реалистичной дневной сцене — солнце. Нажав на «Add Sun to Scene», можно добавить в сцену нод DirectionalLight3D, потому что для солнечного света обычно используется именно он. Направленное освещение можно представить в виде параллельных фотонов, движущихся в одном направлении. Иными словами, это бесконечно удалённый точечный источник света. Солнце отдалено от нас не на бесконечность, но оно достаточно далеко, чтобы это можно было использовать в качестве аппроксимации.

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

  • Энергии солнца.

  • Энергии других источников освещения (например, неба, ламп или огня).

  • Экспозиции камеры.

Стандартная экспозиция камеры (1.0) довольно темна для солнца. Я считаю, что для безоблачного полудня разумно выбрать 3.0. Эту энергию следует менять в зависимости от времени суток и погоды в игре.

screenshot.jpg

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

Также, разумеется, можно менять цвет освещения. Добавление доли жёлтого может выглядеть красиво, особенно на рассвете и закате.

Тональный корректор

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

Причина этого в том, что перед рендерингом на экран цвета хранятся в high dynamic range (HDR). Это не триплеты значений RGB от 0.0 до 1.0 (или от 0 до 255), которые мы видим в цветовых палитрах и цифровых редакторах графики. В HDR каждый канал может иметь значения от 0.0 до бесконечности (если не учитывать точность чисел с плавающей запятой).

Это очень важно для сцен с реалистичным освещением: в традиционном RGB мы никак не можем отличить чистый белый лист бумаги (например, фон веб-сайта) от прямого взгляда на солнце. Оба имеют значения чистого белого цвета (1.0, 1.0, 1.0). Но, разумеется, яркость сильно влияет на итоговый внешний вид цвета и на его взаимодействие с другими цветами, а также на его воздействие на эффекты постобработки наподобие bloom (об этом мы поговорим ниже). Именно поэтому во всех 3D-сценах данные хранятся в high dynamic range.

Однако наши дисплеи не могут работать с этими цветами, их пиксели передают традиционные значения RGB 0.0-1.0. Даже если у вас HDR-дисплей, его дополнительный динамический диапазон далёк от того, что нужно вам для отображения полного динамического диапазона 3D-сцены. Поэтому нам нужно преобразовывать high dynamic range в low dynamic range (LDR). И это задача для тональной коррекции.

Стандартный тональный корректор Linear сам по себе ничего не делает; он просто урезает все значения до максимально возможного 1.0. Для тёмных сцен это приемлемо, но при этом мы не только теряем информацию о яркости, но и всё, что ярче (1.0, 1.0, 1.0), просто становится чистым белым цветом, поэтому мы теряем также цветовую информацию и контрастность.

В Godot есть ещё несколько тональных корректоров, хорошо объяснённых в документации. Реалистичные тональные корректоры — это ACES и AgX, при этом AgX — самый новый и точный. И ACES, и AgX снижают насыщенность ярких значений для передачи яркости, но AgX лучше справляется с сохранением тонов и передачей деталей и контраста, поэтому его обычно стоит использовать для высокореалистичной графики.

screenshot.jpg

По умолчанию AgX достаточно сильно снижает насыщенность. Чтобы компенсировать это, можно увеличить контрастность и насыщенность во вкладке «adjustments» окружения. При этом AgX продолжит корректно и красиво обрабатывать яркость, а результат будет чуть более интересным. (Стоит отметить, что моё демо не показывает в полной мере сильные стороны тональной коррекции и AgX; они становятся очевиднее при работе с очень ярким освещением и такими объектами, как огонь и неоновые лампы.)

screenshot.jpg

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

Освещение окружающей среды

Вернёмся к чему-то более практическому! Освещение окружающей среды (ambient light) — это свет, существующий во всех точках сцены, на которые не попадает направленное освещение. По умолчанию оно включено; в противном случае наши тени выглядели бы полностью чёрными:

screenshot.jpg

Это глобальное освещение окружающей среды можно настроить во вкладке «Ambient Light» окружения. Стандартная опция «Background» берёт освещение окружающей среды от неба, что логично. Если вы хотите настраивать освещение окружающей среды тоньше, то можно установить для параметра «sky contribution» значение меньше 1.0. Благодаря этому можно добавить в освещение от неба свой цвет. В стилизованных играх можно добавлять в освещение окружающей среды синий или фиолетовый для контраста с желтоватым направленным освещением.

Выше я назвал это «глобальным освещением окружающей среды», потому что оно одинаково во всей сцене. Разумеется, это аппроксимация, и на самом деле свет работает иначе. Если вы хотите симулировать свет именно так, как он работает реально, то вам придётся использовать трассировку лучей (raytracing). Однако в Godot есть и другие, более простые решения для создания реалистичного освещения окружающей среды:

Ambient Occlusion

Если вы хотите добавить тени в глубокие области, на которые не падает направленное освещение, то вам нужно ambient occlusion. В окружении Godot для этого есть Screen Space Ambient Occlusion (SSAO). По сути, SSAO сэмплирует геометрию вокруг пикселя, чтобы аппроксимировать величину достигающего его света. Плоская поверхность не получит при этом дополнительного затенения, но оно возникнет в углу, потому что вокруг пикселей внутри угла больше геометрии. «Screen Space» означает, что пиксели проверяются и сравниваются с пикселями отрендеренного изображения, и в частности с буфером глубин отрендеренного изображения. На практике это означает, что SSAO знает только о том, что видит игрок. Поэтому оно может создавать артефакты при перемещении камеры, особенно по краям экрана, на гранях объектов и когда углы очень резкие.

Я выяснил, что при включении SSAO и установке intensity на 3.0 затенённые области становятся гораздо более пластичными:

screenshot.jpg

Если вам нужно ambient occlusion не только в затенённых областях, а везде, то можно установить значение 1.0 для «Light Affect» и «AO Channel Affect» (или какое-то другое больше 0.0). Это повысит пластичность всей сцены:

screenshot.jpg

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

screenshot.jpg

Другие параметры SSAO в основном нужны для устранения его недостатков и артефактов, они будут зависеть от масштаба и геометрии сцены.

Альтернативой (или дополнением) SSAO может быть глобальное освещение (global illumination), обрабатывающее освещение окружающей среды ещё реалистичнее. Мы коснёмся этого в следующем разделе.

Непрямое освещение

При помощи освещения окружающей среды и ambient occlusion мы аппроксимировали величину затемнения в областях, на которые не падает направленное освещение. Непрямое освещение (indirect light) связано с этой концепцией, но имеет обратный смысл: оно симулирует то, как ярко освещённые области распространяют часть этого света на затенённые области. Вместе с освещением окружающей среды непрямое освещение часто называют глобальным освещением (global illumination).

В целом можно разбить реализацию непрямого освещения и global illumination в Godot на три способа:

Screen Space Indirect Light (SSIL)

SSIL можно активировать в окружении. Оно работает подобно SSAO в том смысле, что проверяет в итоговом рендере, сколько дополнительного света отразилось в пиксель. Самым прямым результатом активации SSIL становятся более точные цвета теней, потому что на цвет освещения окружающей среды влияет не только фоновое небо, но и цвет соседней освещённой геометрии.

screenshot.jpg

Как и в случае с SSAO, можно отдельно просматривать буфер SSIL, чтобы изучить работу, выполняемую этим проходом. Так как SSIL влияет довольно слабо, этот буфер очень тёмный; здесь я сжал его вывод, чтобы вы лучше увидели, какой вклад вносит SSIL в финальное изображение. Обратите внимание на коричневый цвет (берущийся от коричневой текстуры бетона) и варьирующуюся яркость, например, нижнюю часть ствола дерева, освещённую окружающим его бетоном.

screenshot.jpg

Signed Distance Field Global Illumination (SDFGI)

SDFGI — это собственный способ Godot реализации глобального освещения в реальном времени. В отличие от SSAO и SSIL, он на самом деле учитывает всю сцену при вычислении величины (и цвета) освещения, получаемого затенённой областью, а потому обеспечивает более точные результаты:

screenshot.jpg

Для этого он создаёт упрощённое представление сцены и её освещения — поле расстояний со знаком (signed distance field) — и выполняет сэмплирование из него. Выглядит это так:

screenshot.jpg

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

Запечённое глобальное освещение

И SSIL, и SDFGI — это алгоритмы реального времени: они могут реагировать на изменение геометрии, движение источников света, смену дня и ночи и так далее. Однако может оказаться так, что всё это не нужно в вашей игре: если ваша сцена по большей мере статична, а освещение не меняется, то следует подумать о запекании глобального освещения.

Под «запеканием» подразумевается, что мы генерируем дополнительные ресурсы (текстуры или воксели), содержащие информацию о глобальном освещении. Запекание может требовать приличного количества времени, но его необходимо выполнять только один раз (при изменении освещения или геометрии), а запечённые данные можно выпускать в составе игры.

Для этого в Godot есть LightmapGI и VoxelGI. LightmapGI полностью статично; по сути, мы генерируем текстуру, содержащую цвета всего дополнительного освещения и теней, добавляемую к обычным текстурам сцены. VoxelGI более динамично, можно считать его чем-то средним между SDFGI и LightmapGI.

Запечённое освещение — само по себе большая отдельная тема, требующая большей ручной настройки, чем SSIL и SDFGI, поэтому здесь я не буду вдаваться в подробности. В документации по Godot есть статьи о различных методиках запекания, например, здесь: https://docs.godotengine.org/en/stable/tutorials/3d/global_illumination/using_lightmap_gi.html; также существуют другие онлайн-ресурсы и видео, например, отличное видео Brackeys о 3D-освещении в Godot.

Постобработка

Под постобработкой (post processing) подразумевается обработка изображения после его рендеринга. Промежуточной или постобработкой можно считать такие методики обработки в экранном пространстве, как SSAO и SSIL. Перед отправкой изображения на экран можно обрабатывать его бесконечным количеством способов, но здесь я хочу рассмотреть три самых важных:

Свечение

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

Чтобы реализовать это, мы можем включить свечение в окружении и установить bloom на значение выше 0.0. Используемый по умолчанию режим смешения (blend mode) «softlight» довольно малозаметен; если вы хотите, чтобы свет распространялся сильнее, то попробуйте переключиться на «screen». Если установить для blend mode опцию «screen», а bloom поставить на 0.1, то мы получим красивое распространение света, делающее сцену гораздо ярче и теплее.

screenshot.jpg

Буфер bloom, по сути, выглядит как размытое изображение ярких областей рендеринга:

screenshot.jpg

Для экспериментов с дальностью распространения света можно настраивать множество разных параметров. В документации по Godot есть подробная статья об этом. Но не переборщите с ним, если не хотите получить эстетику FPS конца 2000-х.

Туман

Моя демо-сцена так мала, что туман практически никак не повлияет на картинку, но если вы работаете с крупными сценами, то вам определённо понадобится красивое затухание и атмосферная дымка вдалеке. Если вам нужна просто атмосферная дымка без изменения неба, то можно активировать туман и установить «Sky Affect» на 0.0. Также можно присвоить «Aerial Perspective» значение 1.0: при этом туман будет смешивать удалённые объекты с цветом неба, а не с выбранным цветом.

Цветокоррекция

В разделе об AgX я упоминал, что значение 1.3 для контраста и насыщенности помогает сделать сцену более интересной. В Godot есть удобные ползунки для настройки яркости, контрастности и насыщенности, но в движке можно и выполнять цветокоррекцию постобработки при помощи слота «color correction».

При помощи текстуры поиска (look-up texture, LUT) можно сопоставить любой входной цвет с любым выходным. LUT — это трёхмерные текстуры, в которых мы вводим RGB-значения в качестве координат, а на выходе получаем новое RGB-значение. Например, если ввести (0.5, 0.8, 0.4), то есть зеленоватый цвет, а в LUT в этой позиции находится более яркий зелёный (0.3, 0.9, 0.2), то ваша LUT будет превращать зеленоватые цвета в ярко-зелёные.

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

Вот стандартная LUT из документации по Godot:

environment_adjustments_3d_lut_template.webp

А ниже я внёс изменения (намеренно бросающиеся в глаза) баланса белого и цветокоррекции в скриншот демо-сцены, а также в LUT, и снова преобразовал изображение в LUT:

lut.png

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

Давайте посмотрим, как выглядит демо-сцена после применения этой LUT. Имейте в виду, что, как написано в документации по Godot, её нужно импортировать как Texture3D с 33 горизонтальными срезами и 1 вертикальным срезом.

screenshot.jpg

Физические единицы света

Как я сказал в самом начале, единицы энергии света в Godot выбраны произвольным образом. Это вполне подходит для настройки универсальной 3D-сцены, но в статье о фотореалистичном рендеринге обязательно следует упомянуть, что всё это можно изменять: вы можете зайти в настройки проекта, активировать «Advanced Settings» в верхнем правом углу, перейти к пункту «Lights and Shadows» в разделе Rendering и установить флажок «Use Physical Light Units». После этого вы сможете использовать реальные единицы для задания яркости освещения.

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

Сделать это можно, перейдя к WorldEnvironment и добавив CameraAttributesPhysical к свойству Camera Attributes. Установив чувствительность экспозиции ISO на 80.0, мы получим картинку, очень близкую к тому, что было раньше (без применённой LUT):

screenshot.jpg

Возможно, также можно попробовать поставить флажок «Auto Exposure»; при этом камера будет действовать, как камера телефона, автоматически меняя свои свойства для получения хорошей яркости и контрастности в зависимости от освещения в сцене. При включенной автоматической экспозиции можно менять ISO, чтобы модифицировать контрастность изображения. Вот сцена со включенной автоматической экспозицией и ISO 40.0:

screenshot.jpg

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

Также есть ещё один пост о физических единицах освещения: он посвящён Unreal, но полезен и в Godot; в нём содержатся значения в люксах для самых распространённых типов освещения.

Надеюсь, моя статья поможет вам освоить реалистичную 3D-графику в Godot. Удачи в ваших проектах!

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