2D свет и тени

Введение

По умолчанию 2D-сцены в Godot не затенены, свет и тени не видны. Хотя рендеринг выполняется быстро, незатененные сцены могут выглядеть скучными. Godot предоставляет возможность использовать 2D-освещение и тени в реальном времени, что может значительно усилить ощущение глубины в вашем проекте.

Нет 2D-света и теней, сцена не затенена

Нет 2D-света и теней, сцена не затенена

Включено 2D освещение (без теней)

Включено 2D освещение (без теней)

2D-свет и тени включены

2D-свет и тени включены

Узлы

В полной настройке 2D-освещения задействовано несколько узлов:

  • CanvasModulate (используется для затемнения сцены)

  • PointLight2D (для всенаправленных или точечных источников света)

  • DirectionalLight2D (для солнечного или лунного света)

  • LightOccluder2D (для источников света и тени)

  • Другие 2D-узлы, получающие освещение, такие как Sprite2D или TileMapLayer.

CanvasModulate используется для затемнения сцены путем указания цвета, который будет выступать в роли базового "фонового" цвета. Это итоговый цвет освещения в областях, не затронутых никаким 2D-источником света. Без узла CanvasModulate финальная сцена выглядела бы слишком яркой, так как 2D-источники света только усиливали бы существующий незатененный внешний вид (который выглядит полностью освещенным).

Sprite2Ds используются для отображения текстур для световых пятен, фона и отбрасывающих тень объектов.

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

LightOccluder2Ds используются для указания шейдеру, какие части сцены отбрасывают тени. Эти окклюдеры могут быть размещены как независимые узлы или могут быть частью узла TileMapLayer.

Тени появляются только в покрытых PointLight2D и их направлением, зависищим от центра Light.

Примечание

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

Свойства Региона Sprite2D могут быть полезны для быстрого создания повторяющейся текстуры фона, но помните также установить Текстура > Повтор на Включено в свойствах Sprite2D.

Точечный свет

Точечный свет (также называемый позиционным светом) самый обычный элемент в 2D освещение. Точечный свет может использоваться, чтобы отобразить свет от факелов, огня, снарядов и т.д.

PointLight2D предлагает следующие свойства для настройки в инспекторе:

  • Texture: Текстура, используемая в качестве источника света. Размер текстуры определяет размер света. Текстура может иметь альфа-канал, который полезен при использовании режима смешивания Mix (Смешивание) в Light2D, но не является обязательным при использовании режимов смешивания Add (Добавление) (по умолчанию) или Subtract (Вычитание).

  • Offset (Смещение): Смещение для текстуры света. В отличие от перемещения узла света, изменение смещения не вызывает перемещение теней.

  • Texture Scale (Масштаб текстуры): Множитель размера света. Более высокие значения увеличат распространение света. Более крупные источники света имеют большее влияние на производительность, так как они влияют на большее количество пикселей на экране, поэтому учитывайте это перед увеличением размера света.

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

Если у вас нет готовой текстуры для использования в освещении, вы можете использовать эту "neutral (нейтральную)" текстуру точечного света (правый клик > Save Image As… (Сохранить изображение как…)):

Текстура нейтрального точечного света

Текстура нейтрального точечного света

Если вам нужно другое затухание, вы можете процедурно создать текстуру, назначив New GradientTexture2D свойству Texture источника света. После создания ресурса разверните его раздел Fill и установите режим заливки на Radial. Затем вам придется настроить сам градиент, чтобы он начинался от непрозрачного белого до прозрачного белого, и переместить его начальное положение в центр.

Направленный свет

Directional lighting is used to represent sunlight or moonlight. Light rays are casted parallel to each other, as if the sun or moon was infinitely far away from the surface that is receiving the light.

DirectionalLight2D имеет следующие свойства:

  • Height (Высота): Виртуальная высота света относительно карты нормалей (0.0 = параллельно поверхностям, 1.0 = перпендикулярно поверхностям). По умолчанию свет полностью параллелен поверхностям, получающим освещение. Это сделает освещение едва заметным при использовании карты нормалей, поэтому рекомендуется увеличить это значение. Настройка высоты света визуально влияет только на поверхности, использующие карту нормалей. Height (Высота) не влияет на внешний вид теней.

  • Max Distance: Максимальное расстояние от центра камеры до объектов, до которого их тени будут отсечены (в пикселях). Уменьшение этого значения может предотвратить отбрасывание теней объектами, расположенными за пределами камеры (и при этом повысить производительность). Масштаб Camera2D не учитывается Max Distance, что означает, что при более высоких значениях масштабирования тени будут исчезать быстрее при масштабировании заданной точки.

Примечание

Направленные тени всегда будут казаться бесконечно длинными, независимо от значения свойства Height. Это ограничение метода рендеринга теней, используемого для 2D-света в Godot.

Чтобы иметь направленные тени, которые не являются бесконечно длинными, следует отключить тени в DirectionalLight2D и использовать пользовательский шейдер, который считывает из 2D-знакового поля расстояния. Это поле расстояния автоматически генерируется из узлов LightOccluder2D, присутствующих в сцене.

Основные свойства света

И PointLight2D, и DirectionalLight2D имеют обычные свойства, являющиеся частью базового класса Light2D:

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

  • Только для редактора: Если включено, то свет будет виден только внутри редактора. Он автоматически выключиться при запуске проекта.

  • Цвет: Цвет света.

  • Энергия: Множитель интенсивности света. Более высокие значения приведут к более яркому освещению.

  • Blend Mode: Формула смешивания, используемая для вычислений света. Значение по умолчанию Add подходит для большинства случаев использования. Subtract можно использовать для негативного света, который не является физически точным, но может использоваться для специальных эффектов. Режим смешивания Mix смешивает значение пикселей, соответствующих текстуре света, со значениями пикселей под ним с помощью линейной интерполяции.

  • Range > Z Min: Наименьший индекс Z, на который влияет свет.

  • Range > Z Макс.: Самый высокий индекс Z, на который влияет свет.

  • Range > Layer Min: Самый нижний визуальный слой, на который воздействует свет.

  • Range > Layer Max: Самый высокий визуальный слой, на который влияет свет.

  • Range > Item Cull Mask: Управляет тем, какие узлы получают свет от этого узла, в зависимости от включенных визуальных слоев других узлов Маска отсечения света. Это можно использовать для предотвращения получения света определенными объектами.

Настройка теней

После включения свойства Shadow > Enabled на узле PointLight2D или DirectionalLight2D вы изначально не увидите никакой визуальной разницы. Это связано с тем, что ни один узел в вашей сцене пока не имеет occluders, которые используются в качестве основы для отбрасывания теней.

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

Наряду с ресурсом полигона (который должен быть установлен для создания какого-либо визуального эффекта), узлы LightOccluder2D имеют 2 свойства:

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

  • Occluder Light Mask: Используется совместно со свойством PointLight2D и DirectionalLight2D Shadow > Item Cull Mask для управления объектами, отбрасывающими тени для каждого источника света. Это можно использовать для предотвращения отбрасывания теней определенными объектами.

Существует два способа создания светозащитных экранов:

Автоматическое создание светового окклюдера

Окклюдеры можно создавать автоматически из узлов Sprite2D, выбрав узел, щелкнув меню Sprite2D в верхней части 2D-редактора, а затем выбрав Создать одноуровневый элемент LightOccluder2D.

В появившемся диалоговом окне контур будет окружать края вашего спрайта. Если контур точно соответствует краям спрайта, вы можете нажать OK. Если контур слишком далеко от краев спрайта (или «съедает» края спрайта), отрегулируйте Grow (pixels) и Shrink (pixels), затем нажмите Update Preview. Повторяйте эту операцию, пока не получите удовлетворительные результаты.

Рисование окклюдера вручную

Создайте узел LightOccluder2D, затем выберите узел и нажмите кнопку "+" в верхней части 2D-редактора. На вопрос о создании ресурса полигона ответьте Yes. Затем вы можете начать рисовать полигон окклюдера, нажав для создания новых точек. Вы можете удалить существующие точки, щелкнув по ним правой кнопкой мыши, и вы можете создать новые точки из существующей линии, щелкнув по линии и перетащив ее.

Для 2D-источников света с включенными тенями можно настроить следующие свойства:

  • Color: Цвет затененных областей. По умолчанию затененные области полностью черные, но это можно изменить в художественных целях. Альфа-канал цвета управляет тем, насколько тень окрашена указанным цветом.

  • Filter: Режим фильтра для использования теней. По умолчанию None — самый быстрый для рендеринга и хорошо подходит для игр с пиксельной эстетикой (из-за его «блочной» графики). Если вам нужна мягкая тень, используйте PCF5. PCF13 еще мягче, но он самый требовательный для рендеринга. PCF13 следует использовать только для нескольких источников света одновременно из-за его высокой стоимости рендеринга.

  • Filter Smooth: Управляет степенью смягчения теней, когда Filter установлен на PCF5 или PCF13. Более высокие значения приводят к более мягкой тени, но могут привести к появлению видимых артефактов полос (особенно с PCF5).

  • Item Cull Mask: контролирует, какие узлы LightOccluder2D отбрасывают тени, в зависимости от их соответствующих свойств Occluder Light Mask.

Примечание

Lighting and shadow resolution in pixel-art games

The engine computes 2D lighting and shadows at the Viewport's pixel resolution, not at the source texture's texel resolution. The appearance of lights and shadows depends on your window or Viewport resolution, not on the resolution of individual sprite textures.

If you create a pixel-art game and want pixelated or blocky lighting and shadows that match your art style, Nearest texture filtering will not achieve this effect. Nearest filtering affects only how the engine samples textures — it does not change how the engine renders lighting and shadows.

To achieve pixelated lighting and shadows, use a custom shader to modify LIGHT_VERTEX and SHADOW_VERTEX to snap light sampling to a pixel grid. The following shader snaps lighting to a grid using the floor() function:

shader_type canvas_item;

uniform float pixel_size = 4.0;

void fragment() {
    // Snap lighting and shadows to pixel grid.
    LIGHT_VERTEX.xy = floor(LIGHT_VERTEX.xy / pixel_size) * pixel_size;
    SHADOW_VERTEX = floor(SHADOW_VERTEX / pixel_size) * pixel_size;

    // Normal rendering.
    COLOR = texture(TEXTURE, UV);
}

This works by dividing the position by pixel_size to convert to grid space, using floor() to round down to the nearest grid point, then multiplying back to convert to screen space. The result forces the engine to sample lighting from discrete grid positions, which creates the pixelated effect.

For more information on canvas item shaders, see CanvasItem shaders.

Резкие тени

Резкие тени

Мягкие тени (PCF13, Фильтр Smooth 1.5)

Мягкие тени (PCF13, Фильтр Smooth 1.5)

Мягкие тени с полосатыми артефактами из-за слишком высокого значения фильтра сглаживания (PCF5, фильтр сглаживания 4)

Мягкие тени с полосатыми артефактами из-за слишком высокого значения фильтра сглаживания (PCF5, фильтр сглаживания 4)

Нормальные и зеркальные карты

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

Both PointLight2D and DirectionalLight2D support normal mapping and specular mapping. Normal and specular maps can be assigned to any 2D element, including nodes that inherit from Node2D or Control.

Карта нормалей представляет направление, в котором «указывает» каждый пиксель. Затем эта информация используется движком для правильного применения освещения к 2D-поверхностям физически правдоподобным способом. Карты нормалей обычно создаются из нарисованных вручную карт высот, но их также можно автоматически генерировать из других текстур.

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

Совет

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

Чтобы настроить карты нормалей и/или карты отражений на 2D-узле, создайте новый ресурс CanvasTexture для свойства, которое рисует текстуру узла. Например, на Sprite2D:

Создание ресурса CanvasTexture для узла Sprite2D

Создание ресурса CanvasTexture для узла Sprite2D

Разверните недавно созданный ресурс. Вы можете найти несколько свойств, которые вам нужно будет настроить:

  • Diffuse > Texture: Текстура базового цвета. В этом свойстве загрузите текстуру, которую вы используете для самого спрайта.

  • Normal Map > Texture: Текстура карты нормалей. В этом свойстве загрузите текстуру карты нормалей, которую вы сгенерировали из карты высот (см. совет выше).

  • Specular > Texture: Текстура карты отражений, которая управляет интенсивностью отражений каждого пикселя на диффузной текстуре. Карта отражений обычно серая, но может также содержать цвет для соответствующего умножения цвета отражений. В этом свойстве загрузите текстуру карты отражений, которую вы создали (см. совет выше).

  • Specular > Color: Цветовой множитель для зеркальных отражений.

  • Specular > Shininess: Зеркальный показатель, используемый для отражений. Более низкие значения увеличат яркость отражений и сделают их более рассеянными, в то время как более высокие значения сделают отражения более локализованными. Высокие значения больше подходят для поверхностей, выглядящих мокрыми.

  • Texture > Filter: можно настроить на переопределение режима фильтрации текстур, независимо от того, какое свойство узла установлено (или настройка проекта Rendering > Textures > Canvas Textures > Default Texture Filter).

  • Texture > Repeat:: можно настроить на переопределение режима фильтрации текстур, независимо от того, какое свойство узла установлено (или настройки проекта Рендеринг > Текстуры > Текстуры холста > Повтор текстуры по умолчанию).

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

Использование аддитивных спрайтов как более быстрой альтернативы 2D-освещению

Если вы сталкиваетесь с проблемами производительности при использовании 2D-освещения, возможно, стоит заменить некоторые из них на узлы Sprite2D, которые используют аддитивное смешивание. Это особенно подходит для кратковременных динамических эффектов, таких как пули или взрывы.

Аддитивные спрайты гораздо быстрее рендерятся, поскольку им не нужно проходить через отдельный конвейер рендеринга. Кроме того, этот подход можно использовать с AnimatedSprite2D (или Sprite2D + AnimationPlayer), что позволяет создавать анимированные 2D "светильники".

Однако аддитивные спрайты имеют несколько недостатков по сравнению с 2D-освещением:

  • Формула смешивания неточна по сравнению с "реальным" 2D-освещением. Обычно это не проблема в достаточно освещенных областях, но это не позволяет аддитивным спрайтам правильно освещать области, которые полностью темные.

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

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

Чтобы отобразить спрайт с аддитивным смешиванием, создайте узел Sprite2D и назначьте ему текстуру. В инспекторе прокрутите вниз до раздела CanvasItem > Material, разверните его и щелкните раскрывающийся список рядом со свойством Material. Выберите New CanvasItemMaterial, щелкните только что созданный материал, чтобы отредактировать его, затем установите Blend Mode на Add.