[Перевод] Почему графику в видеоиграх по-прежнему так сложно создавать?

image-loader.svg


Введение


В этом посте будут рассмотрены трудности и аспекты производства, которые нужно учитывать при создании новых методик и алгоритмов рендеринга/графики, особенно в контексте прикладных исследований рендеринга реального времени. Я буду рассказывать о своём личном опыте работы над Witcher 2, Assassin«s Creed 4: Black Flag, Far Cry 4 и God of War.

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

Я слышал вопросы типа «почему эта великолепная исследовательская методика X не используется в продакшене?» и от геймеров, и от коллег из научных кругов. На то всегда бывают очень веские причины!

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

Я вспоминаю об этой теме ещё и каждый раз, когда слышу дискуссии о том, что «фотограмметрия, трассировка лучей, нейронный рендеринг, [вставить любую другую новую тему] станет универсальным решением для рендеринга и заменит всё остальное!». Спойлер: этого не случится (по крайней мере, в ближайшее время).

Целевая аудитория


Целевая аудитория моего поста:

  • Студенты, изучающие компьютерную графику, и прикладные исследователи,
  • Инженеры рендеринга, особенно начинающие свою карьеру, которые ещё не выработали интуитивного понимания,
  • Технические художники и руководители/продюсеры арт-отделов,
  • Технические директоры и ответственные лица, не имеющие опыта в графике,
  • Инженеры и архитекторы оборудования, работающие над тем, что связано с GPU или с графикой (которым любопытно, почему сложно использовать новые аппаратные функции),
  • Люди, которые любят игровую графику и интересуются ею (или графикой реального времени в целом), желающие чуть больше разобраться в том, «как делается колбаса». Некоторые концепции могут показаться слишком техническими или в них может быть слишком много жаргона, но их спокойно можно пропустить.


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

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

Как интерпретировать это руководство


Очень важное замечание — ни одно из описанных в статье «препятствий» на самом деле не является причиной не использовать методику.

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

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

Способы применения


Категории «способов применения» заслуживают отдельного объяснения и описания «серьёзности» их ограничений.

Технологическое демо


Технологическое демо — самая простая категория. Если весь ваш продукт — это демонстрация определённой методики (для бенчмаркинга, демонстрации новых исследований, художественной демосцены), то большинство ограничений к нему неприменимо.

Вы можете совершенствовать всё: концепцию демо, саму графику, траекторию камеры, демонстрирующую технологию и скрывающую все проблемы.

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

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

Специальный уровень/однократное использование


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

Примером может служить освещение на уровнях с джунглями в Assassin«s Creed 4: Black Flag, над которым я работал.

image-loader.svg


Источник: рекламные материалы Assassin«s Creed 4: Black Flag. Обратите внимание на столбы света с подобием каустики, которые были важным элементом рендеринга на уровнях с джунглями и позволили нам много сэкономить на рендеринге теней!

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

Кинематографические вставки


Чуть более требовательный тип функций — кинематографический. Кинематографические вставки слегка отличаются тем, что их очень сильно могут контролировать художники и большинство их аспектов (освещение, расположение персонажей и анимации) фальшивы — прямо как в настоящем кино! Кинематографические вставки часто содержат быстрые смены кадра (полезно для сокрытия переходов/рывков) и имеют больший бюджет вычислительных ресурсов благодаря своей предсказуемости (и даже в консольных играх с 60 fps рендерятся в 30 fps).

image-loader.svg


В кинематографических вставках Witcher 2 увеличена детализация персонажей, добавлено красивое реалистичное радиальное боке и уникальное освещение. Однако заметьте, что в них рендерится очень мало объектов!

Обычные функции рендеринга


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

В моём посте в основном будет рассматриваться эта категория.

Ключевые/уникальные функции


Как ни парадоксально, если что-то является ключевой или уникальной функцией, это может облегчить многие трудности. Возьмём для примера VR — стереозвук, производительность (низкие задержки) и идеальное сглаживание AA без размазывания (так что забудьте о TAA) являются главными функциями, абсолютно необходимыми для ядра игрового процесса. Это означает, что вы можете, например, игнорировать рендеринг растительности или какие-то анимации, которые бы выглядели нереалистично: самое важное — это погружение и ощущения от VR!

Совместимость функций


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

Функции — это не самая большая трудность. Сложнее всего категория, которую я рассмотрю в конце («процесс»). Но они интересны и их легко изучить.

Плотная геометрия


Плотная геометрия, например, растительность (которая и вдохновила меня на создание поста) — враг большинства алгоритмов рендеринга.

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

Ранее отсечение по глубине и перекрытию? Реализовать очень сложно.

Отделение поверхностей от объёмов? Очень сложно.

Хранение информации для каждой уникальной параметризации поверхностей? Почти невозможно.

Количество анимируемых вершин и затеняемых пикселей? Огромно, шейдеры нужно упрощать!

image-loader.svg


Растительность в Witcher 2 — какая плотность! На мой взгляд, это по-прежнему один из лучших примеров леса в играх.

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

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

Альфа-тестирование


Альфа-тестирование — продолжение описанный выше темы, потому что оно не позволяет использовать ещё больше аппаратных функций/оптимизаций.

Альфа-тестирование — это методика, при которой пиксель вычисляет значение «альфы» из текстуры или вычислений пиксельного шейдера, а потом сравнивает его с пороговым значением, принимая решение, нужно ли его рендерить/записывать.

Это гораздо быстрее, чем альфа-смешение, но, например, не позволяет использовать ранние записи в буфер глубин (ранние z-тесты выполнять можно), и требует hit-шейдеров трассировки лучей, а также считывания из текстуры, чтобы решить, непрозрачен ли тексел.

Также это сильно усложняет сглаживание (забудьте об обычном MSAA, необходимо будет эмулировать alpha to coverage).

Описание и отличное визуальное объяснение некоторых из проблем см. в этом посте Бена Голуса.

Анимация — скелетная


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

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

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

image-loader.svg


Требюше из Witcher 2 — это не люди, но у них всё равно есть «скелеты» и «кости», и в них также используется скелетная анимация!

Анимация — процедурная и нежёсткая


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

См. это видео про движение в промежуточном ПО Speedtree — всё движение здесь описывается математическими формулами, а не анимировано вручную, и выглядит фантастически и реалистично.

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

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

Анимация — текстуры


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

image-loader.svg


Дождь в Assassin«s Creed 4 основан на смещении нормалей с процедурно генерируемой картой высот и текстурой дождя. См. мой доклад на Digital Dragons о рендеринге дождя в игре.

Динамическая точка обзора


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

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

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

Динамическое освещение


Насколько динамично освещение? Есть ли в игре динамическая смена дня и ночи? Система погоды? Может ли пользователь включать/выключать освещение? Испускают ли спецэффекты свет? Есть ли объекты, испускающие динамические тени?

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

Это необязательно исключает возможность использования решений с заранее вычисленным/запечённым освещением (например, нашего решения с заранее вычисленным GI для AC4, поддерживавшего динамическую смену времени суток!), но требует повышенного внимания.

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

Тени


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

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

Для частиц и объёмов ответ может быть непростым (так как частичная пропускаемость не поддерживается картами теней), но и «простые» методики наподобие тесселяции мешей или параллаксных карт перекрытия тоже будут создавать несоответствие между испускающим и получающим тень объектами, что потенциально может вызывать артефакты теней!

image-loader.svg


Слайд из моего доклада на GDC 2014, демонстрирующий параллаксную карту перекрытия в AC4 — обратите внимание на полное отсутствие теней.

Динамическое окружение


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

В God of War участок карты Caldera Lake и мост, движущиеся уровни воды и повороты моста были одними из самых серьёзных проблем на протяжении всего продакшена с точки зрения систем освещения/глобального освещения, которые используют предварительные вычисления. Не существовало какого-то «общего» решения, всё зависело от ручной работы и потоковой передач загруженных данных/управления ими.

image-loader.svg


Мост на Caldera Lake из God of War. Было довольно сложно управлять им на основании изменения освещения по ходу сюжета!

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


Наконец, есть прозрачные объекты и частицы, сильно отличающиеся от остальных категорий.

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

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

Совместимость с конвейером


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

Тестирование и запись глубин


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

«Вкусный» эффект глубины резкости и многие другие эффекты камеры требуют буфера глубин. Старый добрый туман глубины? Ему тоже нужен буфер глубин!

image-loader.svg


Мне нравится боке на этом скриншоте и работа, которую я проделал с художниками над Witcher 2, но обратите внимание на ошибки: пламя перед драконом выглядит резко, а плоскость перед фоном размыта. Это баг, потому что они должны иметь одинаковую глубину резкости (DoF), однако глубина, считываемая для эффекта боке — это глубина твёрдых объектов, а не частиц!

Кажется, что это неустранимое препятствие, ведь мы знаем, что объекты с альфа-смешением не записывают глубину и у них не может быть единого значения глубины… Но разработчики игр — мастера фокусов и имитаций. Если вам это нужно, можно создавать псевдоглубину вручную, сортировать и переупорядочивать некоторые объекты вручную, выполнять альфа-смешение глубины (это неправильно, но выглядит неплохо), настраивать глубину поля зрения, пока артефакты не перестанут мешать… Много ручной работы и головоломок вида «какой же компромисс наименее плох?»

Векторы движения


Близкий к глубинам компонент конвейера — запись векторов движения. Глубина необходима для многих вышеупомянутых эффектов, правильного перекрытия, отражений в экранном пространстве, тумана, и т.д., а векторы движения используются «только» для двух аспектов: размытия в движении и временного сглаживания (см. ниже).

Кажется, что размытие в движении (Motion blur) — это «просто эффект», однако незначительное его количество необходимо для снижения эффекта «стробинга» и ощущения дешевизны (см. motion blur полузакрытого затвора в фильмах с 24 fps).

(Немного хвастовства и ностальгии: размышления о motion blur заставляют меня ностальгировать — motion blur стал первой функцией, о которой я давал интервью прессе. Я до сих пор ощущаю гордость 23-летнего себя, живущего в Восточной Европе и ещё не закончившего колледж!)

Создание точных векторов движения — нетривиальная задача; для каждого пикселя нужно подсчитать, где эта часть объекта находилась в предыдущем кадре. Для этого может потребоваться пересчитать часть данных анимации, сохранить их для предыдущего кадра (ещё больше лишней памяти), или это вообще может оказаться сложно/невозможно (работа с перекрытиями, тенями или анимациями текстур).

В AC4 мы реализовали почти всё, за исключением океана и игнорировали в нём проблемы с TAA и motion blur.

Временное сглаживание


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

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

image-loader.svg


Мерцающий снег стал одним из самых востребованных функций художников God of War, но мне не удалось создать достаточно устойчивый эффект, потому что временное AA устраняло его полностью, считая временным мерцанием/алиасингом…

Отложенное затенение/освещение


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

image-loader.svg


Пример описания GBuffer — текстуры представляют различные свойства материалов и объектов. Позже к ним применяется освещение. Источник: learnopengl

Однако наличие «узкого места» в виде GBuffer и освещения, а также отсутствие доступа ко всем другим данным может сильно ограничивать.

Новая модель затенения? Новая таблица поиска? Новые данные, предварительно вычисляемые/запекаемые и сохраняемые в вершины или текстуры? Нужно уместить всё это в GBuffer!

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

Например, в God of War нельзя использовать подповерхностное рассеивание (subsurface scattering) одновременно с моделью зеркальных отражений ткани/светоотражения, потому что они используют одинаковые слоты в GBuffer. Сам GBuffer занимает очень много памяти и в игре было гораздо больше взаимоисключающих функций — я записал в свой блокнот многие возможные комбинации (если не ошибаюсь, там было 6 битов только для кодирования типа материала + его особенностей) и «торговался» об этих компромиссах с разными художниками, у каждого из которых были свои потребности.

Из-за каждой новой функции приходилось вырезать что-то другое или идти на какие-то ещё компромиссы.

Наличие/отсутствие переключения камер


В большинстве кинематографических вставок постоянно присутствует активное переключение камер, показывающее разных персонажей, разные перспективы на сцену или параллельно происходящие действия. Этот инструмент активно применяется во всех видах кино (возможно, за исключением «Догмы 95» или «Бёрдмена»), и если художник по кинематографии хочет его использовать, нужно обеспечить его поддержку.

Но что произойдёт, когда камера переключается со всей этой попиксельной историей временного накопления, необходимого для TAA/временного суперсэмплинга? Как насчёт потоковой передачи текстур, которая внезапно видит совершенно новый вид? Что насчёт амортизированного рендеринга, зависящего от вида, например, кэширования карт теней? Всё это решаемо, но потребуется много работы или могут возникнуть нежелательные задержки/рывки/слишком большие затраты на новый кадр. Мой коллега сказал, что это проблема и для физики или анимаций — часто при переключении камеры аниматоры изменяют позиции и мы видим, как физические объекты «оседают», например, на персонаже движется ожерелье. Это тоже разрушает погружение в игру и требует собственного набора «хаков».

Нехватка переключений камер (например, как в God of War) тоже сложна, особенно для освещения кинематографических сцен, хороших анимаций, переходов и т.д. Как бы то ни было, обе проблемы необходимо решать/учитывать. Стоит даже добавить в рендере флаг «камера была переключена».

Пирамида усечения


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

image-loader.svg


GIF из Horizon: Zero Dawn демонстрирует усечение по пирамиде видимости. Многие разработчики игр были немного удивлены тем, что игровые медиа и игроки «обнаружили» в играх усечение по пирамиде видимости (оно использовалось всегда).

Теперь всё становится сложнее! Зачем анимировать невидимые объекты? Не будем этого делать, чтобы сэкономить много времени ЦП.

Однако предметы, видимые в основной камере — это только часть истории, есть ещё и отражения с тенями… Не могу сосчитать, сколько раз я видел, что в тенях персонажи вне экрана находятся в «T-позе» (стандартная поза, когда персонаж не анимирован). Ещё одна новая проблема заключается в том, что трассировка лучей может «касаться» поз объектов!

image-loader.svg


Персонаж в T-позе. Я уверен, что вы видели такой баг очень много раз! Стоит обратить внимание и на тени с отражениями.

Усечение по перекрытию


Усечение по перекрытию (Occlusion culling) — это следующий этап после усечения по пирамиде видимости. Нам ведь не нужно рендерить объекты за пределами камеры? Да. Но если перед камерой находится огромное здание, нам тоже не нужно рендерить весь город за ним!

image-loader.svg


Источник: «A Survey of Visibility for Walkthrough Applications».

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

В каком-то смысле система occlusion culling — это новая функция рендеринга, которая должна проходить все перечисленные в этом посте этапы! Но учитывая сложность и общую хрупкость многих решений (ещё один аспект, который нужно учитывать), мы не хотим ещё больше усложнять её.

Уровень детализации


Любая методика, требующая некоего вычислительного бюджета на рендеринг и объёма памяти, должна правильно «масштабироваться» в зависимости от расстояния. Когда отрендеренный объект находится в 100 метрах от камеры и занимает всего несколько пикселей, он не должен занимать 100 МБ памяти, а его рендеринг/обновление не должно занимать и миллисекунды.

На сцене появляется уровень детализации (level of detail, LOD) — упрощённое представление объектов, мешей, текстур(последние реализуются автоматически в форме mip-текстурирования, но их всё равно нужно правильно и по отдельности потоково передавать), а также их вычисления.

image-loader.svg


Источник: Википедия.

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

Как должно масштабироваться глобальное освещение с расстоянием? А объёмные эффекты? Освещение? Частицы?

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

Загрузка, переключение и потоковая передача LOD


Уровень детализации нужно передавать потоково. Если объект вдалеке занимает на экране несколько пикселей, мы можем использовать десяток вершин и, может быть, вообще не применять текстуры — в целом это займёт несколько килобайт. Но потом камера начинает приближаться, и нам нужно загружать материал, текстуры, меши… Для всего этого нужно писать код систем и решений. Что произойдёт, когда камера просто телепортируется? Система потоковой передачи должна справляться с этим.

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

Открытый мир


Я выделил «открытый мир» как отдельный раздел, но на самом деле это набор множества ограничений и требований, которые совместно отличаются качественным образом — нужна не просто надёжная система потоковой передачи, но и всё должно быть спроектировано для потоковой передачи в играх с открытым миром. Дело не только в усечении — нужно качественное усечение, работающее с ИИ, анимациями и многими другими системами. Открытый мир и крупномасштабный рендеринг — это огромное ограничение почти для всего в конвейере, и это необходимо учитывать.

Когда я присоединился к команде разработчиков AC4 в Ubisoft и увидел все технологии «открытого мира» для потоковой передачи, рендеринга на дальних расстояниях и тому подобное, или элементы теней на дальнем расстоянии в Far Cry, я был поражён, насколько специализированный (и продуманный) труд необходим для выпуска игр на консолях.

Бюджет


Наконец, о бюджете… Ниже я буду говорить о бюджете «продакшена», но, надеюсь, это понятно и так. Если новая методика требует памяти или тактов CPU/GPU, их необходимо выделить.

Часто встречается заблуждение о том, что если нечто укладывается в 30 мс — это «методика реального времени». Она может ею быть, но если рендерится только эта методика и только в игре на 30 fps.

В VR иногда приходится иметь дело с бюджетами меньше 10 мс на рендеринг камер для двух глаз для целого кадра! Это означает, что методика освещения, требующая 1 мс, уже слишком затратна!

Аналогично с ОЗУ — все затраты необходимо оценивать в целом и обычно игры уже и так используют всю свободную память. То есть ради любого нового компонента приходится жертвовать чем-то ещё. Стоит ли функция X снижения бюджета на потоковую передачу текстур и риска багов потоковой передачи текстур?

Ещё один «невидимый» бюджет — это пространство на диске. О нём говорят не очень часто, но при современных конвейерах видеоигр мы уже едва можем уместить игру на диски Blu Ray (в God of War это было большей проблемой, чем размер памяти или производительность!).

Можно вспомнить и о патчах, занимающих по 30 ГБ — это смехотворно и обычно является признаком того, что в системе упаковки ресурсов недостаточно хорошо учли патчинг. Как бы то ни было, новое решение с предварительно вычисляемым глобальным освещением, занимающее «всего» по 50 МБ на фрагмент уровня, для целой 30-часовой игры «внезапно» масштабируется до 15 ГБ на диске; скорее всего, это будет неприемлемо!

Процесс


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

Многие «альтернативные» методики рендеринга уже во многих смыслах практичны (например, знаковые поля расстояний), однако нехватка инструментария, конвейеров и опыта в продакшене совершенно исключают их использование, за исключением особых случаев, в которых применяется создаваемый пользователем контент (см. великолепные Dreams или Claybook).

Художественный контроль


Легко впасть в восторг от потрясающих результатов процедурного рендеринга, фотограмметрии или в целом захвата и повторного рендеринга 3D-контента — результаты выглядят великолепно и, казалось бы, обещают устранить огромную долю затрат на продакшен.

Однако художники должны иметь полный контроль над процессом создания контента и участвовать в нём.

Захват модели стула при помощи neural implicit representation выполнить легко, но сможете ли вы изменить цвет сиденья, удлинить некоторые части стула или сделать краску потёртой? А когда арт-директор решит, что нужен стул в стиле «барокко», вы будете искать его?

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

В Assassin«s Creed 4 один из моих коллег работал над процедурным рендерингом неба (в сотрудничестве с другими командами, а также, если не ошибаюсь, с вычислениями какого-то промежуточного ПО). Результат выглядел потрясающе, но арт-директор (который также был профессиональным художником) не мог получить им

© Habrahabr.ru