Рендеринг кадра в Ni No Kuni 2

Рендеринг кадра в Ni No Kuni 2

Ni No Kuni 2 вышла в марте 2018 года и является второй частью японской ролевой игры, разработанной Level-5.

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

Ni no Kuni 2

Первая часть, Ni No Kuni: Wrath of the white witch, была совместным сотрудничеством со студией Ghiblli, а эта нет. Однако над ней работала большая часть прежней команды, поэтому результатом стала игра с прежней атмосферой, ощущением и художественным стилем.

Это вторая статья про то, какие шаги предпринимает игровой движок для визуализации кадра. Предыдущую, про игру The Witness, можно найти здесь. Как и The Witness, Ni No Kuni 2 (NnK2) использует собственный движок, а не Unreal Engine 4 от Epic или Unity. Однако, в отличие от The Witness, на этот раз никто не вел технический блог о нем (насколько я могу судить).

Игра была выпущена как для PC, так и для PS4. Анализируемая версия здесь будет PC с DirectX 11. Этот анализ не претендует на то, чтобы охватить все тонкости. Лишь те части, которые я нашел наиболее интересными.

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

Наконец, если вы еще не играли, призываю вас сделать это. Игра доступна в магазине Humble Bundle со стимовским DRM и в Steam.

Давайте теперь без лишнего шума перейдем прямо к нему.

Порядок отрисовки кадра

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

Визуализация кадра в игре Ni no Kuni 2

Тень

На первом этапе происходит визуализация теней. В Ni no Kuni 2 используется дв различные карты теней, отличающиеся расстоянием по отношению к игроку. Обе визуализируются в 4k текстуру с 32-битной глубиной.

визуализация тени

Этот метод обработки относится к категории каскадных карт теней (CSM). Цель состоит в том, чтобы увеличить качество тени с сохранением малого использования памяти. Наибольшее разрешение на теневой карте сосредоточено вокруг игрока. Это уменьшет видимые артефакты, и чем дальше от игрока, тем большая площадь будет покрыта одинаковой текстурой.

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

Предварительный проход глубины (Depth PrePass)

Ni No Kuni 2 не использует отложенный конвейер визуализации. Я также исключил прямой конвейер или его вариант Forward+, поскольку я мог находить подсчет списка источников света. Ближе все здесь, видимо, методика, подробно описанная Вольфгангом Энгелем в 2009 году как Light Pre-Pass (ссылка на русское объяснение). Этот метод рассматривал также Адриан Куреж (Andrian Courèges) в своем анализе Deus Ex.

Следуя конвейеру, подробно описанному в статье для алгоритма Light Pre-Pass, рендер начинает работать над картой глубины бок о бок с картой нормалей для сцены. Все прозрачные объекты исключаются из этого прохода.

глубина кадра

Используемая карта глубины – это буфер кадра с размером экрана D24S8, но насколько я могу судить, часть трафарета никогда не используется. По сравнению с другими обширными играми открытого мира, которые решили использовать логарифмическую обратную глубину, NnK2 использовал нормальную карту глубины.  Большая часть информации упакована в последние 25% диапазона 0-1, ближняя плоскость находится на 0,1 и дальняя на 1000.

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

Визуализация потери точности у чисел с плавающей точкой или “почему #gamedev ухудшается вдали от начала координат”

Синяя точка – это конец нужного вектора. Черная точка привязывается к ближайшей отображаемой (в упрощенной сетке на основе чисел с плавающей запятой и только 4 битами мантиссы). Из Твиттера Дугласа.

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

карта нормалей

Карта освещенности

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

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

карта освещенности

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

Отражение света

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

зеленый канал

Зеленый каналкрасный канал

Красный канал

Рендер начинает обработку после многократного уменьшения масштаба  используемых в эффекте текстур. Он обрабатывает текстуры 240×135, в восемь раз меньше, чем разрешение экрана.

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

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

очередной этап визуализации

Проход визуализации цвета

Предварительное вычисление глубины означает, что во время визуализации не используется дорогих операций. Вы не беспокоитесь, что сортировка глубины будет происходить на стороне процессора, и что не будут запущены тяжелые шейдеры. Флаг сравнения глубины для правильного чтения карты теперь стоит в значении Меньше или равно. Запись глубины по-прежнему активна, но не нужна.

Проход визуализации выполняется в равном экранному разрешении,  для 4 разных целей визуализации. Давайте разберем их одну за другой.

визуализация цвета в кадре

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

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

наложение персонажей на текстуру ффона

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

вторая цель визуализации

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

передача вершинных данных

Альфа-канал также используется для хранения скалярного произведения вершин по отношению к камере.

очередная часть визуализации кадра

Четвертая и последняя цель визуализации – это сочетание различной информации, которая будет использоваться позже, давайте разберем ее поэлементно.

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

Синий канал использован в качестве идентификатора, где персонажам задано значение 0.27451. Этот идентификатор будет использован во время прохода ambient occlusion, чтобы отменить все принадлежащие персонажам пиксели.

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

Однородное закрашивание

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

создание контуров

Результат

синий канал

Синий канал

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

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

подготовка к блендингу

Наконец, линейный слой добавляется к основному цвету и одновременно к карте глубины. Однако однородное закрашивание с предыдущего шага по-прежнему очень грубо и нуждается в фильтрации, чтобы избежать наложения. Алгоритм выбора здесь – FXAA. Я не буду вдаваться в подробности, вы можете почитать оригинальную статью тут. В игре использована абсолютно стандартная настройка, хорошо описанная здесь. Те же 1/128 для FXAA_REDUCE_MIN и 1/8 для FXAA_REDUCE_MUM. Они передаются как переменная, поэтому мы можем представить, что создатели игры пытались сделать настройку под свои требования к производительности.

float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);
24: mul r0.x, r0.x, u_fxaaReduceMul.x
25: mul r0.x, r0.x, l(0.250000)
26: max r0.x, r0.x, l(0.007813)

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

после

Последо

До

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

Ambient Occlusion

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

отбрасывание пикселей принадлежащих персонажам

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

тень у ног персонажа

тень добавлена

Послебез тени и АО

До

Сглаживание

Ni no Kuni 2 не использует встроенной множественной выборки сглаживания, вместо этого все делается с использованием SMAA. Та является прямым улучшением уже известной MLAA. Я не буду углубленно рассказывать об этих методах, вы можете найти их в интернете по ссылкам: SMAA и MLAA.

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

этап использования SMAA

Далее следует вычислить пропорцию смешивания с использованием предоставленной карты рисунка. В оригинальной статье про MLAA для покрытия всех случаев рекомендуется использовать 16 шаблонов, здесь слева можно увидеть 112. Однако все они кажутся вариацией веса оригинальных 16. Справа находятся диагональные шаблоны, введенные алгоритмом SMAA, еще 16 были рекомендованы и 80 определены здесь.

шаблоны смешивания

карта с блендингом

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

визуализация кадра после сглаживания

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

Размытие в движении

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

Карта движения визуализируется во время основного прохода визуализации цвета. Мне все еще не ясно, как создается эта карта. Но из того, что я вижу, и из отсутствия входных данных предыдущего кадра можно сделать вывод, что карта движения генерируется путем объединения информации о глубине, движении камеры, движении каркаса. Результат кажется статическим и не основан на каком-либо временном анализе.

карта скоростей смещения в кадре

Красный канал содержит информацию о боковом движении, а зеленый – о вертикальном. Это подтверждается позже тем, что для поиска направления размытия шейдер позже берет только эти данные.

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

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

слишком большое размытие

Глубина резкости

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

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

сцена из Ni no Kuni 2

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

глубина резкости в пейзажах игры

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

артефакты при гауссовом сглаживании

Свечение

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

Для достижения желаемого результата Ni no Kuni 2 использует три разные уменьшенные версии подвергнутого размытию основного цветного изображения.

Во-первых, из цветного изображения извлекается самая яркая область.

снова кадр из NnK2

Оригинальный кадризъяты самые яркие области изображения

Самые яркие части

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

визуализация кадра

На входе

устранение артефактов

Края

// Сэмплирование текстур
float4 tex = _ColorTex.Sample(_ColorTexSampler, IN.param1.xy);
float4 subLum = _SublumTex.Sample(_SublumTexSampler, IN.param1.xy);

// Обнаружение края
float4 sub = subLum - tex;

// Сбор краев на всех каналах
float m = max(max(sub.x, sub.y), sub.z);

// Уменьшение контраста
float3 t = -m.xxx * float3(1.5, 1.5, 1.5) + subLum.xyz;

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

Следующее двунаправленное гауссово размытие применяется в два прохода.

результат гауссового размытия

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

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

изображение уменьшено

сжато в углу

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

До

кадр со свечением

После

UI

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

нет маркера квеста

До

добавлен маркер квеста После

Затем визуализируются статичные элементы UI, присутствующие на экране. Такие как информация о квестовых заданиях справа, внизу минимапа.

не наложен минимап

До

наложение минимапа

После

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

динамические элементы минимапа

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

не закончен минимап

Доокончательная визуализация кадра

После

Заключение

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

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

Источник: https://blog.thomaspoulet.fr/ninokuni2-frame/

Понравилась статья? Поделиться с друзьями:
Автор natalya
Переводит для Вас самые интересные статьи про разработку игр. По образованию физик-программист. Техническими переводами начала подрабатывать еще на старших курсах и постепенно это переросло в основное занятие. Интересуется гуманитарными технологиями, пробует себя в журналистике.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *