Сегодня расскажем о реализации размытия движения (motion blur), «кинематографическом» эффекте графики War Thunder.
Что такое Motion Blur?
Каждый кадр видеоигры отрисовывается «с нуля» и не имеет истории изменений. Кинокамеры и наше зрение устроены иначе: нам нужно какое-то время, чтобы снять кадр, а за это время мир не стоит на месте. Если объект движется, он будет виден в каждом моменте времени снимка, и если объект движется, то на кадре он будет отображён одновременно во всех местах, через которые он прошёл за время съёмки кадра. Так и появляется эффект размытия движения (англ. motion blur).
Разберёмся в основах
Для симуляции эффекта размытия движения нам необходимо знать, как каждый пиксель сместился относительно предыдущего кадра. Каждая анимация, каждый динамический эффект должны сообщить свои текущие координаты и координаты в предшествующем кадре. Это могло стать самой сложной частью работы, но, к счастью, у нас в игре уже настроена такая система для эффектов сглаживания. Было несколько анимаций, которые её не поддерживали, и эффект размытия в движении превращал их в огромные смазанные пятна, — мы быстро нашли их и исправили!
За отправную точку мы приняли проверенную технологию построения размытия в движении, почитать о которой можно по ссылке (англ.).
В общем и целом мы берём точку, в которой пиксель был в прошлом кадре, затем точку, в которой он сейчас, и размываем пиксель между этими точками. Чтобы сделать вычисления более эффективными и сгладить некоторые края, линия между пикселями также размывается дальше по направлению между пикселями. Чтобы ещё больше ускорить процесс создания эффекта, в некоторых случаях такие решения принимаются для блоков пикселей, которые движутся в одном направлении.
Расстояние каждого пикселя от камеры также важно, чтобы отдельно размывать изображения на переднем и заднем планах. Размытая линия пикселя фона иногда может проходить за неподвижно стоящим чётким объектом на переднем плане. В других случаях наоборот, нам нужно сохранить фон резким, размыв движения пикселя на переднем плане. Когда два объекта размываются вместе в одном пикселе, нужно также учитывать их скорости, потому что иногда ни один из них не должен оставаться резким.
Сложности реализации
Само собой, базовая технология потребовала настройки под наши нужды. Чтобы решить, как размыть пиксель, нам нужно знать его скорость. Но что, если в одной точке видно больше одного объекта? Без доработок алгоритм размытия «не видит» прозрачных объектов.
Вот кадр, где мы видим лес сквозь стеклянный фонарь кабины падающего в «штопоре» истребителя. Тут в одном пикселе экрана объекты с разной скоростью — фонарь кабины неподвижен, а лес на фоне очень быстро движется. Мы решили пойти тем же путём, как и с разделением видимых объектов на передний план и фон: то, что мы видим через стекло, мы относим к одной категории, в то время как непосредственно видимые объекты — к другой. Мы не размываем одну категорию поверх другой, а допускаем смешивание внутри категорий. Таким образом мы получаем изображение, где фон размывается через стекло, но само стекло может сохранять свой чёткий силуэт.
Примечание: на момент публикации данный алгоритм действует только на максимальных настройках размытия движения.
Ограничения
Поскольку мы точно знаем только одну скорость в каждом пикселе экрана, быстро движущиеся прозрачные объекты не будут размыты, только объекты на фоне. Отсюда получаем, что отражения на таких поверхностях могут быть размыты только так же, как и фон.
Для создания совершенного эффекта нам нужна бы была совершенная информация. Даже если нам известно положение пикселя на экране в настоящем и прошлом кадре, нам ничего не известно о пути его перемещения между кадрами. Мы размываем его движение по прямой линии, «от» и «до», и почти всегда получается хорошо. А что если, скажем, колесо совершило полный оборот за одну смену кадра? Вот тут размытие по прямой уже не работает. Эта проблема пока не имеет решения, вращающиеся колёса требуют особенный алгоритм размытия, который будет работать по другим законам.
Это реалистично?
Размытие движения заметно не только для быстро движущихся объектов, но и когда движется сама камера. Это очень распространённый эффект в кино и фотографии, но наше зрение «цепляется» за быстрый объект, удерживая его в фокусе. Размытие движения в видеоиграх кинематографично — оно выглядит как настоящий фильм, снятый с помощью настоящих камер. Но это не то же самое, что видеть мир своими глазами.
Чтобы лучше имитировать человеческое зрение, мы добавили возможность отключить размытие движения, вызванное движением камеры. Размытие быстрых объектов — пролетающих самолётов, летящих обломков — остаётся, но картинка сохранит четкость, когда вы оглядываетесь по сторонам.
Размытие движения хорошо для игр?
Нам приходилось не раз слышать этот вопрос, внутри команды разработки тоже шли обсуждения. Одни утверждают, что да, размытие передаёт динамику движения и делает игровой процесс более иммерсивным. Другие возражают, что так труднее целиться, пропадает чёткость, необходимая в соревновательной игре.
И те и другие правы. Каждый сам решает, что ему важнее: если результаты, статистика — тогда, наверное, размытие не для вас. Отключайте, без проблем. А вот если бой уже закончен и вы любуетесь повтором, или же просто хотите по-настоящему ощутить скорость вашего самолёта — включайте настройки «Кино» и «Размытие» на максимум!