Как сделать темноту в ue4

Обновлено: 01.07.2024

В данной статье я расскажу как избавиться от ошибки с освещением (lights need to be rebuilt). И так мы создали уровень и сделали освещение, но по каким либо причинам мы какой либо объект передвинули и у нас появилась данная ошибка. Сейчас мы ее будем исправлять.
Для этого нажмите на Build и выберите Lights quality, в в нем самом уже выберите Production.
Затем нам нужно применить все эти изменения. Нажимаем на Build - Lightning only.
Ждем перестроения освещения, мы так же заметим, что чем больше объектов у нас на уровне, тем дольше это самое перестроение у нас будет происходить. Ничего страшного в этом нет, это нормально.
Так мы победили эту ошибку и научились перестраивать освещение на нашем уровне. Для тех кто не чего так и не понял, попрошу удалить Unreal Engine либо посмотреть видео, которое я еще и снял. Ну может я сам пишу так что ни кто не понимает. В общем смотрим. Так же ставим лайк и оставляем комментарии. Всем спасибо.

Создание области видимости с затенением [UE4] Unreal Engine 4, Tuturial, Гифка, Видео, Длиннопост

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

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

В данном примере мы будем использовать процедурную сетку и трассировку линий. А для того чтобы избежать лишнего использования ресурсов и не создавать избыточные элементы сетки, напишем, основываясь на методе половинного деления, функцию, которая будет уточнять положение границ объектов. На картинке выше красным показаны базовые линии сетки (в данном примере их всего 4 на область видимости с углом 90 градусов), а синим — линии сетки, которые образовались после уточнения границ (их 10, так как для каждой границы создается две линии). И этого хватило чтобы правильно отрисовать тени.

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

Добавление трассировки линий к персонажу

Создаем новый проект. За основу берем "Blueprint" шаблон "ThirdPerson" со стартовым набором.

Переходим в папку Content/ThirdPersonBP/Blueprints и открываем Blueprint Class "ThirdPersonCharacter". Добавляем компонент "ProceduralMesh" и создаем переменные, которые понадобятся нам в дальнейшей работе.

Создание области видимости с затенением [UE4] Unreal Engine 4, Tuturial, Гифка, Видео, Длиннопост

Все переменные расположены в трех категориях:

- Base - параметры, определяющие размеры области видимости, ее расположение и детализацию;

- Auxiliary - переменные необходимые во время работы;

- Debug - параметры использующиеся при отладке проекта (не являются необходимыми, но сильно упрощаю жизнь).

Обратите внимание, что у переменных "Base" и "Debug" нужно включить "глазик", что позволит менять их в редакторе для каждого персонажа отдельно.

HalfAngle - половинный угол обзора

DeltaAngle - желаемый угол между базовыми (красными) линиями сетки

ExternalRadius - дальность видимости

bUseExternalPrecise - включает или отключает использование функции "PreciseExternalBorders", отвечающей за точное определение внешних границ объектов

PreciseAngle - угол, задающий точность определения границ объектов, при условии, что "bUseExternalPrecise " = "true"

HeightOfCheck - высота на которой проверяется наличие препятствий

HeightOfShow - высота на которой будет отрисовываться область видимости, являющаяся результатом проверки на высоте "HeightOfCheck"

NumberOfSections - Количество элементов базовой сетки (2*HalfAngle/DeltaAngle с округлением в большую сторону)

dAngle - реальный угол между базовыми (красными) линиями сетки (2*HalfAngle/NumberOfParts), может незначительно отличаться от "DeltaAngle"

StartPoint - координаты точки из которой стартуют лучи

HitResults - массив, состоящий из элементов типа "Hit Result", в которых содержатся результаты работы стандартной функции "LineTraceByChannel"

DrawDebugType - позволяет выбрать несколько режимов отрисовки лучей (тип "EDraw Debug Trace")

DebugDrawTime - длительность отрисовки лучей

bRebuild - позволяет перезапустить "ConstructionScript"

PreciseCount - позволяет ограничить количество итераций в функции "BisectionMethod"

ConstructionScript

Во вкладке "ConstructionScript" (картинка сверху) создаем три блока. Блок 1 позволяет перезапустить "ConstructionScript" для конкретного персонажа при изменении значения переменной "bRebuild" из редактора, а в блоках 2 и 3 вызываем функции "Start" и "LineTracing", которые приводятся ниже.

Функция "Start"

Используется для задания начальных параметров, зависящих от параметров из категории "Base"

Создание области видимости с затенением [UE4] Unreal Engine 4, Tuturial, Гифка, Видео, Длиннопост

Из переменных "HeightOfCheck" и "HeightOfShow" вычитается "100" для того, чтобы значения этих переменных равные "0" соответствовали уровню пола.

Функция "LineTracing"

Генерирует лучи в диапазоне углов от "-HalfAngle" до "HalfAngle", если считать от того направления куда смотрит персонаж (обозначим "ActorForwardVector"), с шагом по углу "dAngle" и записывает результаты трассировки в массив "HitResults".

Создание области видимости с затенением [UE4] Unreal Engine 4, Tuturial, Гифка, Видео, Длиннопост

Блок 1. Вычисляем угол между i-ым лучом и "ActorForwardVector".

(получить это направление можно с помощью функции "GetActorForwardVector")

Блок 2. Задаем направление i-ого луча и его длину.

Блок 3. Делаем трассировку i-ого луча с помощью функции "LineTraceByChannel" и добавляем результат в массив "HitResults". По умолчанию до столкновения с каким-либо препятствием луч отображается красным, а после столкновения — зеленым.

Результат работы цикла

Создание области видимости с затенением [UE4] Unreal Engine 4, Tuturial, Гифка, Видео, Длиннопост

Блок 4. После завершения цикла запускаем функцию "CreateProceduralMesh".

Функция "CreateProceduralMesh"

Создает сетку, опираясь на массив "HitResults", который был получен в функции "LineTracing" и уточнен в функции "PreciseExternalBorders", если выбрана соответствующая опция.

Создание области видимости с затенением [UE4] Unreal Engine 4, Tuturial, Гифка, Видео, Длиннопост

Блок 1. Проверяет нужно ли использовать функцию "PreciseExternalBorders" для уточнения границ.

Блоки 2 и 3. Проверяют встретил ли луч какое-нибудь препятствие. Если не встретил, то для создания треугольника берется конец луча, а если встретил, то координата точки взаимодействия. Рассматриваются i-ый и i+1-ый лучи. Результаты записываются в "L_LeftPoint" и "L_RightPoint" соответственно.

Блок 4. Используя встроенную функцию "CreateMeshSection", создает треугольник и применяет к нему материал "MI_Base" (показан ниже). Функция "CreateMeshSection" использует относительные координаты, поэтому мы вычитаем вектор "StartPoint" из координат всех трех точек и отправляем массив из этих точек на вход "Vertices". На вход "Triangles" подается массив, каждые три элемента которого указывают из каких трех точек предыдущего массива нужно составлять очередной треугольник. Стоит обратить внимание на направление обхода, так как от этого зависит направление нормали, а следовательно, увидим ли мы наш треугольник.

Блок 5. Является следствием того, что функция "CreateMeshSection" использует относительные координаты, и из-за этого "ProceduralMesh" поворачивается в два раза быстрее персонажа. Поэтому приходится доворачивать ее назад.

Материал "MI_Base"

Создаем материал "M_Base".

"BlendMode" устанавливаем на "Translucent" и добавляем параметр "BaseColor".

Создание области видимости с затенением [UE4] Unreal Engine 4, Tuturial, Гифка, Видео, Длиннопост

Создаем "Material Instance" под названием "MI_Base".

Сравнение результатов при разных значения "DeltaAngle" с уточнением границ и без уточнения

Так как мы уже подошли к моменту, когда нужно смотреть на получающиеся результаты при разных значения "DeltaAngle" без использования функции "PreciseExternalBorders", то я решил добавить сюда же и результаты с использованием этой функции. А саму функцию "PreciseExternalBorders" рассмотрим чуть позже.

Создание области видимости с затенением [UE4] Unreal Engine 4, Tuturial, Гифка, Видео, Длиннопост

Создание области видимости с затенением [UE4] Unreal Engine 4, Tuturial, Гифка, Видео, Длиннопост

Создание области видимости с затенением [UE4] Unreal Engine 4, Tuturial, Гифка, Видео, Длиннопост

Хочу обратить внимание на то, что граница тени для области с уточнением нисколько не изменила своего положения во всех трех случаях и по-прежнему существенно точнее чем граница области без уточнения, так как "PreciseAngle" равен "0,01°". Отличия можно увидеть на картинках ниже.

Создание области видимости с затенением [UE4] Unreal Engine 4, Tuturial, Гифка, Видео, Длиннопост

Создание области видимости с затенением [UE4] Unreal Engine 4, Tuturial, Гифка, Видео, Длиннопост

Если персонаж не двигается, то такие неточности несильно заметны с "большого" расстояния, но во время движения граница начинает заметно дергаться.

Создание области видимости с затенением [UE4] Unreal Engine 4, Tuturial, Гифка, Видео, Длиннопост

Создание области видимости с затенением [UE4] Unreal Engine 4, Tuturial, Гифка, Видео, Длиннопост

Создание области видимости с затенением [UE4] Unreal Engine 4, Tuturial, Гифка, Видео, Длиннопост

Создание области видимости с затенением [UE4] Unreal Engine 4, Tuturial, Гифка, Видео, Длиннопост

Стоит отметить, что для DeltaAngle = 20° и выбранных параметрах области возможна ситуация, когда на большой дистанции ни один из базовых лучей (красные линии) не попадет в куб, и поэтому положение границ уточняться не будет в любом случае, а следовательно, и куб не будет отбрасывать тень. Учитывая размеры области и кубов, можно сказать, что DeltaAngle = 10° и использование функции "PreciseExternalBorders" гарантировано позволят захватить куб, так как расстояние между концами базовых лучей всегда будет меньше, чем размеры куба.

Функция "PreciseExternalBorders"

Определяет соседние лучи, попадающие в разные объекты (также подходит вариант, когда один луч попадает в объект, а второй нет), и вызывает для них функцию "BisectionMethod", которая уточняет положение границ объектов методом половинного деления.

Создание области видимости с затенением [UE4] Unreal Engine 4, Tuturial, Гифка, Видео, Длиннопост

Блок 1. Добавляет i-ый элемент из массива "HitResults" в локальный массив "L_HitResults"

Блок 2. Определяет попадают ли i-ый и i+1-ый лучи в разные объекты.

Блок 3. Определяет точку, которая пойдет в функцию "BisectionMethod". Если луч попадает в объект, то берется координата точки взаимодействия, а если не попадает, то координата конца.

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

Блок 5. Обновляем массив "HitResults".

Функция "BisectionMethod"

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

Создание области видимости с затенением [UE4] Unreal Engine 4, Tuturial, Гифка, Видео, Длиннопост

Обозначения поясняются чуть ниже при описании локальных переменных.

Создание области видимости с затенением [UE4] Unreal Engine 4, Tuturial, Гифка, Видео, Длиннопост

Создание области видимости с затенением [UE4] Unreal Engine 4, Tuturial, Гифка, Видео, Длиннопост

"L_LeftDirection" - направление левого луча (L)

"L_RightDirection" - направление правого луча (R)

"L_StartPoint" - координаты точки из которой выходят лучи

"L_MidDirection" - биссектриса угла между правым и левым лучом (M)

"L_LeftActor" - объект, в который попал левый луч

"L_RightActor" - объект, в который попал правый луч

"L_CurrentAlpha" - текущий угол между правым и левым лучом (A)

"L_NewHits" - массив, в который добавляются результаты "попаданий" левого и правого луча, после того как угол между ними становится меньше, чем "PreciseAngle".

"L_OtherActors" - массив из объектов, которые оказались между объектами "L_LeftActor" и "L_RightActor"

Блок 1. Инициализирует необходимые локальные переменные

Блок 2. Сравнивает угол между левым и правым лучом с "PreciseAngle" и проверяет сколько прошло итераций

Блок 3. Определяет угол между левым и правым лучом

Блок 4. Определяет биссектрису угла между левым и правым лучом

Блок 5. Проводит трассировку луча, направленного по биссектрисе

Блок 6. Выбирает какой из лучей (левый или правый) нужно заменить на биссектрису и проверяет наличие других объектов между лучами

Блок 7. Определяет куда попадают лучи после того, как была достигнута нужная точность, и записывает результаты в массив "L_NewHits"

Блок 8. Проверяет остались ли еще дополнительные объекты между лучами, и если остались, то запускает девятый блок. Если же таких объектов нет, то функция завершает свою работу и возвращает список найденных границ ("L_NewHits").

Блок 9. Берет первый объект из дополнительных и запускает уточнение его границ (цикл while).

Схематичный пример наличия дополнительного объекта между лучами.

Создание области видимости с затенением [UE4] Unreal Engine 4, Tuturial, Гифка, Видео, Длиннопост

Сначала была найдена граница между пустотой и шаром (I), а потом — между шаром и треугольником (II).

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

Создание области видимости с затенением [UE4] Unreal Engine 4, Tuturial, Гифка, Видео, Длиннопост

В данном случае между левой стеной и "углом" оказалась область с максимальной дальностью (ее видно на правой картинке в красном круге), что и привело к нежелательному результату на левой картинке. Конечно, в этом примере угол между базовыми лучами равнялся 30° и в такую область может попасть далеко не один дополнительный объект. Если же мы уменьшим угол между лучами, то шансы на наличие дополнительного объекта сильно упадут, хотя и останутся не нулевыми. Поэтому мы и делаем дополнительную проверку (блок 8).

Последние приготовления

Создаем функцию "Update", в которой обновляем переменную "StartPoint" и удаляем старые данные из "HitResults" и "ProceduralMesh".

Переходим во вкладку "EventGraph" и соединяем "EventTick" c функцией "Update" и "LineTracing".

Создание области видимости с затенением [UE4] Unreal Engine 4, Tuturial, Гифка, Видео, Длиннопост

Теперь область видимости готова.

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

В планах добавить уточнение контуров вогнутых тел и внести некоторые изменения в уточнение границ. Есть мысли по поводу того, чтобы разные части области видимости имели разные цвета, в зависимости от высоты объекта, который еще можно увидеть в данной точке. Также хочу постараться для все своих постов по "Blueprint"-ам делать второй вариант на C++.

Если да, то попробуй поиграться с пунктом lightmass resolution на меше(или ландшафте), на котором стоят деревья.

Shadow Bias крутил, но что меняется так и не увидел
shadow filrering sharp что на 0 что на 1 никакой разницы

в рендере ставлю только свет, на high настройках


Разработка компьютерных игр. С чего начать? Это просто! С нуля до разработчика игр: как начать создавать свою игру. Заказать создание игры.


Сегодня я вам расскажу о такой вещи, как IES профиль.


3D Художник Frederic Kielemoes

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

Вот например:

В игре есть светильник ACP SERIES 70W HPS 6X6 DIST от производителя American Electric Lighting.


Его характеристики и фотометрические данные в виде графов.


Как заставить его светить именно так, как он светит в реальности? Если вы попробуете настроить источник освещения в ручную то:
1: Вы потратите уйму времени.
2: У вас все равно не получится. Да, вы сможете добиться примерного результата, но результат будет очень примерный и вы все равно потратите уйму времени.

Здесь нам и приходит на помощь IES, который нам любезно предоставил производитель этого осветительного прибора.

Движок Unreal Engine 4, позволяет загружать фотометрические данные осветительных приборов, как реальных так и сделанных вручную.

Скриншот обычного Spot Light источника света.


Скриншот Spot Light с IES профилем.


Скриншот Spot Light с IES профилем (Немного с другого ракурса).


Ну и естественно для вас, я не поленился записать и видео демонстрацию.

Как видно на уровне применены разные источники освещения, как с профилями IES так и без. Что позволяет делать более ярко выраженную разницу между осветительными приборами. Соответственно — это положительно влияет на восприятие элементов окружения в целом.

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

Следует отметить, что на производительность это практически не влияет.

Spot Light без IES


Spot Light с IES



Как видно влияние на производительность настолько незначительна, что вы ее не сможете ощутить.

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

PS: Пример конечно нужно было выбрать более контрастный, чтобы была сильнее выражена разница.

Читайте также: