Смешивание кадров с использованием векторов движения
Введение
Моя вариация смешивания кадров, впервые разработанная Guerrilla Games для Killzone 2, в конце статьи вы найдёте ссылки на их статью и другие ресурсы. Цель данного метода заключается в том, чтобы повысить полезность анимированных текстур путём искажения их с motion vectors для процедурной генерации промежуточных кадров. Повышается сложность шейдера и потребление текстурной памяти, но результат стоит того, особенно если речь идёт о кинематографических моментах.
Пример того, что мы поличим используя методику описанную в данной статье:
Те кто из вас, кто знаком с редактированием и композом видео, могут сравнить эту технику с тем, что делает плагин Twixtor от RevisionFX, это, по сути, то же самое, но в нашем случае векторы движения не генерируются «на лету», нам нужно их создать вручную.
Для этого урока я буду использовать UE4, FumeFx для 3dsMax и After Effects с плагином RevisionFX под названием «Motion Vectors: Create» идущий в комплекте с pro версией Twixtor. Вы можете сделать тоже самое и с другим программным обеспечением, главное что бы это ПО могло на выходе давать нормализованные данные вектора движения, но в таком случае результат может отличаться. Итоговый результат данной методики полностью зависит от данных вектора движения, поэтому это может быть самым трудным шагом для правильного выбора и возможно придётся немного поэкспериментировать.
Данные вектора движения
Чтобы отрендерить векторы движения в FumeFX вы должны удостовериться в том, что вы выводите канал velocity прежде чем начнёте симуляцию. Кроме того вам необходимо перейти в Rendering –> Environment, выбрать FusionWorks Renderer, а в параметрах выбрать Create Channels и Image Motion Blur, иначе векторы скорости не будут рендериться. После чего вы можете отрендерить их как отдельный проход именуемый FusionWorks Velocity. Вы можете поиграться с параметром max velocity, дабы убедиться что значение не = 0 или 1, нужно иметь промежуточное значение дабы получить полный диапазон данных движения.
После того как вы перенесёте проход со скоростью в After Effects (или другое по для композа) вам необходимо поправить гамму. Если вы не уверены, то один из способов проверки — удаление синего канала и удостовериться, что пустая область имеет следующие значения:
Стоит отметить, что вам, возможно, придется инвертировать x или y компоненты вашего вектора движения, чтобы убедиться, что Unreal правильно его интерпретирует.
Наряду с векторами движения вы также захотите отрендерить базовую текстуру с альфа-каналом вместе с любыми другими проходами текстур, которые у вас могут быть. Это будет конечным результатом и мы будем использовать текстуру вектора движения, чтобы управлять ими.
Используйте альфа-канал в качестве маски текстуры вектора движения, см. изображение ниже. Вы также можете немного его размыть — позже поможет в смешении кадров в Unreal.
Далее я использую эффект Motion Vectors:Create идущий в комплекте с Twixtor pro для генерации дополнительных векторов движения на основе экрана из базовой текстуры. Я считаю этот шаг обязательным раз уж я хочу использовать одну текстуру вектора движения. Основная идея заключается в генерации некоторой дополнительной информации движения за пределами нашей симуляции, иначе пиксели не будут искажаться за пределами края. Также мне потребовалось инвертировать красный канал дабы соответствовать выходу из FumeFX.
Вы можете увидеть результат векторов Motion Vectors:Create, которые я создал из базовой текстуры слева, и слоя вектора движения FumeFX, добавленного поверх этого справа. Поскольку я замаскировал и размыл слой FumeFX, то он хорошо сочетается с изображением слева.
Ниже приведен пример итоговых текстур, которые вы можете получить. Я использую 8 × 8 SubUV, в итоге 64 кадра, примерно 2 секунды со скоростью 30 кадров в секунду, но мы сможем продлить её в более чем 10 раз, сохраняя при этом одну и ту же воспринимаемую частоту кадров. В своей работе вы скорее всего будет использовать меньшее количество SubUV, дабы уменьшить размер текстуры. Текстуру вектора движения можно значительно уменьшить, я использовал разрешение 512 для базовой текстуры в 4096, но он должен быть несжатым в движке, иначе вы получите много артефактов. Также не забудьте отключить sRGB при импорте в Unreal.
Шейдер
Шейдер довольно прост. Основная идея состоит в том, чтобы создать настраиваемое перекрестное смешивание SubUV, аналогично тому, что автоматически делает SubUV Particle, но нам нужно сделать это вручную, чтобы контролировать следующий шаг. В дополнение к интерполяции из одного промежуточного кадра в следующий, нам необходимо исказить пиксели текущего промежуточного кадра в направлении следующего и аналогично исказить следующий кадр в направлении текущего, чтобы они встречались посередине. Данное искажения мы и будет делать из сделанной ранее текстуры вектора движения.
Граф шейдера созданного по данному руководству:
Функция SubUV
Как вы видите, мы используем функцию в нашем шейдере, дабы получить функциональность SubUV. Мы изменим существующий вариант идущий «в коробке» с Unreal 4, чтобы она выводила координаты текстуры вместо канала RGB, см. изображение ниже.
SubUVCoordinates_Function:
Контроль кадров
Использовать мы будем 2 ноды ранее созданной SubUV функции, одну для текущего кадра и одну для последующего. В целях тестирования мы можем управлять анимацией с выражением времени, как показано ниже, позже мы будем использовать цветной канал частиц или динамический параметр, чтобы управлять им в Cascade. Важно всегда добавлять 1 к значению «Next» для смещения SubUV на один кадр.
Движение в плавающем диапазоне
Мы подключим выход функции SubUV в нашу текстуру вектора движения. После этого мы сначала используем маску компонента для маскировки z-компонента вектора, его мы не используем. Затем мы умножаем значение карты на 2, а затем вычитаем 1, чтобы переместить его в диапазон с плавающей точкой от — 1.0 до + 1.0 — это приведет к тому, что искажение будет отцентрировано. Мы сделаем это для обеих ветвей шейдера, текущего и следующего.
Текущий кадр:
После получения вектора движения в диапазоне float мы будем использовать frac для определения процента того где в кадре мы сейчас находимся, и умножаем величину искажения на основе этого значения, от отсутствия искажения в начале и к полному искажению к концу. Затем мы вычитаем выход из функции SubUV, чтобы добавить искажение к базовой текстуре.
Следующий кадр:
Точно так же, после получения вектора движения в диапазоне с плавающей запятой, мы будем использовать инвертированный Frac для определения процента того, где в кадре мы находимся в текущий момент, но на этот раз в обратную сторону, поэтому в начале полное искажение, а к концу отсутствие оного. Впоследствии мы добавим выход в функцию SubUV, чтобы вычесть искажение из базовой текстуры, изменив направление процесса.
Скалярный параметр Distortion_Strength будет контролировать величину искажения, из описанного выше. Это двойственное значение, как у вашего глазного яблока, оно имеет прямую корреляцию с размером SubUV и скоростью вашей текстуры, если у вас меньше кадров, вы, как правило, хотите, чтобы это значение было выше, UVs нужно будет исказить далее, чтобы догнать следующий кадр. Обычно я использую очень низкие значения в этом параметре.
Перекрёстное смешивание
Мы будем использовать линейное интерполяционное выражение как для текущего, так и для последующего кадра с выражением времени для альфы, чтобы смешать их, когда мы проходим через кадр. Это нужно сделать для каждого канала используемой текстуры.
Возможно по картинкам сложно понять суть происходящего, поэтому кратко объясню — когда кадр начинается, он всё больше искажение по отношению к положению следующего кадра, аналогично этому, следующий кадр искажается по отношению к положению предыдущего кадра, после чего переходит в исходное положение. После того как мы лерпанули их они перекрёсно затухают, что в итоге даёт плавное движение. Это просходит непрерывно от кадра к кадру.
Итого
Я считаю это особенно полезным для крупномасштабных эффектов, замедленных движений и секвенций где эффект в кадре должен развиваться естественным образом. В большинстве случаев визуальные эффекты имеют кратковременное присутствие на экране, в угоду геймплейным требованиям, поэтому обычные анимационные диапазоны и перекрёстное затухание работают на отлично, это определенно не заменяет существующий рабочий процесс, но является очень приятным дополнением в арсенале любого художника.
Основное различие между моим подходом и техникой Guerrilla Games описано в векторах движения. По-видимому, они используют 2 текстуры вектора движения, один из которых специально предназначен для смешивания со следующим кадром, а другой для смешивания с текущим. Насколько я могу судить, мне удалось достичь одинаковой визуальной верности с выгодой для использования меньше текстурной памяти, потому что я использую одну векторную текстуру движения. Тем не менее, их техника может быть более точной при работе с меньшими текстурами SubUV, и я полагаю, что они генерируют свои векторы процедурно с Houdini, убирая часть ручного труда из процесса. В конечном счете, я не знаком с их подходом, чтобы делать какие-либо заключительные призывы, поэтому не принимайте это за чистую монету.
Дата размещения: 3-11-2019, 17:29
- Раздел: Советы на все случаи жизни