Как сделать карту теней

Обновлено: 03.07.2024

1 Вступление
2 Краткая теория
2.1 ShadowMapping
2.2 Рендер Depth Texture
2.3 Рендер Shadow Map
2.4 Сборка Теней
2.5 Настройка Теней в unity
2.6 Алгоритм фильтрации Percentage Closer Filtering
3 Практика. Пишем шейдер
3.1 Отбрасывание теней
3.2 Получение теней

Вступление

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

Краткая теория

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

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

Unity рендерит реалтайм тени с помощью самого распространенного на данный момент алгоритма - Shadow Mapping.

Shadow Mapping

Shadow Mapping - это алгоритм рендеринга динамических теней, где информация о тенях хранится в текстуре. Главным его достоинством является быстрая отрисовка теней геометрически-сложных объектов.

Для того, чтобы разобраться, как юнити реализует данный алгоритм, создадим простую сцену: куб, две сферы, бросающих на него тень, камера и источник направленного света (directional light).

Теперь посмотрим, как происходит рендер одного кадра нашей сцены. В этом нам поможет инструмент для отладки frame debugger . Откываем Windows->FrameDebugger.
Нажимаем кнопку Enable.
Перед нами появилось окно с какими-то непонятным вещами внутри.

Разложим все по полочкам.
1 . Ползунок, показывающий номер шага. В моем случае номер шага равен 4, а всего 24 шага. Хотя правильно называть это не шагами, а draw call'ми.
2 . Окно вызовов отрисовки (draw call'ов). Здесь находятся сгруппированные draw call'ы.

Это запрос отрисовки, направленный графическому API. Чем запросов больше, тем выше нагрузка.
Для оптимизации draw call'ы однотипных объектов объединяют (батчат / batching)

3 . Окно информации о draw call'е, выбранном во втором окне. Здесь есть данные о шейдере, pass'е(проходе), ключевых словах, смешивании, текстурах, векторах, матрицах, текстурах и т.д.

Что же нам показывает frame debugger ?

Рендер depth texture

Прежде , чем рендерить геометрию, unity делает дополнительный проход, в котором создает depth texture(текстуру глубины). Это текстура, в которой каждый пиксель содержит информацию о "глубине" обектов на сцене.

  • Размер текстуры глубины совпадает с разрешением экрана
  • Значения пикселей в текстуре глубины находятся в диапазоне от 0 до 1 с нелинейным распространением. 0 - далеко от камеры, черный цвет. 1 - близко к камере, белый цвет.
  • Показывает только видимые объекты. Т.е. если один закрыт другим объектом, то информация о нем не будет занесена в текстуру глубины.
  • Рассчитывается с "точки зрения" камеры в clip space //(пространство камеры)

Рендер shadow map

Далее по списку идет рендер карты теней, которая используется для shadow mapping'а.

Идея Shadow mapping очень проста - мы поместим камеру в положение источника света и отрендерим для нее depth map. Её мы будем использовать для проверки видимости объектов. По сути, shadow map будет показывать, какое расстояние прошел луч от источника света, прежде чем столкнулся с объектом. Если расстояние(в shadow_space) от источника света до точки меньше, чем расстояние, закодированное для этой-же точки в shadow map, то это значит, что эта точка затенена.

Т.к. directional light распространяется равномерно и независимо от расстояния, то для него будет использоваться ортогональная камера. Плюс ко всем, directinal light олицетворяет собой солнце, а значит, по идее, расстояние от него до каждой точки должно быть одинаковым, а shadow map очень большой. На самом деле это не так. Расстояние для рендера Shadow map выбирается в зависимости от положения камеры.

Вот так примерно выглядит shadow map для нашей сцены.

  • Размер текстуры задается в настройках теней
  • Значения пикселей в текстуре глубины находятся в диапазоне от 0 до 1 с нелинейным распространением. 0 - далеко от камеры, черный цвет. 1 - близко к камере, белый цвет.
  • Показывает только видимые объекты. Т.е. если один закрыт другим объектом, то информация о нем не будет занесена в текстуру глубины.
  • Рассчитывается с "точки зрения" источника света в clip space
  • Рендерится для каждого отдельного источника света

А почему их четыре ? Это все потому, что мы используем четыре теневых каскада в сцене. Подробнее о них мы поговорим чуть позже.

Сборка теней

Итак, что мы имеем ? У нас есть карта глубины с точки зрения камеры, у нас есть карта глубины с точки зрения источника света. Конечно, они сохранены в разных системах отсчета ( clip spaces), но мы знаем пространственные отношения и направления "взгляда" обоих точек зрения. А это в свою очередь означает, что мы можем сравнивать глубину depth map и shadow map. Другими словами, мы можем сравнивать два вектора(вектор, выходящий из источника света и вектор, выходящий из камеры). Если они, заканчиваются в одной точке и эта точка затенена, то мы сохраняем цвет тени в отдельную текстуру. Если же вектор света или вектор взгляда сталкиваются по пути с каким-либо объектом и не достиюте точки, то она не затенена или ее не видно, следовательно, нам не нужно сохранять значение тени в ней. В итоге получается текстура с тенями. На значения, сохраненные в ней, умножается цвета объетов во время рендера сцены.

clip space shadows final scene

В итоге мы имеем такой алгоритм shadow mapping'а в юнити:

  1. Создание карты глубины камеры (depth map)
  2. Создание карт глубины всех источников света (shadow map)
  3. Вычисление теней
  4. Сборка теней

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

Теперь , когда мы знаем, как происходит ренер теней, можно перейти к изучению их настроек.

Открываем Edit->Project Settings->Quality

В Quality Setting мы устанавливаем параметры для всех источников света. Тем не менее, некоторые из них можно будет переопределить уже на каждом конкретном источнике света в зависимости от его задачи.
1 . Shadows - этот параметр отвечает за качество теней.

  • Diable Shadows - тени не будут рендерится
  • Hard Shadows Only - будет происходить рендер только жестких(hard) теней
  • Hard and Soft Shadows - будет происходить рендер мягких(soft) и жестких(hard) теней в зависимости от настроек источника света

жесткие тени мягкие тени

2 . Shadow Resolution - настройка разрешения карты теней. Чем больше разрешение, тем качественнее на сцене будут тени

  • Low Resolution - размер карты теней с низким разрешением (1024x1024 )
  • Medium Resolution - размер карты теней со средний разрешением (2048x2048 )
  • High Resolution - размер карты теней с высоким разрешением (4096x4096)
  • Very Hight Resolution - размер карты теней с очень высоким разрешением (не особо понятно, в чем разница, размер карты теней 4096x4096)

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

Чем больше текстура, тем качественнее тени, но и ресурсов будет использоваться больше. Особенно это касается памяти. А зачем нам рендерить качественные тени для объектов, находящихся далеко от камеры ? Для них вполне бы подошли текстуры с маленьким разрешением. Эту проблему решают теневые каскады.

Под теневыми каскадами подразумевают разбиение пространства на каскады в зависимости от удаления до камеры. Каждый каскад уже реализует свою карту теней. Именно для них и рендерится несколько теневых карт с разным разрешением.

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

3 . Shadow Projection - параметр, на основе которого выбирается теневой каскад. По умолчанию используется Stable fit.

  • Close Fit - в зависимости от глубины камеры
  • Stable Fit - в зависимости от расстояния до камеры

Close fit cascade Stable fit cascade

4 . Shadow Distance - расстояние от камеры, после которого тени не будут рендерится. По умолчанию стоит 150. При установки значения shadow distance = 8, тень от дальней сферы уже не рендерилась. Так же, при маленьком shadow distance необходимость в теневых каскадах отпадает.
Чем меньше shadow distance, тем быстрее рендерится сцена. У меня количество draw call'ов уменьшилось с 24 до 16.

5 . Shadowmask Mode - в каком режиме будет работать shadowmask (текстура, в которой сохранены тени от статических объектов на другие статические объекты. Используется в mixed-lighting'е)

  • Shadowmask - статические объекты отбрасывают всегда запеченные тени
  • Distance Shadowmask - использование реал-тайм теней до shadow distance, а статических после нее

6 . Shadow Near Plane Offset - смещение ближнего плана(near plane) камеры, которая рендерит теневую карту. По умолчанию равно 3.

7 . Shadow Cascades - количество теневых каскадов.

  • No Cascades - без теневых каскадов, тени ограничиваются только shadow distance
  • Two Cascades - два теневых каскада
  • Four Cascades - четыре теневых каскада

8 . Cascade splits - Панель, где можно настроить расстояние, на котором активируется и выключается каждый из каскадов. Расстояние считается в процентах от shadow distance.

Это были общие настройки для теней. Также в unity можно настроить отображение теней для каждого отдельного источника света.

1 . Shadow Type - тип теней.

  • Hard Shadows - жесткие тени
  • Soft Shadows - мягкие тени

-
2 . Strength - коэффициент, на который умножаются тени при их сборке. 0 - нет теней, 1- черные тени.

3 . Resolution - разрешение карты теней для данного источника света.

  • Use Quality Settings - использует значение, которое мы выставили в Quality Settings
  • Low Resolution - размер карты теней для данного источника света 512x512
  • Medium Resolution - размер карты теней для данного источника света 1024x1024
  • High Resolution - размер карты теней для данного источника света 2048x2048
  • Very Hight Resolution - размер карты теней для данного источника света 4096x4096

4 . Bias - коэффициент, который добавляется к глубине. Он как-бы немного вдавливает тень. По умолчанию равен 0.05. Если выставить слишком большое значение, тень слишком далеко отодвинется от объекта и будет казаться, что она отдельно от него, если слишком маленькое, появится эффект shadow acne.

5 . Normal Bias - делает все то-же самое, что и bias, только выравнивание идет по нормалям объекта. Если установить слишком высокое значение, то тень станет слишком "вжатой в себя" или очень узкой.

6 . Near Plane - смещение ближнего плана камеры для данного источника света.

Алгоритм фильтрации Percentage Closer Filtering (PCF)

PCF - это алгоритм фильтрации, основанный на усреднении значений между соседними текселями тени в shadow map. В нем для каждого пикселя мы берем значения соседних пикселей в Shadow Map и усредняем их. Получается своеобразный переход из затененной в освещенную область. Узнать поподробнее о PCF, а также о других алгоритмах можно здесь

Пишем шейдер

!Переходим! к практике!

  1. Предмет должен отбрасывать тени
  2. Шейдер должен принимать тени от directional light'а
  3. Тени должны быть мягкими

Создадим новый материал, для него создадим новый Unlit шейдер и применим его к сфере.
Как видно на изображении ниже, сфера перестала отбрасывать тень, т.к. в unlit шейдере нет её реализации.

Отбрасывание теней (Casting Shadow)

Итак , перейдем к реализации отбрасывания теней. Если мы сейчас откроем frame debugger, то увидим, что наша unlit сфера не рендерится ни в shadowmap, ни в depth map. Это происходит потому, что в шейдере unlit сферы нет прохода с тэгом "ShadowCaster", из которого движок берет информацию о глубине на основе положения объекта.

Добавим дополнительный проход в наш шейдер:

В этом проходе нам важна только позиция, поэтому просто переведем положение объекта из object space в clip space.
Ну, собственно, вот и все. Теперь наш шейдер пишет глубину, а это значит, что объект отбрасывает тень.
Но тут возникает небольшая проблема: у нас не производится смещения в зависимости от bias'а и normal bias'а.

Чтобы правильно скорректировать положение сферы в зависимости от bias'а, мы применим функции, реализованные в " UnityCG.cginc ":

UnityClipSpaceShadowCasterPos - переводит точку из model space в clip space с поправкой на normal bias

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

Карта теней
Здравствуйте. Пытаюсь сделать тени через карту теней в opengl 3.3. и тени не выводятся. вот коды.

Создать модель движения Солнца вокруг орбиты, Земли вокруг Солнца, Луны вокруг земли
Вот есть набросок, что дальше? :help: Const pi = 3.14 Dim intRev As Single Private Sub.

Нет теней
Ребят, нет теней в Directional Light, почему? Когда создаю новый проэкт, они есть, потом они резко.

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

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

zayats80888,, ну по стандарту кариа теней 1024x1024, но ведь ее можно увеличивать? Сильно ли это будет влиять на производительность, и как оптимизировать карту теней, ибо отрисовку каждый кадр дает 50 фпс при прорисовке мира и 120 в спокойствие, вместо 200-300

Стандарт сам выбираешь по производительности .

Тестировать нужно, где узкое место в коде.

и как оптимизировать карту теней, ибо отрисовку каждый кадр дает 50 фпс при прорисовке мира и 120 в спокойствие, вместо 200-300

Поробуй разрешение карты теней поменьше поставь, или если мир большой, то не нужно на весь мир тени рендерить, а если солнце медленно движется, то и рендери не каждый кадр а через 1с например(или каждый кадр один маленький кусочек рендери, разбей на несколько)

И как мне расчитать отдаление камеры по y координате если солнце смотрит даже п усть и перпендикулярно?

Ну весь твой мир можно уместить в коробку(bounding box), расстояния - диагональ этой коробки - будет достаточно.

zayats80888, Спасибо большое, я разобрался что да как, я упоминал использование glOrtho для параллельности лучей, однако как мне использовать ortho правильно? я видел разные примеры и glOrtho(0, w, 0, h, -1, 1) и glOrtho(0, w, h, 0, 0, 1), какой лучше всего использовать и в чем разница?

Может быть можно как-то также сделать карту теней не имея конкретной позиции, а лишь вектор направления

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

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

А что это даст, нам ведь нужно глубину сравнивать.

обновление посредством рендера это и есть "искривление" - всяко быстрее, чем на процессоре что-то там считать с картинкой.

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

И не забудь поделиться результатами тестов :)

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

zayats80888, аха, за ortho спасибо, но не помогло, много чего порыскал, в итоге посмотрев от позиции источника света понял, проблема вообще с тенями. Я ставлю перспективу 1024, то-есть довольно далеко, но дальность мира 128 на текущей прогрузки (догружается при перемещении игрока), я думаю как раз проблема в дальности глубины перспективы в целом. Суть в том что координаты на карте теней от 0,9999 и там уже идут цифры, поэтому и собственно сама карта теней белая, я думаю проблема в том и есть что цвет 0,9999, может оно как-то округляет ибо тени могут появиться непонятно где, а где-то они могут вообще не появится где нужны, как можно настроить цвет и сделать его более разным, уменьшить перспективу?

Суть в том что координаты на карте теней от 0,9999 и там уже идут цифры, поэтому и собственно сама карта теней белая, я думаю проблема в том и есть что цвет 0,9999, может оно как-то округляет ибо тени могут появиться непонятно где, а где-то они могут вообще не появится где нужны, как можно настроить цвет и сделать его более разным, уменьшить перспективу?

ты уверен что белая? может с буфером что то напортачил обычно с ними один геморой да и код настройки и рендера + шейдера нужны так сложно сказать


Карта теней вероятно, самая трудная часть в создания визуального представления объекта. Мы используем их, чтобы получить запеченные свет и тень.
Они должны быть однозначно развернуты, так что каждая часть модели имеет свое собственное место в UV пространстве, чтобы в итоге получать корректную информацию о свете и тени.
Важно помнить, что разрешение карты теней крошечное по сравнению с размером UV пространства.
Важно также понимать, что чем больше уровень должен быть оптимизирован тем ниже дизайнер уровней должен использовать разрешение на лайтмапах, иногда доходя до 8 на 8 или 16 на 16 в случае с более мелкими объектами.
Эта тенденция требует, чтобы мы оставили много дополнительного пространства вокруг каждой секции из развертки объекта так, чтобы области, которые являются темными,
не воздействовали на светлые и не уничтожали иллюзию визуальной корректности теней в игре.

Есть 3 основных способа создания такой развертки:

BOX UNWRAP

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

PLANAR UNWRAP

Этот способ особенно полезен для плоских конструкций, таких как стены с несколькими фасками или выдавливаниями. Это также очень полезно для больших частей фасадов зданий, таких как, например, многоквартирные дома.
Planar будет разворачивать значительно лучше если использовать неразрывную геометрию, потому что здесь вопрос будет стоять лишь в “расслаблении” сетки развертки.
Иногда так же хорошее правило заключается в том, чтобы убедиться, что на подобной развертке больше места по горизонтали, чем по вертикали, так как отбрасывание теней, как правило, происходит со стороны при слегка повышенном угле,
а не прямо вниз. Так, большее горизонтальное пространство даёт более широкие возможности для построения более резкой тени, из-за тенденции выбора дизайнерами освещения под углом,
чтобы создать более интересные тени, чем при освещении сверху вниз.

CYLINDRICAL UNWRAP

Большинство других форм можно представить как вариации цилиндрической формы, если конечно они не близки к параллелепипедам или плоскостям.
Цилиндрическую развертку хорошо использовать для многих конструкций которые имеют переднюю и боковые части, но не имеют задней, иначе мы бы использовали метод BOX UNWRAP.

Примеры


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

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

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

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

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

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

У некоторых проектов не выходит следовать этим простым правилам, как на скриншоте ниже.

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

Иногда развернуть объект легко, достаточно разбить его на несколько обоснованных частей. А затем просто “расслабить” развертку. Отличный пример объект ниже.

Такая конструкция является по существу цилиндром с плоским основанием поэтому здесь используются эти два основных метода развертки объекта.
Planar разворачивает части геометрии вниз по оси Z, а затем применяется модификатор “расслабления” и немного регулируется положение вершин чтобы убедиться, что ничего не получает слишком мало покрытия.
В середине схожий с основанием случай, здесь центральная часть разделена и использован Planar вместо Cylindrical для того что бы обеспечить большую зону покрытия.
Как всегда, мы больше озабочены охватом, чем чем соотношением сторон 1 на 1. Большим преимуществом будет располагать швы в их реальных местах, это позволит выглядеть теням более естественно.
Если на вашем объекте есть глубокие вырезы, крайне резкие стыки геометрии то это отличное место что бы здесь проложить шов, если конечно он требуется.

Lightmap Coordinates Index

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

UV чарты и отступы

UV чарты

Группы обособленных треугольников с сопредельными UVs называются UV чарты (charts).

Отступы

Разделять развертку на чарты и располагать их отдельно следует если вы хотите исключить воздействие теней одного чарта на другой. Так же делая отступ следует помнить о простом правиле:
Размер отступа должен быть больше чем 4х4 текселя, так как DXT сжатие работает с блоками именно такого размера.

  1. Потраченный впустую отступ
  2. Необходимый отступ

Это означает, что для карты теней разрешением 32, отступы между частями UV развертки должны быть 12,5% от всего UV-пространства.
Однако, имейте в виду, что использование слишком больших отступов между частями UV развертки приведет к трате памяти, отведенной на карту теней, впустую на более высоких разрешениях.
Чем ближе ближе вы сможете расположить UV чарты, тем лучше. Это позволит уменьшить количество растраченной впустую памяти.

Это далеко не идеальная развертка.

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

Лучший способ создания развертки для карты теней является моделирование всего меша как одного непрерывного элемента или создание развертки вручную.

Это даст единую развертку, на которой почти нет швов и которая гораздо более эффективна.

Конечным результатом является меш, который освещается должным образом без каких — либо артефактов.

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

OGL3

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

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

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

Результат расчета освещения (затенения) зависит от направления векторов нормалей. Поддерживаются стандартные типы затенения, использующиеся в Blender, Shading: Flat (используются нормали граней) и Shading: Smooth (используются интерполированные нормали вершин), а также их комбинации.

_images/flat_smooth_shading.jpg

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

Результат применения различных типов затенения и использования редактора нормалей:

Smooth Shading + фаска

Smooth Shading + фаска + редактирование нормалей

Освещение от источников света¶

На сцене может быть несколько (но не менее одного) источников света разного типа.

Типы источников света¶

Поддерживаются источники света следующих типов:

Точечный. Свет распространяется из одной точки равномерно во все стороны, с постепенным затуханием.

“Солнце”. Свет распространяется из бесконечной плоскости прямолинейно в одном направлении, без затухания.

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

Полусфера. Свет распространяется из бесконечной полусферы, без затухания.

Настройка источников света¶

Производится во вкладке Object Data при выборе объекта-лампы.

_images/lighting_setup.jpg

Цветовая характеристика света. Значение по умолчанию (1.0, 1.0, 1.0) (белый).

Интенсивность излучения. Значение по умолчанию 1.0.

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

Параметр затухания. Применяется для источников света типа Point и Spot . Значение по умолчанию 30.0.

Создание отблеска на объектах. По умолчанию включено.

Применение рассеянного освещения к объектам. По умолчанию включено.

Spot Shape > Size

Угол конуса в градусах. Применяется для источников света типа Spot . Значение по умолчанию 45º.

Spot Shape > Blend

Параметр смягчения края светового пятна. Применяется для источников света типа Spot . Значение по умолчанию 0.15.

Источник света используется для расчета изменения времени суток. Применяется для источников света типа “Солнце”. По умолчанию отключено.

Источник света используется для расчета падающих теней. Применяется в случае наличия нескольких источников света. По умолчанию отключено.

Shadow > Clip Start

Расстояние между источником света и ближней плоскостью отсечения. Используется при генерации теней. Значение по умолчанию - 1.001.

Shadow > Clip End

Расстояние между источником света и дальней плоскостью отсечения. Используется при генерации теней Значение по умолчанию - 30.002.

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

Движок поддерживает 3 метода симуляции рассеянного освещения от окружающих объектов.

“Плоское” освещение белым цветом.

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

Освещение с помощью карты окружения - т.н. методика image-based lighting.

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

Активация¶

Включить опцию Environment Lighting во вкладке World .

_images/lighting_environment.jpg

Настройка¶

Интенсивность освещения от окружающей среды. Значение по умолчанию 1.0.

World > Environment Lighting > Environment Color

Выбор метода симуляции рассеянного освещения: White - “плоское” освещение белым цветом, Sky Color - полусферическая модель , Sky Texture - освещение с помощью карты окружения . Значение по умолчанию White .

World > Horizon Color и World > Zenith Color

Если выбрана полусферическая модель рассеянного освещения Sky Color , цвет горизонта и цвет зенита задаются цветоподборщиками World > Horizon Color (цвет горизонта) и World > Zenith Color (цвет зенита). При выборе цвета рекомендуется активировать опцию World > Blend Sky .

World > Use Nodes (Cycles)

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

World > Reflect World

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

World > Render Only Reflection

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

Использование карты окружения¶

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

Включить опцию Environment Lighting во вкладке World .

Выбрать метод Environment Lighting > Sky Texture .

Перейти из вкладки World во вкладку Texture .

Создать карту окружения , загрузить в нее соответствующее изображение.

Для карты окружения на панели Export Options для значения Sky Texture Usage выбрать ENVIRONMENT_LIGHTING или BOTH (опция BOTH активирует также использование этой текстуры в качестве текстуры неба ).

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

Платформой Blend4Web реализуются такие техники, как каскадные карты теней (CSM) и смягченные тени (PCF).

Генерировать тени могут не более четырёх (или трёх, если включен SSAO) источников света одновременно. Если источников света больше (и у всех включён параметр Shadow), будут видны тени только от четырёх из них.

_images/lighting_multiple_shadows.jpg

Активация¶

На объектах, отбрасывающих тени, включить опцию Shadows: Cast во вкладке Object .

На объектах, получающих тени, включить опцию Shadows: Receive во вкладке Object .

Убедиться, что включена опция Shadows AUTO или ON во вкладке Render .

Объекты, имеющие прозрачные материалы с градиентом , не отбрасывают теней.

_images/alpha_shadows.jpg

Настройка¶

В случае наличия нескольких источников света рекомендуется указать, какой именно источник света будет использоваться для расчета падающих теней, включив опцию Shadow > Shadow во вкладке Object Data при выборе объекта-лампы.

Цвет тени определяется настройками освещения от окружающей среды .

Во вкладке Render на панели Shadows находятся дополнительные настройки:

_images/lighting_shadow_settings.jpg

Render Shadows

Включает и выключает рендеринг теней. Возможные значения: ON , OFF и AUTO . Значение по умолчанию - AUTO .

Включает размытие карт теней. По умолчанию включено.

Разрешение используемой карты теней. Значение по умолчанию: 2048 x 2048px.

Количество сэмплов, используемых для размытия карты теней. Возможные значения - 4x, 8x и 16x (значение по умолчанию).

Self-Shadow Polygon Offset

Коэффициент смещения полигона в зависимости от ориентации к источнику света. Значение по умолчанию: 1.

Self-Shadow Normal Offset

Коэффициент смещения полигона по нормали. Значение по умолчанию: 0.010.

Последние две настройки служат для борьбы с артефактами самозатенения. Они проявляются на объектах, одновременно отбрасывающих и принимающих тени. Параметр Self-Shadow Polygon Offset лучше справляется с артефактами во внутренних областях полигонов, а Self-Shadow Normal Offset - в приграничных. Оба параметра приводят к искажению теней, поэтому рекомендуется держать их как можно меньшими.

_images/self_shadow_artifacts.jpg

Тени для точечных ( Point ) источников света генерируются так же, как и для направленных ( Spot ), и падают только в одном направлении, определяемом параметром Rotation .

Включение каскадной модели теней; открывает доступ к расширенным настройкам. Отключено по умолчанию. Не работает, если опция Shadow включена более чем для одного источника света. Для источников света типа Point и Spot поддерживается только один каскад теней.

Эта опция позволяет выбрать один из следующих вариантов наложения теней:

Стандартная модель, использующая одну оптимизированную карту теней, охватывающую всю сцену ( Enable CSM отключена).

Каскады теней ( Enable CSM включена).

Коэффициент размытия теней, позволяющий настроить cмягченные тени. Значение по умолчанию: 3. Коэффициент 0 даст жесткие тени.

_images/blur_radius.jpg

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

Стандартная модель¶

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

Каскады теней¶

Данные настройки поддерживаются только для источников освещения типа Sun . Для других источников каскады автоматически отключаются.

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

При включении предоставляет расширенные настройки:

_images/lighting_cascades.jpg

Количество каскадов теней. Поддерживается от 1 до 4 каскадов. Значение по умолчанию: 1.

CSM First Cascade Border

Размер первого каскада. Значение по умолчанию: 10.0.

CSM Last Cascade Border

Размер последнего каскада. Значение по умолчанию: 100.0.

Размеры промежуточных каскадов интерполируются на основе последних двух параметров.

При настройке следует помнить, что, увеличивая размер каскада, мы получаем на нем менее качественные тени. С другой стороны, уменьшение параметра CSM First Cascade Border приблизит к камере и сделает более заметными последующие менее детальные каскады. Уменьшение параметра CSM Last Cascade Border приведет к исчезновению теней на более близком расстоянии от камеры. Однако, при использовании мягких теней качество в целом улучшится благодаря размытию на границах.

_images/csm_cascade_distance.jpg

Коэффициент размытия на первом каскаде. Значение по умолчанию: 3. Коэффициент 0 даст жесткие тени.

CSM Last Cascade Blur Radius

Коэффициент размытия на последнем каскаде. Значение по умолчанию: 1.5. Коэффициент 0 даст жесткие тени.

Радиус размытия каждого промежуточного каскада интерполируется на основе этих параметров.

Смягченные тени рекомендуется настраивать сначала на первом каскаде опцией CSM First Cascade Blur Radius , а далее на всех остальных с помощью CSM Last Cascade Blur Radius . Часто на последнем каскаде может потребоваться размытие меньшее, нежели на первом. Это нужно для того, чтобы тени на последнем каскаде не стали слишком блеклыми из-за низкой детализации, к тому же это уменьшит нежелательные артефакты самозатенения.

Плавное исчезновение последнего каскада. По умолчанию включено.

Blend Between Cascades

Сглаживание границ между каскадами. По умолчанию включено.

_images/blend_between_cascades.jpg

Цвет фона¶

Цвет фона можно задать несколькими способами:

Установить параметры Horizon Color и Zenith Color на вкладке World в Blender, предварительно выставив опцию World > Render Sky .

Поместить сцену внутрь модели (например, куба или сферы) с направленными внутрь нормалями, с материалом и опциональной текстурой.

Разместить перед камерой поверхность с материалом и опциональной текстурой, присоединить ее к камере связью родитель-потомок. При необходимости настроить расстояние до поверхности, переднюю и заднюю плоскости отсечения камеры.

Настроить динамически генерируемую атмосферу .

Установить параметр движка background_color , используя программный метод config.set() , предварительно отключив опцию World > Render Sky на вкладке World в Blender. Установленное значение используется в качестве аргумента метода WebGL clearColor() . Для получения корректных результатов рекомендуется отключить прозрачность контекста WebGL (параметр alpha ). Такая конфигурация используется по умолчанию в стандартном веб-плеере движка.

В качестве фона можно использовать любой HTML контент, находящийся позади элемента canvas , который используется для рендеринга. Для это необходимо активировать прозрачность контекста WebGL (параметр alpha ), предварительно отключив опцию World > Render Sky на вкладке World в Blender. Для получения корректных результатов рекомендуется выставить полностью прозрачный черный цвет фона. Такая конфигурация используется по умолчанию в стандартном просмотрщике сцен SDK движка.

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