Skyrim — и только блеск кожанки в отражении заднего зеркала

Доброго времени суток, уважаемые граждане Хабрастана! Сегодня мы вводим всеобщее крепостное избирательное право. Рады вам сообщить, что самая демократичная и народная игра сегодня пожаловала к нам на операционный стол.

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

Лороведы всегда поправляют, что это не пятая часть Скайрима, правильно — Древние Свитки 5: Скайрим (Небесный Край), и следующая часть не будет, называться Скайрим, однако, потом сразу две следующие части называли Скайрим. И так, встречайте, Creation Engine — The Elder Scrolls 5: Skyrim 2.5 штуки.

Тодд Говард / Штаб-Квартира Bethesda

Тодд Говард / Штаб-Квартира Bethesda

Начнём с нюансов, есть 2 версии, и одна подделка, итого 2.5 игры. Наш, богом данный Скайрим, работает на новом и очень злом — Creation Engine. Созданный специально для Скайрима. Да, Скайрим, все дополнения, движок и мододельня были созданы Беседкой за 5 лет, командой из 120 человек.

Поэтому первая  версия Creation Engine была, именно, для Скайрим:

Карта версий движка:

a9b8cc0db85e45ae3257e4b63af1b225.png

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

Мы воспользуемся другой курткой, чтобы анализировать это всё и возможно продуктом самого бесполезного технического подразделением в мире — подразделение графических технологий Интел: Nvidia Nsight и Intel Graphics Analyzer.

Однако, нам сразу вставляют палки в колёса и ограничивают доступные API для отладки. Поэтому, с самого начала мы рассмотрим вторую версию игры, которая запущена на DirectX11. Для неё нам понадобится обычный GPA и уже устаревший NSight 2022 — который содержит уже вырезанный Range Profiler, который позволяет хоть как-то исследовать приложения на DirectX 11. Последующие версии нацелены на версии не ниже — DirectX 12 и Vulkan.

Central Park — Тело Кудряша

Начнём анализ со структуры кадра, базовый кадр, с видом на Ривервуд:

Берём кадр, и дробим на составляющие.

68ad520bcea23bfb07e72686ca3232bb.png

У нас есть Цвет до коррекции:

522589b560b981cf9c2bb408318138fe.png

Буфер глубины:

fe23cf536032d647acedc41d4f2d010b.png

Буфер нормали:

812f22fa5e8c279c1998c5d1edf34914.png

Неизвестный цвет:

b8708a27ac0acee69abe60612c5cca2f.png

Трафарет, если достать оружие оно тоже будет в трафарете:

302d9efede18b48ed18a3a11f54b2649.png

Начнём с самого простого — буфер глубины и трафарета. Формат D24S8. В 8-битный канал Stencil буфера — пишется вода и оружие, при этом глубина режется до 24-бит. Раньше использовали повсеместно на DirectX 9, но теперь ограничений по совместимости нету. Формально, это всё ещё дешевле по памяти, но точность глубины могла бы улучшить качество изображения.

Затенение в экранном пространстве

Освещение — одна из важнейших составляющих игр, без преувеличения, половину всего визуала — делает освещение. В Skyrim используется Forward Rendering, в отличии от Отложенного (Differed) Освещения, свет просчитывается на этапе растеризации пикселя. Не имеет значения карта нормалей и глубины, пиксель имеет свой более точный формат на этапе Pixel Shader. Однако, это ограничивает количество источников освещения, не позволяет делать десятки и сотни разных источников в одной сцене. Возрастает нагрузка, каждый пиксель, в не зависимости от радиуса источника освещения и видимости, будет просчитан. Даже, если источник освещает модель с обратной стороны или освещает только пару пикселей, все пиксели модели будут просчитаны. Конечно, перекрытие пикселя, просто уничтожит результат работа, а вычисления были полными.

Ambient Occlusion (AO) / Затенение Окружения — дешёвый метод имитации переотражений от ближайших объектов. Например, вместо просчёта переотражение по всей локации, ищутся только ближайшие объекты и расчёт происходит только с ними, сами алгоритмы упрощены. Большинство физики света — игнорируется

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

Screen Space AO (SSAO) — несмотря на абстрактное название, это очень конкретный метод, созданный Crytek в 2006 году при создании игры Crysis. Алгоритм действительно просчитывает информацию только в экранном пространстве, игнорируя объекты, которые не видны в кадре. Но, все похожие алгоритмы такие как HDAO/HBAO/MBAO/GTAO — несмотря на то, что не содержат, приставку Screen Space, всё ещё считаются только в экранном пространстве.

https://youtu.be/ifdAILHTcZk?si=HWgGdJMTHRKwOu6x

https://youtu.be/ifdAILHTcZk? si=HWgGdJMTHRKwOu6x

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

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

Исторически, SSAO выходил на платформах 2006 года, где было малое количество памяти и небольшое разрешение экрана. Что требовало больших оптимизаций и ещё большими жертвами качества ради уменьшения потребления ресурсов, при этом качество было — менее важным.

SSAO в Скайриме

Наш кадр / AO

Наш кадр / AO

SSAO — появился только в обновлённой версии с выходом Специального Издания. Для SSAO понадобились как раз буфер Нормали и буфер Глубины, так как методом Forward Rendering SSAO не добиться. Буфер глубины был и так, а вот буфер нормали пришлось добавить. Получилась двойная нагрузка на свет:

  1. Сначала проходит Прямое Освещение

  2. Создаются буферы как для Отложенного Освещения

  3. Позже вычисляется Отложенное Освещение только для SSAO

Посмотрите на буфер Нормали — вы видите синий? может голубой/бирюзовый или фиолетовый? Может вы видите какие-либо нормали, которые повернуты вокруг… оси Z в пространстве экрана?

Обычно, 3D нормали используют для задания ориентации в 3-х мерном пространстве, так проще считать, 3D пространство — 3D направление. В экранном 2D пространстве у нас получается странная картина:

  1. Все нормали, которые не смотрят в экран отсекаются и не идут в растеризатор.

  2. Остаются только нормали, которые указывают поворот к сторонам экрана — сверху-вниз и справа-налево.

  3. Остаётся ещё поворот вокруг оси Z, но нормаль — это вектор, направление, которое можно представить как стрелку или прямую линию перпендикулярно полигону.

  4. Тогда какой поворот вокруг оси Z, будет у вектора (линии)?

Беседка пошла ещё дальше, формат буфера нормалей:  

Для выравнивания был использован буфер размером 4 компоненты, а не 3, что нужны для нормали в 3-х мерном пространстве. При это сами каналы используют 8 бит для экономии памяти. Соответственно, простаивает не только Синий-канал, но ещё и Альфа-канал. Получается, что из выделенных 32-х бит, используются только первые 16 бит, вторые 16-бит заполняются нулями, при этом каждая операция проводится сразу с 32-мя битами.

00bdc5da90ec57d64dcc63f5fc77f94f.png

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

Качество постобработки:

  • Разрешение освещения: 256×256

  • Точность: 0,7… градуса

  • Разница между соседними значениями: 1 на 7,5 пикселя

В итоге, такое малое разрешение влияет на качество изображения. Классический SSAO, подразумевает 2 канала по 8 бит для нормалей, что дешевле подхода Беседки, при этом качество тоже самое. Современные и улучшенные версии, конечно используют 16 бит на компоненту для нормалей. Там и точность выше и качество лучше, особенно, под современные разрешения экранов.

Теперь представьте, что будет на экране 1440P и ? Правильно, для них не меняется разрешение непрямого освещения в Скайрим.

И это только один из фокусов в арсенале Беседки.

Конвейер

Общий таймлайн

Общий таймлайн

Поближе

Поближе

В строке RenderTarget видно, что есть 7 основных стадий:

HD

Full HD

Ultra HD

Создание карты отражений

6%

7%

2,5%

Создание карты теней

17%

19%

15%

Вычислительный шейдер

8%

3,2%

9%

Проход буфера глубины

26%

25%

9%

Преобразование теней в экранное пространство

0,2%

0,4%

4%

Рендер сцены

34%

38%

18,0%

Постобработка

8,8%

7,4%

42,5%

Количество пикселей

1 567 645

2 683 746

10 832 553

Среднее количество пикселей на объект

624

1 067,5

4305.5

Лишние пиксели

646 045

610 146

2 538 153

Полезные пиксели %

58,79%

77,27%

76,57%

Разница в кадрах и локациях значительно, пока что рассматриваем только одну локацию. Так же нужно оговорится, что соседние кадры могут иметь разницу в 30–50% по Рендеру Сцены, так как иногда появляются странные объекты Рендера Сцены с 0 видимых пикселей.

Напоминаю количество пикселей разных разрешений:

Высота

Ширина

Пиксели

HD

720

1 280

921 600

FullHD

1 080

1 920

2 073 600

Quad HD

1 440

2 560

3 686 400

UltraHD

2 160

3 840

8 294 400

И наши пиксели:

HD

Full HD

Ultra HD

Лишние пиксели

646 045

610 146

2 538 153

Интересно, что в Full HD разрешении, всего 2 миллиона пикселей, тогда в Ultra HD, получается игра рендерит на самом деле не 4K, а 5.25K, хотя отображает только 4K. Пока вы играете в Ultra HD, вы играете ещё и в Full HD, только не видите. Все пропавшие пиксели были на экране, но потом поверх нарисовали другие.

Это именно тот случай, где никакой Тест Глубины не спасает, а нужно использовать Буфер Видимости, но есть свидетели, оптимизации железа и ничего оптимизировать самому не надо, кто бы им верил.

Рекордный прирост Постобработки

HD

Full HD

Ultra HD

Постобработка

8,8%

7,4%

42,5%

Да, невероятная постробработка почти не грузит видеокарту, но она максимально последовательная и связная. На каждом этапе используется результат предыдущего этапа, а значит параллелизации не будет. Будет бесконечная запись из одного буфера в другой с упором в память. Зато размытие какое интересное, ценой половины кадров. Добавили бы модные Виньетирование,  Хроматическая аберрации и Зернистость, чтобы игру вообще не запускать.

Загадка от Тодда Говарда, на встроенных видеокартах Intel результаты другие:

Nvidia

Intel

Отрисованные пиксели (прошли Z-тест)

2 835k

9 160k

Один и тот же кадр на Intel GPA, воспроизведённый на разных видеокартах.

В чём секрет, пишите в комментариях. А я пока пойду дальше писать, что там и как, столько фокусов ещё в куртке. И не забудьте про Неизвестный Буфер.

© Habrahabr.ru