[Перевод] Как происходит рендеринг кадра в GTA V

Серия игр Grand Theft Auto прошла долгий путь с момента своего первого релиза в 1997 году. Примерно 2 года назад Rockstar выпустила GTA V. Просто невероятный успех: за 24 часа игру купило 11 миллионов пользователей, побито 7 мировых рекордов подряд. Опробовав новинку на PS3, я был весьма впечатлен как общей картинкой, так и, собственно, техническими характеристиками игры.

Ничто так не портит впечатление от процесса, как экран загрузки, но в GTA V вы можете играть часами, преодолевая бескрайние сотни километров без перебоев. Учитывая передачу солидного потока информации и свойства PS3 (256 Mb оперативной памяти и видеокарта на 256 Mb), я и вовсе удивился, как меня не выбросило из игры на 20-ой минуте. Вот где чудеса техники.

В этой статье я расскажу о проведенном анализе кадра в версии для ПК в среде DirectX 11, которая съедает пару гигов как оперативки, так и графического процессора. Несмотря на то, что мой обзор идет со ссылкой на ПК, я уверен, что большинство пунктов применимо к PS4 и в определенной степени к PS3.

Анализ кадра


Итак, рассмотрим следующий кадр: Майкл на фоне любимого Rapid GT, на заднем плане прекрасный Лос-Сантос.

image

Осторожно! Трафик!
В GTA V используется система отложенного рендеринга, работающая со множеством HDR буферов. На мониторе такие буферы не отображаются корректно, а потому я воспользовался методом Рейнхарда, чтобы все снова привести к формату 8-бит на канал.

Environment Cubemap (кубическая текстура окружающей среды)


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

Как создается кубическая текстура? Для тех, кто не знаком с техникой, поясню. Это как делать панорамные снимки: поставив камеру на штатив, представьте, что вы стоите прямо в центре большого куба и по одной фотографируете все 6 его граней, каждый раз поворачиваясь на 90°.

В игре задействован тот же принцип: каждая грань превращается в HDR-текстуру 128×128. Первая грань располагается следующим образом:

1b91b79ab23c43d28221bf71dbeed0e1.PNG

Та же схема повторяется для 5 оставшихся граней, и в итоге мы получаем кубическую текстуру (cubemap):

image
Так куб выглядит снаружи

67f4bafc5ff44ac3b20ada68617190b6.png
Так он выглядит изнутри (к сожалению, вставить на Хабр панорамное изображение, представленное в первоисточнике в виде js-скрипта, не удалось)

Для каждой грани предусмотрено более 30 вызовов процедуры отрисовки, ячейки графической сетки весьма низкополигональны, а потому отрисовывается только «пейзаж» (местность, небо, некоторые здания), персонажи и авто остаются нетронутыми.

Вот почему в игре, если смотреть из автомобиля, панорама выглядит отлично, а другие машины и персонажи — нет.

От кубической текстуры к текстуре двойного параболоида


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

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

08724a7b288b4cd19dd80e2226613d46.png
Куб в «развороте» и полученные «полушария»

Для чего нужны подобные трансформации? Думаю, все дело (как всегда) в оптимизации: в кубической текстуре шейдеры фрагментов, теоретически, имеют доступ к 6 граням размером 128×128, в то время как в случае с текстурой двойного параболоида все сводится к 2 «полушариям» 128×128. Кроме того, поскольку большую часть времени камера находится на крыше автомобиля, большинство запросов поступает в верхнюю полусферу.

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

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

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

Выбраковка и уровень детализации


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

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

Здесь-то и обнаруживаются отличия между запуском игры на PS3 (не хватает вычислительной поддержки шейдеров) и ПК или PS4.

Генерирование G-буфера


«Основная» доля рендеринга происходит именно здесь. Все видимые ячейки графической сетки отрисовываются одна за другой, но вместо немедленного расчета степени затенения вызовы отрисовки лишь фиксируют необходимую информацию в отдельных буферах, получивших название G-Buffer. GTA V использует технологию MRT, что позволяет каждому вызову отрисовки фиксировать до 5 специальных команд.

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

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

Генерирование G-буфера
5bdbac9b16cb4874bd2ff34dd3b54541.PNG
Генерирование на 15%

18386ca61aa44bb1a6cb25e87306d6f2.PNG
Генерирование на 30%

b472da396c9f4fb1aeb9239154614f5a.PNG
Генерирование на 50%

798f8b7fea5a4d2a8b46db16260fc1c3.PNG
Генерирование на 75%

d0080faffc5f4df583de2ae66e770dc5.PNG
Генерирование на 100%

За воспроизведение всех этих эффектов отвечают цели рендеринга — LDR-буферы (RGBA с 8 битами на канал), хранящие различную информацию, которая позже понадобится для расчета итоговых показателей затенения:

• Диффузная карта: сохраняет «исходный цвет» ячейки. По сути, она представляет собой свойство материала и, фактически, не меняется при различном освещении. Но видите белые блики на капоте автомобиля? Примечательно то, что в GTA V затенение рассчитывается на основе поступающего солнечного света до формирования, собственно, диффузной карты. Необходимая информация о «смешивании» хранится в альфа-канале (подробнее об этом позже).

• Карта нормалей: сохраняет векторы нормалей для каждого пикселя (R, G, В). Здесь также используется альфа-канал, хотя я и не уверен, каким образом: похоже, он выполняет функцию бинарной маски для отдельных растений, расположенных рядом с камерой;

• Карта бликов. Здесь хранится информация, связанная с бликами / отражениями:

  • Красный: насыщенность блика;
  • Зеленый: глянец (гладкость);
  • Синий: насыщенность промежуточных бликов (обычно постоянный показатель для всех пикселей с изображением одного и того же материала).


• Карта освещенности: судя по всему, красный канал хранит данные об освещенности каждого пикселя за счет солнечного света (основан на данных нормалей пикселей, их положении и направлении поступающих солнечных лучей). Я не совсем уверен насчет зеленого канала, но, похоже, что он отвечает за освещенность за счет дополнительных источников света. Синий канал — данные об эмиссионных свойствах пикселей (ненулевое значение для неоновых ламп). Существенная часть альфа-канала не задействована, разве что для маркировки пикселей, соответствующих коже персонажа или изображению растительности.

Итак, ранее я упомянул о создании команд одновременно для 5 целей рендеринга, но рассказал только о 4 из них.

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

957b22cc549c49c788fbb4c5bb8a3546.PNG
Глубина слева и шаблон справа соответственно

Карта глубины: в ней фиксируется информация о расстоянии каждого пикселя до камеры.

Интуитивно можно было бы ожидать, что отдаленные пиксели будут белыми (глубина 1), а те, что ближе, — темнее. Но это не тот случай: видимо, в GTA V использовали логарифмический Z-буфер, изменив Z. Но зачем? Похоже, дело в числах с плавающей запятой, которые в процессе кодировки гораздо точнее, если их значение близко к 0. Так, изменив Z, можно вводить куда более точные данные о глубине отдаленных объектов, которые, в свою очередь, устраняют Z-погрешности. Учитывая продолжительность игровой сессии, не воспользоваться таким приемом было просто невозможно. Хотя, GTA V и не открыли Америку, ведь аналогичная техника встречается в той же Just Cause 2, например.

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

  • 0×89: персонаж, управляемый игроком;
  • 0×82: автомобиль, управляемый игроком;
  • 0×01: неигровые персонажи;
  • 0×02: транспортные средства, включая машины, велосипеды и так далее;
  • 0×03: растительность и листва;
  • 0×07: небо.


Все эти буферы были сгенерированы благодаря 1900 с лишним вызовам отрисовки.

Обратите внимание, что рендеринг выполнен как будто «задом наперед», что позволяет оптимизировать все необходимые операции с учетом сравнения глубины фрагмента со значением буфера глубины на стадии растеризации: в процессе отрисовки сцены очень многие детали проваливают тест глубины, так как перекрываются близко расположенными пикселями, отрисованными ранее. Если очевидно, что пиксель не пройдет тест глубины, графический процессор может автоматически его пропустить, даже не запуская шейдер. Если же мы имеем дело с шейдерами тяжелых пикселей, уместен только стандартный прямой порядок рендеринга, в то время как «обратный» (алгоритм художника) окажется в этом случае самым неэффективным.
А сейчас хотелось бы сказать пару слов о роли альфа-канала в диффузной карте. Посмотрите на скриншот:

image
Приближенный фрагмент дифузной карты

Видите, что некоторых пикселей не хватает? Это особенно заметно на примере деревьев. Как будто в спрайтах отсутствуют отдельные тексели.

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

Такая модель, действительно, выглядит странно, почти как шахматная доска. Возможно ли что… игра делает рендеринг только для 1 из 2 пикселей?

Чтобы уточнить, я заглянул в D3D байт-код. И вот, пожалуйста:

dp2 r1.y, v0.xyxx, l(0.5, 0.5, 0.0, 0.0)  // Dot product of the pixel's (x,y) with (0.5, 0.5)
frc r1.y, r1.y                            // Keeps only the fractional part: always 0.0 or 0.5
lt r1.y, r1.y, l(0.5)                     // Test if the fractional part is smaller than 0.5

По сути, мы видим условие (X+ Y)% 2 == 0, которое соблюдается только для одного пикселя из 2 (где х и у — координаты пикселя).

Это лишь одна из причин выбраковки пискелей (вторая это значение альфа <0,75), хотя и ее было вполне достаточно для того, чтобы объяснить специфику обнаруженного явления.

Информация о том, какие ячейки отрисовывались в рассмотренном «выборочном» режиме, хранится на альфа-канале диффузной карты, как видно на картинке

Альфа-канал диффузной карты


imageТак почему же некоторые модели отрисовывались именно так? Может, это помогало сохранить заливку или параметры затенения? Я вовсе не хотел сказать, что графические процессоры не предусматривают подобную детализацию: пиксели закрашиваются не по отдельности, а группами 2×2. И речь не о производительности, дело в уровне детализации: такая модель делает закрашенные ячейки более прозрачными за счет разных уровней детализации.

Этот метод называется альфа-стипплинг.

Тени


В игре используются CSM (каскадные карты теней): 4 карты теней формируют текстуры 1024×4096. Каждая карта теней предназначена для разной видимости. Чем чаще повторяются действия, тем шире пирамида видимости камеры, тем больше панорама кадра. Благодаря такому подходу тени объектов возле игрового персонажа имеют более высокое разрешение, чем тени отдаленных предметов. Вот краткий обзор информации о глубине 4 карт:

image

Карты теней


Этот процесс может потребовать немало энергии, так как приходится делать ререндеринг сцены целых 4 раза, но отсечение по пирамиде видимости позволяет опустить обработку ненужных полигонов. В данном случае CSM были созданы в результате 1000 вызовов отрисовки.

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

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

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

image
Тени от солнца и облаков (зеленым)

image
Размытые тени

Несколько слов о размытии: техника не из дешевых, т.к. приходится отдельно заниматься разными текстурами. Таким образом, чтобы облегчить задачу, как раз перед выполнением размытия создается «облегченная» текстура: масштаб буфера тени снижается до 1:8 и делается легкое размытие пиксельным шейдером посредством четырехкратного повторения команды Собрать (). Это позволяет примерно оценить общее количество полностью освещенных пикселей. Впоследствии, когда понадобится полное размытие, в первую очередь, считывается информация об «облегченном» варианте процедуры: как только шейдеру попадается полностью освещенный пиксель, он автоматически выдает единицы и ему не приходится запускать трудоемкий процесс полномасштабного размытия.

imageЯ не буду вдаваться в подробности, так как освятил тему отражения (изображение карты отражения плоскости справа) во второй части и в данной сцене эффект едва заметен. Скажу только, что этот шаг генерирует карту отражения для поверхности океана. Суть принципа сводится к повторной прорисовке сцены (650 вызовов отрисовки) в рамках крошечной текстуры 240×120, но уже в режиме «вверх ногами», чтобы создавалось ощущение отражения в воде.

Преграждение окружающего света в экранном пространстве


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

image
Четкое изображение

image
Размытое изображение

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

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

Комбинация G-буфера


Так, настало время объединить все сгенерированные буферы!

Пиксельный шейдер считывает данные из различных буферов и определяет окончательное значение затенения пикселей в HDR.

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

4cf4f4a5dc3042dcb41e21b55f9abbe6.png

И мы получаем итоговое изображение:

image

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

Subsurface Scattering (подповерхностное рассеивание)


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

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

7340e6089d564c12bec9a1b7c6636b43.png

Но как удалось запустить SSS отдельно для образа Майкла?

Во-первых, вырезается только силуэт. Тут на помощь приходит сгенерированный ранее буфер шаблона: всем пикселям Майкла присвоено значение 0×89. Таким образом, мы можем сконцентрироваться именно на них, но ведь нужно применить SSS только к коже, а не к одежде.

На самом деле, когда объединяли все G-буферы, помимо показателей затенения, хранящихся в RGB, отдельные данные были зафиксированы и в альфа-канале. А точнее, альфа-каналы карты освещенности и карты бликов использовались для создания бинарной маски: пиксели, соответствующие коже Майкла и изображению некоторых растений, помечались единицей в альфа-канале. Другим пикселям, в частности, пикселям одежды, присваивалось значение альфа 0.

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

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

Вода


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

Визуализация воды в GTA V сосредоточена в двух направлениях — отражение и преломление.

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

Океан и бассейны отрисовываются по очереди в режиме MRT. Так одновременно достигается несколько целей:

b78663726c5941449c58ecba0476e8b1.png
Слева диффузия воды, справа непрозрачность

  • Диффузная карта воды: фиксирует исходный цвет воды.
  • Карта непрозрачности воды: в красном канале, по сути, сохраняется информация об отдельных свойствах непрозрачности воды (например, для океана это всегда 0,102, для бассейнов — 0,129). В зеленом канале помечено, насколько глубоко пиксель расположен относительно поверхности воды (глубокие пиксели соответствуют менее прозрачной воде, что требует подключения диффузной карты, в то время как пиксели воды с поверхности гораздо прозрачнее).
  • Обратите внимание: все бассейны визуализируются без привязки к условиям, даже если их, практически, перекрывают данные других ячеек, они все равно хранятся в красном канале. Что касается зеленого канала, где учитываются только реально видимые пиксели, исключительно «водные» пиксели попадают на готовое изображение.

Теперь можем объединить предварительно созданные буферы и сгенерировать карту преломления:

image
Карта преломления для воды

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

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

image
Изображение перед добавлением воды

fe7e9e883f87476eb8817590ccd9fd92.png
Преломление на плоскости, отражение и карты рельефа

image
Изображение после добавления воды

Атмосфера


Создаем карту так называемых объемных теней: она помогает затемнить атмосферу / туман, которые непосредственно не освещены солнцем.

image

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

image
Базовое изображение

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

image
Базовое изображение с добавлением тумана

После визуализируется небо.

image

И в самом конце, вслед за ним, отрисовываются облака.

image
Конечное изображение

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

На этом этапе задействованы отдельные текстуры, напоминающие эффект шума Перлина.

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

a2d6b3cd2abd430fae302b0119d07412.png» alt=«image»/>
Слева плотность облаков, справа нормаль

Прозрачные объекты


Теперь займемся всеми прозрачными объектами: очки, лобовое стекло, пылинки в воздухе…

image

Всего-то потребуется 11 вызовов отрисовки, правда, при обработке пыли придется неоднократно обращаться к инстансингу.

image
Итоговое изображение

Сглаживание разрядности


Помните ранее проведенный краткий экскурс об отдельных деревьях, сглаженных на диффузной карте? Вот так выглядит изображение без сглаживания:

image

Самое время все исправить: запускаем пиксельный шейдер для пост-обработки — и он считывает данные буфера исходного цвета и альфа-канала диффузной карты, чтобы выяснить, какие пиксели сглажены. Для каждого пикселя может понадобиться до 2 соседних пикселей, чтобы определить конечный цвет «сглаженного» элемента.

image
После сглаживания

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

Заметим, однако, что данный фильтр неидеален: в отдельных случаях, видимо, он не справился, я все равно заметил эффект шахматной доски и на PS3, и на ПК.

Тональная компрессия и свечение


До этого обрабатываемое изображение сохранялось в формате HDR: каждый RGB канал хранится в виде 16-битного индекса с плавающей запятой, что позволяло существенно расширить диапазон интенсивности освещения. Но мониторы не способны отображать столь различные значения и сводят все к RGB цвета с 8 битами на канал.

Тональная компрессия осуществляет конвертирование этих значений цвета из HDR в LDR. Есть несколько функций, с помощью которых один формат заменяется другим. Классический вариант, получивший широкое распространение, — метод Рейнхарда (именно его я использовал при создании скриншотов, опубликованных ранее) — дает результаты, близкие к окончательному виду игры.

Но разве в GTA V, действительно, использовали метод Рейнхарда? Придется опять залезть в байт-код шейдера:

// Suppose r0 is the HDR color, r1.xyzw is (A, B, C, D) and r2.yz is (E, F)
mul r3.xy, r1.wwww, r2.yzyy            // (DE, DF)
mul r0.w, r1.y, r1.z                   //  BC
[...]
div r1.w, r2.y, r2.z                   // E/F
[...]
mad r2.xyz, r1.xxxx, r0.xyzx, r0.wwww  // Ax+BC
mad r2.xyz, r0.xyzx, r2.xyzx, r3.xxxx  // x(Ax+BC)+DE
mad r3.xzw, r1.xxxx, r0.xxyz, r1.yyyy  // Ax+B
mad r0.xyz, r0.xyzx, r3.xzwx, r3.yyyy  // x(Ax+B)+ DF
div r0.xyz, r2.xyzx, r0.xyzx           // (x(Ax+BC)+DE) / (x(Ax+B)+DF)
add r0.xyz, -r1.wwww, r0.xyzx          // (x(Ax+BC)+DE) / (x(Ax+B)+DF) - (E/F)

Так, так… что тут у нас? Именно уравнение типа (x(Ax+BC)+DE) / (x(Ax+B)+DF) - (E/F) ознаменовало прорыв Джона Хэбла в киноиндустрии в 2009 году.

Оказывается, в GTA V и речи не идет о методе Рейнхарда, но ведь и принцип из Uncharted 2, согласно которому не обесцвечиваются черные области, тоже не годится.

Процесс преобразования в LDR осуществляется следующим образом:

Разрешение буфера HDR снижается до ¼ от исходного значения.

  • Вычислительный шейдер определяет среднюю яркость буфера, выводя результат в виде текстуры 1×1.
  • Рассчитывается новая экспозиция, за счет чего сцена будет яркой/темной.
  • Фильтр яркости запрашивает только пиксели, имеющие яркость выше определенного значения (задается экспозицией).
  • В этой сцене всего несколько пикселей прошли фильтрацию: некоторые освещенные участки на автомобиле с высокой отражающей способностью.
  • Показатели буфера яркости неоднократно сокращаются вплоть до 1/16 от исходных, а затем увеличиваются до ½ от исходных.
  • К исходным HDR пикселям добавляется свечение, а затем при помощи конвертера из Uncharted 2, цвет преобразуется в LDR. Одновременно производится гамма-коррекция, позволяющая заменить линейные каналы на sRGB.

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

image

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

Так была предпринята попытка имитировать природу человеческого глаза: вы заметили, что после длительного пути по темному туннелю и внезапного выезда на солнце окружающая обстановка некоторое время воспринимается слишком яркой? Затем перестает «резать глаз» и становится «нормальной», а экспозиция адаптируется к новому значению. Похоже, в GTA V пошли еще дальше, максимально приблизив адаптацию экспозиции по линии «Темный → Яркий» к аналогичным свойствам человеческого глаза.

Сглаживание и искажение объектива


Если применяется метод FXAA, то он теперь он определенно уделяет внимание сглаживанию неровных контуров ячеек.

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

image
До искажения

image
После искажения

Пользовательский интерфейс


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

image
Мини-карта

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

image
Изображение перед добавлением мини-карты

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

Да, времени потратили немало, но оно того стоило: вот вам финальный кадр во всей красе!

image

Всего потребовалось 4155 вызовов отрисовки, 1113 текстур и 88 целей рендеринга.


Послесловие от переводчика.

Уважаемые читатели, надеюсь, Вам понравился данный материал. Если это так, то мы, в лице команды ua-hosting.company, подготовим для вас продолжение, размещенное в блоге автора первоисточника.

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

© Habrahabr.ru