Прямое освещение каскадными картами теней(затенение всей сцены). Настройки карты тонов

В Source есть несколько объектов, отвечающих за освещение, а также множество разнообразных настроек в зависимости от игры, для которой вы делаете карту. В этом уроке мы начнём с базового освещения для Half-Life 2 и других игр на Source 2007, прежде чем обращаться к более сложным приёмам.

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

  • Работа с освещением, cubemaps и HDR

Базовое освещение

Самый простой способ добавить на карту освещение – это объекты light и light_spot. Они создают «статическое освещение», просчитываемое в компиляторе и хранящееся в особом файле текстур, известном как карта освещения.

Объект light

Данный объект представляет из себя точечный источник освещения, светящий во все стороны. Создайте один такой и загляните в его свойства (меню Object Properties). Перед тем как мы продолжим, хочу обратить ваше внимание на один важный момент. Не присваивайте объектам light имя, если только не собираетесь включать и выключать их. Каждому именованному объекту light соответствует отдельный файл карты освещения, что может серьёзно отразиться на размере и производительности карты.

Выделив поле Brightness, вы увидите четыре значения. Первые три отвечают за красный, зелёный и синий цвета, а четвёртое за интенсивность света. По умолчанию оно установлено на 200, но я заметил, что меньшие значения делают свет мягче и атмосфернее. Следующие несколько опций настраивают эффект HDR.

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

Объект light_spot

Этот объект имитирует направленный свет. Его можно поворачивать, чтобы выбрать направление света. Выделение объекта light_spot покажет конус освещения на 3D-виде.

Свойства у объекта практически те же самые. Следует помнить, что значение яркости (Brightness) должно быть на порядок выше – для начала я рекомендую 600-800 для внутреннего освещения. Углы освещения (ширину пучка света) тоже можно поменять. Поглядывайте на 3D-вид, чтобы увидеть разницу в значениях внутреннего (Inner) и внешнего (Outer) углов. Для видимости на больших расстояниях дальность света также необходимо повышать.

  • Избегайте насыщенных цветов, если не хотите, чтобы карта была похожа на рейв-дискотеку.
  • С направленным светом будет полезно комбинировать обычные объекты light с малым радиусом освещения. Таким образом края конуса будут не такими резкими и пространство вокруг него не будет слишком тёмным.
  • Метод проб и ошибок – лучший способ сделать хорошее освещение. Вы можете использовать инструмент Cordon Tool для компиляции небольшой части карты, с которой работаете в данный момент – так процесс пойдёт быстрее.
  • Изобретательный подход может добавить уникальности даже совершенно невзрачному месту – располагайте источники освещения так, чтобы они отбрасывали интересные тени.
  • Освещение может быть очень полезным, помогая игроку увидеть важный объект или подсказывая нужное направление. Об этом есть (на английском).

Наружное освещение

Стоит отдельно поговорить о том, как сделать освещение «на улице». В Source наружные пространства – это те же комнаты со скайбоксом. Давайте создадим большое пространство и протестируем в нём наружное освещение. Добавьте несколько объектов, чтобы проверить отбрасывание теней. В списке текстур найдите tools/toolsskybox и примените её к «потолку». В игре эта текстура заменяется на скайбокс.

Чтобы поменять небо, зайдите в меню Map>Map Properties и найдите поле SkyBox Texture Name. Со списком доступных текстур неба можно ознакомиться на этой странице Valve Developer Wiki. Убедитесь, что используете текстуру _hdr.

Чтобы свет исходил от скайбокса, вам нужно создать объект light_environment. Его расположение роли не играет. Свойства его тоже не сильно отличаются от других объектов освещения. Однако, есть две особенных настройки яркости: Brightness отвечает за направленный свет, идущий от «солнца», а Ambient за свет «в тени» (за пределами углов освещения солнца). Настройки Pitch Yaw Roll отвечают за направление света. Все они достаточно сложны в понимании, но страница на Developer Wiki включает примеры настроек для каждого неба, и вы можете придерживаться их в точности, либо немного изменять под свои нужды.

Компиляция с освещением

К этому времени вы уже должны освоиться с основными настройками компиляции. В окне Run Map выберите Expert для дополнительных настроек, связанных с освещением. На этом виде доступны несколько заранее подготовленных конфигураций с балансом производительности и картинки. Эффект настроек VIS будет рассмотрен в уроке по дистанции обзора.

Сейчас просто запомните, что пропуск настроек VIS намного ускорит компиляцию, но снизит производительность карты (и создаст проблемы с водой). Компиляция HDR сделает свет наиболее красивым, но займёт гораздо больше времени. Последний флажок $game отвечает за запуск игры после компиляции.

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

Ознакомившись с первой частью урока, вы уже должны иметь представление о базовых возможностях Source в плане освещения. Давайте же рассмотрим и более продвинутые приёмы, которые может предложить движок, включая дополнительные возможности Portal 2, CS:GO и Dota 2.

Настройки карты тонов

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

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

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

Масштаб карты освещения

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

Для примера создадим комнату с освещением light_spot и несколькими блоками для проверки теней. Выберите Toggle texture application и на 3D-виде выделите несколько поверхностей возле источника освещения. Теперь вы можете изменить параметр Lightmap Scale. Меньшие значения эквиваленты повышенному разрешению. Чтобы разница была более наглядной, измените камеру 3D-вида на 3D Lightmap grid.

На изображении показано сравнение двух параметров в игре. Слева установлено значение 16 (по умолчанию), справа 2. Во втором случае тени более чёткие и лучше заметны.

Не увлекайтесь этой опцией, потому что она серьёзно влияет на размер файлов и производительность карты.

Динамическое освещение и тени

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

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

Тени от моделей и shadow_control

В модах к Half-Life 2, CS:S, Portal 1 и Source Base модели и NPC отбрасывали тени с помощью одного базового метода «render to texture», работающего, как показано на картинке.

Все тени отбрасываются в одном направлении, задаваемом объектом shadow_control. Чтобы тени падали под правильным углом, настройки Pitch Yaw Roll в свойствах shadow_control должны совпадать с углами освещения объекта light_environment.

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

В играх Left 4 Dead, Portal 2, и Alien Swarm тени могут зависеть от ближайшего источника освещения, что задаётся в свойствах shadow_control и соответствующих объектах освещения. Не рекомендуется создавать много таких объектов в одной зоне, иначе при движении объектов и игрока тени будут менять направление случайным образом или вовсе не менять его.

Проецируемые текстуры

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

Для следующего примера я использовал инструменты Portal 2 Authoring Tools. Создаём объект env_projectedtexture, его можно вращать и передвигать, как и любой источник освещения. Загляните в свойства, тут нам кое-что понадобится. Убедитесь, что параметр Enable Shadows выставлен на Yes и увеличьте значение FarZ, чтобы свет покрывал большее расстояние. Для изменения внешнего вида можете задать другое имя текстуры в поле Texture name, но имейте в виду, что большинство материалов не предназначены для этой цели! Также добавьте на карту обычный объект light.

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

Технология проецируемых текстур работала и в ранних играх на Source, включая Half-Life 2, где она применялась для динамического света от фонарика игрока. Однако, их не рекомендуется использовать из-за конфликта с фонариком при одновременном задействовании.

Глобальное динамическое освещение

В Dota 2 и CS:GO есть свои новые объекты для динамического освещения.

В CS:GO используется env_cascade_lighting. Он просто помещается на карту и работает в паре с light_environment, излучая динамический свет из скайбокса. Объект использует так называемую каскадную карту теней, выдавая куда более впечатляющую и реалистичную картинку по сравнению с возможностями ранних игр.

В Dota 2 работает похожий метод: env_global_light. Этот объект работает по аналогии с проецируемыми текстурами и размещается рядом с фиксированной камерой, создавая тени от всех объектов окружения. В новом редакторе «Source 2» доступен предварительный просмотр такого освещения в реальном времени.

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

Кубические текстуры и эффект HDR

Ваша карта кажется простоватой? Ей не хватает чего-то особенного? В таком случае засиять по-новому ей поможет High Dynamic Range.

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

Что такое кубические текстуры и как они с этим связаны?

Кубические текстуры – это технология, применяющаяся движком Source для отражений, также они играют важную роль в работе эффектов HDR, так как должны генерироваться для Low Dynamic Range (не-HDR) и High Dynamic Range. Мы вернёмся к ним чуть позже.

Как устроен HDR

Технический анализ реализации эффекта HDR на карте можно найти на Valve Developer Wiki .

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

Источники освещения

Первым делом проверяем освещение – в свойствах отвечающих за него объектов есть значения Brightness, Brightness HDR и BrightnessScale HDR.

Brightness – это обычный цвет освещения.

BrightnessHDR – это отдельный цвет для случая, когда задействован HDR, по умолчанию его значение установлено на «-1 -1 -1 1», что значит «Так же, как при LDR».

BrightnessScale HDR – на это значение умножается интенсивность HDR-освещения, если оно работает на карте.

Цвет HDR обычно не меняют, но вы можете заметить, что в HDR-режиме всё становится намного ярче, так что можно чуть убавить множитель яркости.

Скайбокс

Здесь всё просто: убедитесь, что ваша текстура скайбокса поддерживает HDR. Большинство скайбоксов от Valve либо поддерживают HDR, либо имеют HDR-версию. Список скайбоксов и дополнительную информацию по ним можно найти на Valve Developer Wiki .

Компиляция HDR

Здесь ваша карта превращается в HDR-карту: просто включите эффект в настройках. Для этого поставьте флажок «HDR» в настройках рендеринга или выберите HDR-профиль в экспертных настройках.

После этого предстоит ещё кое-что сделать, но давайте пока вернёмся к кубическим текстурам.

Кубические текстуры

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

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

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

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

Технический анализ реализации кубических текстур на карте можно найти на Valve Developer Wiki .

Генерирование кубических текстур

Когда ваша карта готова и кубические текстуры размещены по своим местам, вы компилируете её и запускаете в соответствующей игре. Создание кубических текстур происходит в самой игре (тот простой шаг, который после рендеринга). Консольная команда «buildcubemaps» запускает быстрый процесс снятия скриншотов с позиций объектов env_cubemap и сохранения их в BSP-файл карты. После этого ваша карта может существенно располнеть, в зависимости от числа кубических текстур.

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

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

Скачав Pakrat, открываем файл своей карты и находим кубические текстуры. Они именуются по шаблонам c123_123_123.vtf и c123_123_123.hdr.vtf. Удаляем их и сохраняем карту. Теперь мы можем генерировать новые текстуры, открыв карту в игре.

Команды консоли

Пошаговая инструкция по удалению старых и созданию новых кубических текстур для HDR и LDR:

  1. Открыть BSP-файл в Pakrat
  2. Удалить повреждённые текстуры. Они относятся к типу «Texture» (НЕ «Material»)
  3. Открыть игру
  4. Ввести команды «mat_hdr_level 2» и «mat_specular 0»
  5. Загрузить свою карту: «map название-вашей-карты.bsp»
  6. Загрузить другую карту для очистки кэша (ввести «Maps *» для вывода списка карт)
  7. Ввести команду «mat_hdr_level 0»
  8. Снова загрузить свою карту
  9. Ввести команду «buildcubemaps»

Карта готова, если хотите посмотреть на результат, введите «mat_specular 1» и «mat_hdr_level 2». Загрузите другую карту для очистки кэша, затем можете загружать свою.

Для проверки кубических текстур можно использовать команду «impulse 81», если они отображаются неочевидно.

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

  • Не переименовывайте файл карты, хранящиеся в нём текстуры могут быть привязаны к имени файла. Это не всегда создаёт проблемы, но всё же имейте это в виду.
  • Проверяйте содержимое файла карты в Pakrat, чтобы убедиться в успешном сохранении текстур и обнаружить скрытые большие файлы.
  • Pakrat умеет отображать текстуры – если на их месте одна чернота, значит что-то пошло не так.
  • Иногда образец игры, который запускает Hammer, генерирует текстуры некорректно. Попробуйте запустить полную Steam-версию игры и сгенерировать текстуры в ней.

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

  • Разработка игр
    • Перевод

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

    Часть первая: Динамическое освещение

    На его создание меня вдохновил пост на реддите, где aionskull использовал карты нормалей в Unity для динамического освещения своих спрайтов. А пользователь с ником gpillow запостил в комментах что он сделал что-то похожее в Love2D. Вот тут 8-мб гифка с результатами. За неё спасибо jusksmit’у.

    Итак, что такое динамическое освещение? Это техника в 3D графике, где источник света освещает объекты на сцене. Динамическое потому, что обновляется в реальном времени при движении источника. Довольно стандартная штука в 3D мире и легко применимая к 2D, если, конечно, вы можете использовать преимущества шейдеров.

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

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

    Ок, всё очень здорово, но как получить вектора нормали в 2d игре? Здесь, вообще-то, нет никаких объемных объектов… Однако, здесь нам могут помочь дополнительные текстуры (те самые карты нормалей), в которых будет записана необходимая информация. Я создал 2 таких карты для двух домов в видео повыше и использовал их чтобы посчитать освещение, вот пример:

    В начале вы видите обычный спрайт домика без затенения. На второй части картинки расположена его карта нормалей, кодирующая вектора нормалей в цвет текстуры. У вектора есть (x,y,z) координаты, а у пикселя текстуры есть r,g и b компоненты, так что закодировать нормаль реально просто: Возьмем фасад дома, который направлен на юг. Его нормаль будет вектором с координатами . (По хорошему, нормаль должна быть равна (0, 1, 0), но так как вектор мы определяем от -1 до +1, а кодировать надо в промежуток от 0 до 1, то, видимо, автор решил не запариваться и сразу считать нормали от -0.5 до +0.5. прим. перев.)

    RGB значения не могут быть отрицательными, так что мы подвинем все значения на 0.5: . Ну и ещё RGB обычно представляется в числе от 0 до 255, так что мы домножим на 255 и получим , или, другими словами, вектор «на юг» будет вот этим светло-зеленым на карте нормалей.

    Теперь, когда у нас есть нормали, мы можем позволить графической карте сделать её магию.
    Я использую ImpactJS , у него неплохая совместимость с WebGL2D . (Он платный, я рекомендую pixi.js или любая другая графическая библиотека с webgl рендерером. Если знаете ещё аналоги - пишите в комменты! прим. перев.) Используя WebGL2D мы можем легко добавить пиксельный шейдер для освещения:

    #ifdef GL_ES precision highp float; #endif varying vec2 vTextureCoord; uniform sampler2D uSampler; uniform vec3 lightDirection; uniform vec4 lightColor; void main(void) { // Берем вектор нормали из текстуры vec4 rawNormal = texture2D(uSampler, vTextureCoord); // Если альфа-канал равен нулю, то ничего не делаем: if(rawNormal.a == 0.0) { gl_FragColor = vec4(0, 0, 0, 0); } else { // Транслируем из RGB в вектор, а именно из 0..1 в -0.5..+0.5 rawNormal -= 0.5; // Вычисляем уровень освещенности float lightWeight = dot(normalize(rawNormal.xyz), normalize(lightDirection)); lightWeight = max(lightWeight, 0.0); // И записываем в пиксель gl_FragColor = lightColor * lightWeight; } }

    Пара заметок: У нас получается попиксельное освещение, которое немного отличается от вершинного освещения (обычного в 3d). Выбора особого нет, так как вершины в 2d бессмысленны (их всего 4 штуки для отображения плоскости на сцене). Но, вообще-то, это не проблема, попиксельное освещение гораздо более точное. Также следует отметить, что шейдер рендерит только освещение, без основного спрайта. Придется признать, я немного жульничаю, ведь на самом деле я не освещаю свой спрайт, а, скорее, затеняю его и в lightColor я передаю темно-серый цвет. Настоящее освещение пикселей, а именно повышение яркости, выглядит хуже, пиксели кажутся «вытертыми». У этой проблемы есть решения, но сейчас это непринципиально.

    Часть вторая: рисование теней.

    Отбрасывание теней в 3D - хорошо изученная проблема с известными решениями, типа рейтрейсинга или shadow-mapping’а . Однако, я затруднился найти какое-нибудь приемлимое готовое решение для 2d, пришлось делать самому, думаю получилось нормально, хотя и у него есть пара недостатков.

    Вкратце, будем рисовать линию от пикселя на сцене к солнцу и проверять, есть ли какое-нибудь препятствие. Если есть - то пиксель в тени, если нет - на солнце, так что, впринципе, ничего сложного.

    Шейдер принимает xyAngle и zAngle , которые отвечают за то, где находится солнце. Так как оно очень далеко, то лучи света будут параллельны, и, соответственно, эти два угла будут одинаковы для всех пикселей. Также, шейдер будет принимать карту высот мира. Она будет показывать высоту всех объектов, зданий, деревьев и т.д. Если пиксель принадлежит зданию, то значение пикселя будет примерно 10, и означать, что высота здания в данной точке - 10 пикселей.

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


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


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

    Вот код шейдера в упрощенной/псевдо форме:

    Void main(void) { float alpha = 0.0; if(isInShadow()) { alpha = 0.5; } gl_FragColor = vec4(0, 0, 0, alpha); } bool isInShadow() { float height = getHeight(currentPixel); float distance = 0; for(int i = 0; i < 100; ++i) { distance += moveALittle(); vec2 otherPixel = getPixelAt(distance); float otherHeight = getHeight(otherPixel); if(otherHeight > height) { float traceHeight = getTraceHeightAt(distance); if(traceHeight <= otherHeight) { return true; } } } return false; }

    А вот и весь код:

    #ifdef GL_ES precision highp float; #endif vec2 extrude(vec2 other, float angle, float length) { float x = length * cos(angle); float y = length * sin(angle); return vec2(other.x + x, other.y + y); } float getHeightAt(vec2 texCoord, float xyAngle, float distance, sampler2D heightMap) { vec2 newTexCoord = extrude(texCoord, xyAngle, distance); return texture2D(heightMap, newTexCoord).r; } float getTraceHeight(float height, float zAngle, float distance) { return distance * tan(zAngle) + height; } bool isInShadow(float xyAngle, float zAngle, sampler2D heightMap, vec2 texCoord, float step) { float distance; float height; float otherHeight; float traceHeight; height = texture2D(heightMap, texCoord).r; for(int i = 0; i < 100; ++i) { distance = step * float(i); otherHeight = getHeightAt(texCoord, xyAngle, distance, heightMap); if(otherHeight > height) { traceHeight = getTraceHeight(height, zAngle, distance); if(traceHeight <= otherHeight) { return true; } } } return false; } varying vec2 vTextureCoord; uniform sampler2D uHeightMap; uniform float uXYAngle; uniform float uZAngle; uniform int uMaxShadowSteps; uniform float uTexStep; void main(void) { float alpha = 0.0; if(isInShadow(uXYAngle, uZAngle, uHeightMap, uMaxShadowSteps, vTextureCoord, uTexStep)) { alpha = 0.5; } gl_FragColor = vec4(0, 0, 0, alpha); }

    В uTexStep записана длина шага для проверки пикселей. Обычно достаточно 1/heightMap.width или 1/heightMap.height, ибо в OpenGL координаты текстур имеют значения от 0 до 1, так что 1/разрешение как раз даст нам размер одного пикселя.

    Заключение

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

    Описание:
    Теперь в игре Skyrim SE факелы будут отбрасывать динамические тени, настройка освещения от факела...и многое другое.Для игры Skyrim LE этот мод

    Обновление:3.1.1
    - Улучшено меню отладки в МСМ.
    - Незначительные исправления.
    - Скрипт теперь применяется к NPC, если это необходимо.

    Обновление:3.1
    * Добавлено МСМ меню с настройками мода и более подробными описаниями каждой функции.
    * Все модули в МСМ меню можно переключать для повышения совместимости с другими модами.
    * Логика Магического света изменена.
    * Функциональность для НПС работает без проблем в экстерьерах, то есть если у НПС есть факелы или фонари оснащенные, то у них также будут отбрасываться тени, но лучше не применять эту опцию, могут быть баги. Обходной путь возможен с помощью параметров месторасположения.
    * Произведены незначительные исправления.
    * Улучшена производительность скрипта.
    * Совместимость с ELFX (все через скрипт, без дополнительного esp-файла).
    * Совместимость с Wearable Lanterns.
    * Улучшена совместимость с заклинанием Свет свечи.
    * Мод теперь требует наличие skse64 и SkyUI для настроек.
    * ВАЖНО: Если вы обновляетесь с версии 2.2, то удалите мод с помощью книги настроек перед обновлением, в книге есть опция Удалить.

    Журнал изменений:
    - По доп.ссылке добавлен патч для мода "Smoking Torches and Candles".
    - НОВАЯ ОСОБЕННОСТЬ СКАНИРОВАНИЯ. Сканирует область с источниками света с тенями и включает / отключает тени соответственно.
    - Удалены некоторые вещи (нет больше бесконечных ям в тестовой комнате qasmoke).
    - Теперь мод полу-совместим с модами на изменение моделей факелов. Они будут работать только для NPC, игрок использует уникальную модель факела.
    - Опциональная модель факела теперь включена в основной мод.
    * Добавлена заметка об освещение внизу в описании мода.

    Подробнее:
    * Факелы будут отбрасывать динамические тени.
    * Заклинание Свет свечи будет отбрасывать динамические тени.
    * Заклинание Магический свет будет отбрасывать динамические тени (во время полета).
    * Переключение заклинания Свет свечи (использовать его снова, чтобы отключить).
    * Настройки яркости / диапазона света прямо в игре через МСМ меню.
    * Отключение / включение функций мода в определенных местах или в целом.
    * Настройки света осуществляется в игре, такие как яркость, диапазон, тени и автоматическое переключение настроек, чтобы обойти проблемы, связанные с динамическими тенями.
    * НОВАЯ ОСОБЕННОСТЬ СКАНИРОВАНИЯ. Сканирует область для источников света с тенями и включает / отключает тени соответственно.
    * Патч для мода Wearable Lanterns от Chesko: позволяет фонарю который вы носите отбрасывать тени (только спереди на ремне).
    * Все настройки мода через МСМ меню.

    Совместимость:

    * : совместим (патч прилагается)
    * (ELFX): совместим (патч не требуется)
    * : совместим (патч не требуется). В данном моде есть вариант ELE с уже встроенным модом "Torches Cast Shadows".
    * Моды которые вносят изменения в заклинания Свет свечи и Магический свет могут быть несовместимы.

    Заметки:
    * Если у вас в игре после установки мода нет теней от факелов, то переоснастите факел или выкиньте и подберите.

    Требования:
    Skyrim SE 1.5.39.0.8 и выше
    2.0.7 и выше
    5.2 и выше

    При обновлении с 2.2 до 3.1 и выше:
    1. Зайдите куда нибудь в помещение где нет факелов горящих, уберите у себя факел из рук в инвентарь. Удалите мод с помощью книги настроек перед обновлением, в книге есть опция Удалить. Сохранитесь в пустой слот, выйдите из игры.
    2. Удалите файл Player_Shadows.esp из папки Data в игре.
    3. Удалите скрипты _ST_CanFX.pex, _ST_Handler.pex, _ST_Magelight.pex, _ST_Options.pex, _ST_TorchEquip.pex по пути Data/scripts/
    4. Удалите скрипты _ST_CanFX.psc, _ST_Handler.psc, _ST_Magelight.psc, _ST_Options.psc, _ST_TorchEquip.psc по пути Data/scripts/source
    5. Удалите файл lightspellactorfx.nif по пути Data/meshes/magic/
    6. Зайдите в игру, сохранитесь снова но в другой пустой слот сохранений, выйдите из игры и установите новую версию.

    Установка: (можно через NMM менеджер или вручную)
    1. Берем все содержимое из папки Data в архиве и кидаем в папку Data в игре, подтвердите слияние папок, активировать мод.
    2. Если у вас есть мод "Smoking Torches and Candles" (вариант факелы), то скачайте по доп.ссылке патч и установите с заменой файлов, если потребуется.
    3. Если у вас есть мод "Wearable Lanterns", то скачайте по доп.ссылке патч и установите с заменой файлов, если потребуется. Работает только с фонарями которые размещены спереди на ремне. Установить патч после Wearable Lanterns и Torches Cast Shadows.
    4. Как устанавливать моды

    Включает/отключает текстуру окружения карты (т.н. «скайбокс » или попросту небо).
    очень малое или нет.

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

    Подробнее о технологии мип-маппинга

    MIP mapping (от лат. multum in parvo - «много в малом») - метод текстурирования, использующий несколько копий одной текстуры с разной детализацией. Это страшное слово на самом деле означает изменение детализации текстур в зависимости от расстояния от камеры. Методика позволяет избавиться от шума на удалённых объектах и существенно повышает производительность отрисовки.

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

    При использовании этого метода вы увидите изображение в высоком разрешении, находясь близко от объекта, и изображение в низком разрешении при удалении от объекта. MIP-mapping снижает мерцание и «зашумлённость» изображения, возникающие при texture mapping.

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

    Изображение лучше всего выглядит, когда детализация текстуры близка к разрешению экрана. Если разрешение экрана высокое (текстура слишком маленькая/объект очень близко), получается размытое изображение. Если же разрешение текстуры слишком высокое (текстура слишком велика/объект очень далеко), получаем случайные пиксели - а значит, потерю мелких деталей, мерцание и большой процент промахов в кэш. Получается, что лучше иметь несколько текстур разной детализации и накладывать на объект ту, которая наиболее подходит в данной ситуации.

    Чтобы получить доступ к ручной настройке графических эффектов, приведённых ниже, снимите галочку с опции «Автоматическая настройка качества графики» в настройках. Если у вас нет этой опции, ознакомьтесь со статьёй «Отсутствие настроек графики » .

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

    Включает/отключает затенение малоосвещённых участков карты, что позволяет получить более объёмное изображение.
    Влияние на производительность: очень высокое.

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

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

    Static Lights

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

    Персонаж на картинке выше, тот что слева, стоит под статическим светом, свет и тени никак не взаимодействуют с ним; а тот что справа, стоит под стационарным источником света.

    Прямое освещение каскадными картами теней(затенение всей сцены)

    Directional Stationary Lights — специальные источники света, т.к. они поддерживают затенение всей сцены посредством Cascaded Shadow Maps , в момент использования статического затенения.Это очень удобно на уровнях с множеством анимированной растительности; вы хотите движущиеся тени вокруг игрока, но не хотите переплачивать за чрезмерное количество каскадов, для покрытия больших дистанций обзора.С увеличением расстояния, динамические тени растворяются среди статических теней настолько, что переход практически незаметен.Чтобы применить данную возможность, просто измените значение Dynamic Shadow Distance StationaryLight в DirectionalLightStationary , чтобы изменить дистанцию растворения.

    Тени Стационарных источников света

    Динамические объекты (такие как StaticMeshComponents и SkeletalMeshComponents с подвижностью установленной в Movable ) должны быть интегрированны в мировое статическое затенение на дистанции полей карт затенения.Это достигается с помощью теней для каждого объекта.Каждый подвижный объект создаёт 2 динамические тени от стационарного источника света: одну, для управления статической тени проецируемой на объект и вторую, для управления тени проецируемую на остальной мир.С такой настройкой, затенение для стационарных источников света происходит от динамических объектов,которое оно затрагивает.Это означает, что стоимость может варьироваться от очень маленькой, до огромной, в зависимости от того, сколько присутствует динамических объектов.При наличии достаточного количества динамических объектов, более эффективным будет использование Movable освещения. На сцене ниже, сферы — подвижный объект, и все они получают тени от статического мира и проецируют собственные тени, которые соединяются с остальными тенями на отдалении.Фруструм Per Object теней для каждого подвижного объекта также показан.

    Per Object тени используются для подвижных компонентов используя теневую карту границ объекта, поэтому границы должны быть точными. Для скелетал мешей это значит, что они должны иметь physics asset . Для частиц — любой фиксированный ограничивающий бокс должен быть настолько велик, чтобы вместить в себя все частицы.

    Динамические тени

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

    Динамические тени самые ресурсоёмкие.

    Превью теней

    Когда редактируете стационарное или статическое освещение, тени могут стать «незапечёнными», Preview Shadowing показывает вам как будут выглядеть ваши тени после запекания.

    Такие (имеется ввиду незапечённые) тени показываются в редакторе с наложенным поверх текстом «Preview «, для распознавания их среди других теней.

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

    Для того, чтобы получить тени из превью теней, вам необходимо выбрать опцию Build Lighting из меню Build .

    Вы можете отключить превью теней посредством снятия галочки с Preview Shadows Indicator во вьюпорте Show/Visualize меню.

    Если вы хотите изменить текст материал функции освещения, которая проецирует этот текст, то вы можете его найти в: Engine/EditorMaterials/PreviewShadowIndicator.

    Всё вместе

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

    Статьи по теме: