Рендеринг с динамическим разрешением

Скачать статью и посетить домашнюю страницу Dynamic Resolution Rendering

Скачать статью Dynamic Resolution Rendering [Eng., PDF 1.1MB]
Домашняя страница Dynamic Resolution Rendering (исходный код, видео)


Введение

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

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

В этой статье мы представим данные по производительности, а также продемонстрируем скриншоты, полученные на системе с предрелизной версией процессора Intel® Core™ i7 второго поколения (микроархитектура Intel® Sandy Bridge, степпинг D1, 4 ядра, 2.4 ГГц, ОЗУ 4ГБ DDR3 1333МГц) с графикой Intel® HD Graphics 3000.

Статья и все приведенные в ней примеры были представлены на конференции разработчиков игр (GDC) в Сан-Франциско в 2011 году. Видео-презентации можно найти на сайте GDC Vault [GDC Vault 2011], слайды доступны на сайте Intel GDC 2011. С момента публикации, автор узнал, что некоторые компании-разработчики игр уже используют данный метод в своих консольных приложения. Презентация Дмитрия Андреева из LucasArts, посвященная антиалиасингу, является единственным открытым ресурсом, в котором затронуты некоторые аспекты используемого здесь метода динамического разрешения [Andreev 2011].

Рис. 1:Вид сцены из точки расположения одной из статичных камер.

Актуальность

GПроизводительность игр почти всегда сильно зависит от выбранного разрешения экрана, а растущая сложность шейдеров и методов постобработки в современных играх всё больше увеличивает затраты на обработку каждого пикселя. Рост разрешения также приводит к увеличению объёма сэмплирования текстур и обмена с рендер-таргетом. Таким образом, критическим моментом является установка разрешения, оптимального для необходимого уровня производительности в конкретной системе. Возможность динамического изменения разрешения позволяет разработчику контролировать производительность и поддерживать стабильный фреймрейт на необходимом уровне, добиваясь оптимального качества игры.

Рендеринг GUI с «родным» разрешением экрана особо важен в ролевых играх, стратегиях реального времени и многопользовательских играх. Иногда, даже на дешёвых системах, игрок может погрузиться в сложный обмен сообщениями, не упуская при этом из виду статус своих соратников.

В конце концов, учитывая всё большую популярность игр на ноутбуках, перед разработчиками игр серьёзно встаёт вопрос экономии энергии. Установки производительности могут приводить к уменьшению частоты CPU и GPU при работе компьютера от батареи, и при наличии рендеринга с динамическим разрешением игра может сама автоматически настроить соответствующее разрешение. В некоторых играх может присутствовать опция пониженного потребления энергии, которая позволит пользователю продлить жизнь батареи и, соответственно, игровой процесс. Тестирование технологии на приведённых здесь примерах показали, что уменьшение разрешения вдвое снижает потребление процессора на 30% при включённой вертикальной синхронизации, то есть при сохранении фреймрейта на прежнем уровне.


Базовые принципы

Базовый принцип рендеринга с динамическим разрешением заключается в использовании вьюпорта, который ограничивает рендеринг частью рендер-таргета, и в последующем масштабировании изображения до полного размера. Например, рендер-таргет может иметь размер (1920, 1080), при этом вьюпорт может располагаться в границах (0, 0) - (1280, 720).

Рис.2:Использование вьюпорта для ограничения размеров рендеринга.

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

DRR_figure3.jpg

Рис. 3:Динамическое разрешение может менять свой размер как в большую (supersampling), так и в меньшую сторону (subsampling)

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

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

// Clamp UVs to texture size
// PSSubSampleRTCurrRatio is the fraction of the render target in use.
float2 clampedUV = min( unclampedUV,  g_PSSubSampleRTCurrRatio.xy );
В случае размытия движения – частой операцией постобработки, при которой используются зависимые чтения из рендер-таргета – требуемые дополнительные вычисления слабо влияют на производительность, поскольку работа шейдера в основном ограничивается скоростью доступа к текстурам.

DRR_figure4.jpg

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

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

// Now convert to give integer height and width for viewport
m_CurrDynamicRTHeight	= floor( (float)m_DynamicRTHeight * m_ScaleY / m_MaxScalingY );
m_CurrDynamicRTWidth	= floor( (float)m_DynamicRTWidth *  m_ScaleX / m_MaxScalingX );

// Recreate scale values from actual viewport values
m_ScaleY = m_CurrDynamicRTHeight * m_MaxScalingY / (float)m_DynamicRTHeight;
m_ScaleX = m_CurrDynamicRTWidth *  m_MaxScalingX / (float)m_DynamicRTWidth;
 

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

Точечный фильтр
Точечный фильтр является быстрым простым фильтром. Масштабирование динамического вьюпорта размером 0.71х от 1280х720 до полного разрешения занимает приблизительно 4.0 мс.

Билинейный фильтр.

При аппаратной поддержке билинейный фильтр работает почти так же быстро, как и точечный фильтр. Он позволяет уменьшать артефакты алиасинга на границах с помощью сглаживания, но это приводит и к размытию сцены. Масштабирование динамического вьюпорта размером 0,71х от 1280х720 до полного разрешения занимает приблизительно 4,0 мс.

Бикубический фильтр
Преимущества бикубического фильтра над билинейным проявляются только при использовании вьюпорта размером 0.5х от бэк-буфера Его производительность в 7 раз ниже даже при использовании быстрого бикубического фильтра [Sigg 2005]. Масштабирование динамического вьюпорта размером 0,71х от 1280х720 до полного разрешения занимает приблизительно 3.5 мс.

Шумовая фильтрация
Добавление некоторого количества шума к точечному фильтру добавляет в изображение высокие частоты, которые, ценой небольших усилий, несколько снижают уровень алиасинга. Реализация данного фильтра в приведённом здесь примере очень проста, и улучшенный фильтр плёночного зерна мог бы поднять художественный уровень рендеринга. Масштабирование динамического вьюпорта размером 0,71х от 1280х720 до полного разрешения занимает приблизительно 0.5 мс.

Шумовой фильтр со смещением
Добавление небольшого случайного смещения к точке сэмплирования при масштабировании снижает алиасинг границ. Данный метод широко применяется в быстрых фильтрах теневых карт. Масштабирование динамического вьюпорта размером 0,71х от 1280х720 до полного разрешения занимает приблизительно 0.7 мс.

Темпоральный антиалиасинг
Данный фильтр требует дополнительных действий при начальном проходе рендеринге, чтобы чётные и нечётные фреймы были сдвинуты относительно друг друга на полпикселя по осям X и Y. При дальнейшей фильтрации артефактов, качество итогового изображения существенно улучшается благодаря удвоенному количеству пикселей. Данный метод фильтрации описывается более подробно в следующем разделе. Масштабирование динамического вьюпорта размером 0,71х от 1280х720 до полного разрешения занимает приблизительно 1.1 мс.. При этом качество изображения практически не уступает картинке при рендеринге с полным разрешением.

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

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

Рис. 5:Базовые принципы работы темпорального антиалиасинга.

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

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


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


Чтобы получить повышенное разрешение текстур, к ним можно применить методы Mip-mapping. Для этого В Microsoft Direct3D* 11 используется D3D11_SAMPLER_DESC MipLODBias = -0.5f. К тому же, при масштабировании мы должны использовать билинейный уменьшающий фильтр (bilinear minification filter): D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT.

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


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

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

Альтернативой такому методу удаления двоения является использование скорости для сэмплирования из предыдущего фрейма в позиции, в которой там находился текущий пиксель. Этот метод используется в CryENGINE* 3, впервые продемонстрированном в игре Crysis* 2 [Crytek 2010]. Интересно, что Дмитрий Андреев из LucasArts рассматривал возможность использования темпорального антиалиасинга, но не стал его применять по причине использования в своём движке динамического разрешения [Andreev 2011]. Однако мы полагаем, что эти методы совместимы, что и показано в коде примера.

Рис.8:Результат применения темпорального антиалиасинга

Эффект размытия в движении

Размытие в движении смазывает пиксели и эффективно удаляет алиасинг. При движении камеры можно использовать пониженное разрешение. Однако в нашем примере в алгоритме контроля разрешения данный приём не используется. На приведённых скриншотах показано, как уменьшение разрешения до 0,71х относительно бэкбуфера позволяет увеличить производительность, почти не теряя сохраняя качество изображения. В сочетании с переменной скоростью сэмплирования в фильтре размытия, это может оказаться хорошим способом уменьшить уровень артефактов, возникающих от недосэмплирования (undersampling) при быстром движением камеры, поддерживая при этом производительность на приемлемом уровне.

Рис. 9:Размытие в движении при отключённом динамическом разрешении.


Рис. 10:Размытие в движении при динамическом разрешении на уровне 0.71х. Отметим уменьшение времени фрейма при сходном качестве результата.

Суперсэмплирование

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

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

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


Очистка рендер-таргета

Поскольку рендеринг с динамическим разрешением не всегда задействует весь рендер-таргет, можно очищать только требуемую его часть. При тестировании в системе на базе Intel® HD Graphics 3000 производительность очистки пиксельного шейдера была выше, чем у стандартной очистки, при динамическом рендеринге с разрешением менее чем 0.71x бэкбуфера размером 1280x720. Во многих случаях можно вообще не чистить рендер-таргеты, поскольку они полностью перезаписываются в каждом фрейме.

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


Масштабирование производительности

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

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

Рис. 11:Производительность метода динамического разрешения при разрешении 1280x720

Контроль разрешения

TВ нашем примере дополнительно к ручным настройкам реализован и метод контроля разрешения. Код этого метода содержится в файле DynamicResolutionRendering.cpp, в функции ControlResolution. Желаемую производительность можно выбирать в пределах между частотой обновления экрана (обычно 60 Гц или 60FPS) и половиной этой частоты (обычно 30FPS).

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

Где S' – это новое соотношение между разрешениями, S - текущее соотношение разрешений, - дельта разрешения, k - константа скорости изменения, T- желаемое время фрейма, t - текущее время фрейма.

Текущее время фрейма получается как среднее внутреннего времени фрейма GPU за вычетом времени present, получаемого с помощью запросов Microsoft DirectX*, и времени фрейма, рассчитанного обычным образом как интервал между соседними фреймами. Знание внутреннего времени фрейма GPU требуется, когда включена синхронизация по вертикальной развертке, поскольку в таком случае время фрейма привязывается к частоте обновления экрана, а нам нужно знать, отличается ли от него реальное время рендеринга фрейма. Усреднение времени фрейма с реальным временем фрейма помогает учесть работу present наравне с некоторой другой работой CPU над фреймом. Если реальное время фрейма существенно превышает внутреннее время фрейма GPU, то этот показатель игнорируется, поскольку обычно вызывается единичными пиковыми нагрузками на стороне центрального процессора, такими как переход из оконного режима в полноэкранный.


Перспективы проекта

Приведённый ниже список содержит некоторые варианты улучшений, которые мы считаем полезными для расширения возможностей рассматриваемой программы:

  • Объединить рендеринг сцены с динамическим разрешением с подобными методами для теневых карт.
  • Использовать этот метод с отдельным механизмом контроля для систем частиц, что позволит улучшить качество рендеринга для систем, состоящих из малого количества частиц, и повысить производительность при повышении скорости заполнения.
  • Метод темпорального антиалиасинга совместим с другими методами антиалиасинга, которые можно применять параллельно.
  • В методе темпорального антиалиасинга можно использовать не простую сумму, а улучшенную взвешенную сумму, зависящую от расстояния до центра пикселя в текущем и предыдущем фрейме. Можно также задействовать зависящее от скорости смещение позиции чтения, как это делается в CryENGINE* 3 [Crytek 2010].
  • Некоторым приложения может быть лучше использовать методы антиалиасинга высокого качества над небольшими участками изображения, например, над главным героем или игровыми блоками, подсвеченными мышкой.

Заключение

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


Ссылки

[Sigg 2005] Christian Sigg, Martin Hadwiger, "Fast Third Order Filtering", GPU Gems 2. Addison-Wesley, 2005.

[Crytek 2010] HPG 2010 "Future graphics in games", Cevat Yerli & Anton Kaplanyan. http://www.crytek.com/cryengine/presentations

[GDC Vault 2011] http://www.gdcvault.com/play/1014646/-SPONSORED-Dynamic-Resolution-Rendering

[Intel GDC 2011] /en-us/articles/intelgdc2011

[Andreev 2011] http://www.gdcvault.com/play/1014550/Anti-aliasing-from-a-Different [PPT 4.6MB]
Для получения подробной информации о возможностях оптимизации компилятора обратитесь к нашему Уведомлению об оптимизации.
Возможность комментирования русскоязычного контента была отключена. Узнать подробнее.