В течение последних четырех лет воксели служили в качестве системы освещения в мире Roblox. Но рано или поздно во всем приходит время перемен. Именно поэтому разработчики задались вопросом, что делать дальше.
Освещение — штука сложная, так что нужно быть осторожными при выборе новых технологий, ведь при этом необходимо учитывать множество факторов. Для облегчения принятия решения для Roblox создали прототипы двух будущих систем: так называемых вокселей и теневых карт. Для того, чтобы понять ограничения тех и других, сначала важно понять, как они работают.
Примечание: Скриншоты в статье расположены так, чтобы слева всегда были показаны воксели, справа — теневые карты.
Реализация: воксели
Хотя именно эта система долгое время работала в игре, рассматриваемый здесь вариант претерпел множество доработок.
Данные о мире преобразуются в набор сеток вокселей: каждая сетка центрируется вокруг персонажа и может иметь размеры вокселей от 1 до 16 (всего 5 решеток). Каждый воксель содержит информацию о наполненности (occupancy) в диапазоне от 0 до 100%. Затем вычисляются данные освещения для каждого вокселя в каждой сетке на основе этой наполненности и информации об источниках/направлении света. Все вышеперечисленное происходит на графическом процессоре, так как центральный недостаточно быстр для обновления такого количества вокселей со столь высокой плотностью.
Система хранит все данные в вокселях, в частности — для каждого имеющегося вокселя есть данные о:
- Наполненности (несколько значений, описывающих, насколько заполнен каждый воксель);
- Skylight (какая часть неба видна из вокселя);
- Тени от солнца (какая часть солнца закрыта вокселем);
- Цвета светового объекта/конуса (приближение цвета/конуса воздействия локальных источников света на воксель).
Эта информация позже используется для вычисления цвета каждого пикселя при заданном разрешении. Разрешение экрана и вокселей можно регулировать независимо друг от друга. Части сетки вокселей могут обновляться покадрово по мере перемещения источников света/объектов.
Реализация: теневые карты
Этот метод для вычисления большинства теневых эффектов использует растеризацию. Он выполняется в три этапа. Сначала для каждого теневого каста мы обновляем теневую карту, запуская касты множества лучей от источника света в сцену и запоминая результаты пересечений. Затем мы строим структуру пространственного ускорения, в которую встраиваем каждый видимый световой объект, по сути представляющий собой воксельную сетку в форме усеченного конуса (также известную как фроксельная сетка).
Сетка покрывает всю часть игрового мира, видимую камерой. В каждом фрокселе мы записываем список всех световых объектов, которые его пересекают. Наконец, чтобы вычислить влияние всех источников света, при рендеринге сцены для каждого пикселя мы ищем фроксель, в котором содержится этот пиксель, перебираем все источники света и для каждого источника света вычисляем отдельно его влияние, используя теневые карты, построенные на первом этапе.
Система хранит данные в двух структурах:
- Теневые атласы (все карты теней от видимого света, упакованные в одну большую текстуру);
- Световая сетка (сетка из фрокселя, эффективно преобразующая точку в камере в список источников света).
Цвет каждого пикселя вычисляется динамически и не хранится в явном виде. Части теневого атласа можно обновлять покадрово по мере перемещения источников света/объектов.
Производительность: воксели
Техника вокселей лучше поддается масштабированию: для ухудшения качества вывода мы можем уменьшить количество сеток вокселей или же обновлять меньше вокселей в каждом кадре (что приводит к «световой задержке» — более медленному обновлению светового воздействия объектов по сравнению с обновлением самих объектов).
Воксели имеют три характеристики сложности: геометрическая сложность, сложность света и количество пикселей. Геометрическая сложность влияет только на стоимость вокселизации, так что добавление большего количества объектов не приведет к появлению задержек. Сложность света влияет только на стоимость его вычисления, которая не зависит от геометрической сложности или количества пикселей. Наконец, окончательный цвет пикселя вычисляется из количества вокселей/источников света/объектов, поэтому мы можем масштабировать разрешение, не влияя при этом на качество освещения.
Производительность вокселей вычисляется как O (G) + O (L) + O (P), где G — количество треугольников (геометрическая сложность), L — количество источников света, P — количество пикселей.
К сожалению, пиковая производительность вокселей не оптимальна, поскольку количество вокселей масштабируется как N3, а графические процессоры не идеально подходят для необходимых методов обновления и не могут поддерживать хорошее управление производительностью. При наличии достаточных исследований в области вычислений на GPU можно компенсировать потерю производительности, но в настоящий момент базовая стоимость может оставаться довольно высокой.
Производительность: теневые карты
Теневые карты более удобны для графического процессора, поскольку они разработаны на основе растеризации. Стоимость обновления теневого атласа может быть частично снижена путем кэширования/задержки обновлений (что логично приводит к дополнительной задержке). Оптимизация представления геометрии (включая уровень детализации сетки) также снижает стоимость метода.
Однако обновление теней в сложных сценах все еще остается дорогостоящим, поскольку его стоимость зависит как от количества геометрических деталей, так и от числа отбрасывающих тени источников света. Внутри здания в случае движущегося источника необходимо повторно отрендерить все здание в каждом кадре для обновления информации о тени для этого источника света. Множество движущихся световых кастов в здании приводит к снижению производительности: мы не можем обновить сразу все источники света в кадре, что приводит к визуальным артефактам.
Кроме того, этот метод не позволяет отделить параметр разрешения от количества света: для каждого пикселя мы должны пересчитывать влияние всех источников света, которые его покрывают. Этот шаг также нельзя кэшировать, что приводит к проблемам с производительностью при высоких разрешениях в сильно освещенных сценах: 20 перекрывающихся источников света в комнате с разрешением 4K могут потребовать 160 миллионов оценок освещенности.
Производительность карт теней рассчитывается как O (GL) + O (LP), где G — количество треугольников (сложность геометрии), L — количество источников света, P — количество пикселей.
Производительность: оценка
Для большей наглядности оба метода применялись для специально отобранных игровых уровней. Обратите внимание, что это уже существующие реализации уровней, а не созданные специально для оценки производительности.
Париж (тени от солнца, очень мало источников света, не отбрасывающих тени)
- Воксели: обновление теней — 6 мс, рендеринг сцены — 1,5 мс;
- Теневые карты: обновление теней — 1 мс, рендеринг сцены — 2,4 мс;
- Стоимость вычисления базовой воксельной тени выше, поскольку графическому процессору тяжелее ее обрабатывать.
Пещеры (много отбрасывающих тени источников)
- Воксели: обновление теней — 7 мс, рендеринг сцены — 0,9 мс;
- Теневые карты: обновление теней — 10 мс, рендеринг сцены — 2,1 мс;
- Из-за большого количества геометрии и движущихся источников света обновление теневых карт обходится дорого.
Вестерн (много отбрасывающих тени источников)
- Воксели: обновление теней — 8 мс, рендеринг сцены — 1 мс;
- Теневые карты: обновление теней — 15 мс, рендеринг сцены — 2,5 мс;
- С движущимися источниками света и большим количеством треугольников обновление карты теней оказывается дорогим.
1000 источников света без тени
- Воксели: обновление света — 20 мс, рендеринг сцены — 0,5 мс;
- Теневые карты: обновление света — 0,5 мс, рендеринг сцены — 5 мс;
- Совокупный объем перекрытия света и вокселей в этом случае замедляет обновление вокселей. Кроме того, можно увидеть, что в ближнем каскаде приближение для «одного источника света в каждом вокселе» не выполняется.
Производительность: заключение
Теневые карты хорошо масштабируются для рабочей нагрузки, однако стоит учитывать два аспекта:
- Стоимость каждого пикселя растет по мере увеличения разрешения, что делает это решение практичным только при среднем разрешении (1080p); выход за рамки 1080p требует наличия очень хорошего графического процессора.
- Стоимость просчета тени растет очень быстро в случае сложной геометрии множества динамических источников света. Это может быть компенсировано лучшей отбраковкой, но на данном этапе пока остается фундаментальной проблемой.
В то же время, напротив, производительность вокселей намного меньше зависит от контента уровня, но имеет гораздо более высокую базовую стоимость. Это может быть компенсировано улучшенными алгоритмами графического процессора и уменьшением количества вокселей.
Требования к памяти
Требования к памяти для теневых карт и вокселей зависят от требуемого качества.
В случае вокселей в памяти хранятся несколько текстур для каждого каскада, поэтому их совокупный размер зависит от количества каскадов и размера каждого из них. В настоящее время используется 4 каскада (с размерами вокселей 1..8) по 128x64x128 вокселей в каждом, что добавляет до 128 МБ используемой VRAM. Можно было бы завести еще 2 каскада (0,5 вокселя и 16 вокселей) или перенастроить имеющиеся, что увеличило бы это значение до 192 МБ. Можно, наоборот, уменьшить количество каскадов (удалив некоторые близкие каскады) в системах с ограниченным объемом памяти, и тогда минимальное воздействие на память может составить около 64 МБ с двумя каскадами (4..8) и около 96 МБ с тремя (4..16).
В случае теневых карт используются атлас теневых карт и фроксельная сетка. Последняя отчасти зависит от разрешения. Размер теневого атласа, в свою очередь, можно уменьшить, если нужно уменьшить качество теней для улучшения производительности/памяти. Текущая система использует 73 МБ видеопамяти, большую часть из которых (64 МБ) занимает теневой атлас. Можно уменьшить его и таким образом ограничить количество затемненных источников света или качество теней. Также можно рассмотреть некоторые варианты теневых карт, для которых требуется больше памяти для поддержки полупрозрачности, а значит, они займут больше места (до 130 МБ или более). Минимальное воздействие на память системы, вероятно, будет достигнуто, если уменьшить размер теневого атласа и воспользоваться его более простым вариантом, который будет занимать около 25 МБ.
Для сравнения: текущая система освещения имеет два режима: для высокого (ПК) и низкого качества (мобильные девайсы). Вариант для ПК занимает ~ 40 МБ (24 МБ RAM, 16 МБ VRAM); мобильный — ~ 11 МБ (6 МБ RAM, 5 МБ VRAM).
По сути, оба метода достаточно близки с точки зрения воздействия на память, но теневые карты несколько более масштабируемы для одного и того же диапазона света/тени.
Мобильная совместимость
Аудитория игры становится все более «мобильной», и это означает, что при сравнении выбранных реализаций нужно учитывать еще и различные игровые устройства. На high-end девайсах должно быть достаточно возможностей API для реализации обоих методов, но, конечно, они могут оказаться не столь практичными с точки зрения памяти и производительности.
Уже существующая воксельная система освещения отлично подходит для мобильных устройств: она поддерживает множество сложных функций освещения (light shadows, skylight и т. д.) и выполняет большинство сложных вычислений на ЦП, таким образом обеспечивая минимальные требования к производительности графического процессора и набору фич. Поскольку в обозримом будущем все равно придется поддерживать эту систему для недорогих мобильных устройств и ПК, возникло несколько вариантов поддержки большого пула устройств:
- Сохранить существующую систему в мобильном виде, новая же будет только ПК/консольной. Это означает, что большой сегмент пользовательской базы не будет иметь доступа к новой системе.
- Небольшое улучшение существующей системы для передовых мобильных устройств (слегка уменьшенный размер вокселей, улучшенное представление вокселей), использование новой системы для ПК/консолей.
- Сохранить существующую систему на low-end девайсах, найти способ уменьшить масштаб новой системы, чтобы она могла работать на современных мобильных устройствах.
Во всех перечисленных случаях необходимо ответить на вопрос о совместимости контента, ведь одно из основных обещаний платформы — «загрузить контент один раз и запускать его где угодно». Над этим еще нужно поработать. Поначалу кажется, что новое воксельное решение лучше в том смысле, что обеспечивает постоянство качества/поведения от старой к новой системе, тогда как теневые карты представляют более резкий переход к другому качеству, но при этом имеют больше шансов ужиться с ограниченными возможностями на мобильных устройствах.
Качество: источники света
Решение с теневыми картами обеспечивает достоверную информацию с точки зрения имитации источников света: на скриншоте ниже с 1000 источников света в случае теневых карт вы можете увидеть отлично воспроизведенные зеркальные блики — смоделированные с помощью BRDF, который и дает нам нужные световые отражения.
Воксельное решение принципиально хуже, поскольку оно аппроксимирует влияние света на каждый воксель, как если бы оно исходило только от одного источника. Отсюда видно, что качество зеркального отражения ухудшается:
Итак, в случае вокселей в области с зеркальными бликами цвета сливаются в соотношении 1:1, создавая желтый свет вместо зеленого и красного, хотя в сцене даже нет желтых огней. Решение с теневыми картами, напротив, точно моделирует цветовое сочетание.
В некоторых случаях мы получаем и вовсе очень неубедительные результаты, хотя и их в перспективе можно улучшить:
На примере выше видно изогнутые, удлиненные, искаженного цвета зеркальные блики, а в нескольких вокселях под одним из объектов и вовсе отсутствует световая информация. Тот же скриншот для теневых карт дает гораздо лучший результат.
Качество: тени
Определяющим качеством теневых карт является точность, а воксельных теней — мягкость. Теневые карты обеспечивают довольно четкие тени с минимально возможными деталями, но достаточно точными для создания убедительной тени персонажа. С другой стороны, воксельный алгоритм очень хорош для создания действительно мягких теней, однако тени от мелких деталей при этом либо не регистрируются вообще, либо имеют неправильную форму.
По этой причине в настоящее время используется вариант теневой карты для рендеринга теней от персонажей — однако это скорее «костыль», применяющийся только к солнцу, отбрасывающему тени от персонажа. Другие источники света при этом не учитываются.
Кроме того, ключевым методом ускорения вокселей является использование каскадов. Однако это означает, что данные о наполненности становятся грубее по мере удаления от интересующей нас точки сцены. Качество тени при этом тоже ухудшается по мере увеличения расстояния между источником и приемником тени:
На скриншоте выше размера самого маленького вокселя было бы достаточно для визуализации высококачественной тени от моста, но мост находится слишком далеко от поверхности воды, поэтому его воксели оказываются слишком грубыми даже при условии, что воксели у поверхности воды весьма неплохи.
Качество: skylight
Важной функцией в воксельном пайплайне является вычисление коэффициента skylight, определяющего, какая часть неба видна из текущего вокселя. Он используется для смешивания внешнего и внутреннего освещения и очень эффективен для улучшения его качества. На скриншоте ниже снаружи дома должно быть намного ярче, чем внутри, даже в тех областях, которые находятся в тени. Воксельное решение хорошо вычисляет и воспроизводит этот коэффициент, однако в случае теневой карты он отсутствует, оттого отсутствует и возможность сделать тени тусклыми.
Качество: геометрическая точность
Стоит отметить фундаментальные различия в представлении геометрии между вокселями и теневыми картами.
Воксели предполагают, что все объекты, поддерживаемые движком освещения, могут быть «вокселизированы» — то есть, для каждого вокселя в игровом мире существует быстрый способ вычислить объем пересечения между объектом и вокселем. Это хорошо работает для примитивных форм, но сложные объекты, такие как CSG и MeshParts, уже представляют серьезную проблему. Сейчас с этим отчасти помогает грубая декомпозиция и набор других хаков для эффективной вокселизации, но это часто приводит к видимым артефактам. В то же время теневые карты используют то же многоугольное представление, что участвует и в рендеринге, оттого они могут идеально отображать формы всех объектов:
Качество: light leaks
Хотя форма тени и чрезвычайно важна, пожалуй, даже более важно то, что невидимые пиксели обязаны обрабатываться должным образом. Когда различные приближения это нарушают, возникают так называемые утечки света — видимые полосы, порождающие наибольшее число проблем в высококонтрастных средах — например, внутри здания при ярком солнце снаружи. Вот пример утечки света:
Речь идет о тонкой освещенной части пола прямо у стены. Теневые карты намного лучше сохраняют световую окклюзию и борются с этой проблемой.
Для вокселей существует несколько источников утечек. Смягчить некоторые из них можно, сохраняя анизотропную наполненность: так, сейчас в памяти хранится по 3 значения на воксель, обозначающих, «сколько материи находится в проекции вокселя вдоль оси» для всех трех осей. К сожалению, пусть это помогает тонким деталям отбрасывать тени независимо от их толщины, все утечки устранить так не получится. Единственный способ гарантировать полную блокировку света в этом аспекте — сделать деталь вдвое толще, чем воксель. Кроме того, утечка растет с увеличением размера вокселя, и это означает, что на более низком уровне качества и/или на большом расстоянии она становится более заметной.
Теневые карты не являются полностью герметичными, но утечки в них представляют собой значительно меньшую проблему — так, в данной реализации объект толщиной 0,4 вокселя не будет пропускать видимый свет (при толщине 0,2 вокселя он может пропускать часть света, но и от этого в перспективе можно избавиться).
Качество: заключение
Теневые карты превосходны в большинстве аспектов качества. Единственная значительно проседающая область — вычисление коэффициента skylight. Возможно, для этого понадобится гибридный метод, который использует вокселизацию для skylight, что вносит некоторые заминки в воксельный пайплайн — или, может быть, есть альтернативные решения этой проблемы. Также было бы неплохо иметь возможность поддерживать мягкие тени, что можно организовать при помощи некоторых расширений алгоритма теневой карты.
Воксели обеспечивают приемлемое качество, но по сравнению с теневыми картами они сильно проигрывают, особенно в точности воспроизведения теней и зеркальных бликах. Придется каким-то образом решить эти проблемы, чтобы иметь возможность реализовать воксельное освещение, способное обеспечить красивые тени от игрока, ведь использование текущего решения дает таковые только от солнца, что кажется несовместимым с будущим видением мира в игре.
Видимость: полупрозрачность
Рендеринг теней — довольно хорошо изученная проблема для непрозрачных объектов, однако полупрозрачность — совсем другое дело. Поскольку в случае воксельной системы свет распространяется через воксельные ячейки с учетом значения наполненности, не так уж и сложно поддерживать полупрозрачные тени, которые могут дать низкочастотные (мягкие) тени от эффектов частиц и других полупрозрачных объектов в сцене, включая самозатенение (self-shadowing) для самих эффектов частиц:
Ниже представлено видео этого эффекта в движении:
Для теневых карт сейчас поддержки полупрозрачности нет. Это означает, что, если мы хотим поддерживать частицы или другие прозрачные объекты, отбрасывающие тени, нужно искать другое решение. Есть некоторые исследования для альтернативных представлений теневых карт, которые могут служить этому варианту использования, но еще неизвестно, насколько это эффективно.
Видимость: растительность
Хотя теневые карты не особенно хорошо справляются с полупрозрачностью, они могут отображать мелкие детали объектов (например, растительность) независимо от того, смоделированы ли они с помощью геометрии или текстур. Воксели недостаточно малы, чтобы служить этому варианту использования. Кроме того, в данном случае нелегко получить доступ к информации о текстуре, ведь для этого требуется точное моделирование поверхности сетки, а не объема. Сомнительно, что когда-либо можно будет получить красивые тени от растительности с помощью вокселей, тогда как теневые карты могут обеспечить это даже с существующим контентом, как показано на этом скриншоте:
Видимость: self-illumination
Благодаря тому, как реализованы воксели, относительно просто вводить источники света произвольной формы и количества в сетку, не влияя на производительность других частей пайплайна. Однако в то время, как вы добавляете множество источников света на теневые карты, создание источников света с нестандартными формами имеет некоторые трудности с архитектурой и производительностью. В частности, с вокселями гораздо проще реализовать истинную самосветимость: в настоящее время для «излучения света» используется неоновый материал, но на самом деле он не излучает свет на другие объекты поблизости.
Да, можно добавить дополнительные источники света, но было бы неплохо реализовать все это автоматически. Теневые карты не очень для этого пригодны, но воксели по необходимости поддерживают вокселизацию любых форм, и, таким образом, с ними поддержка светового излучения от самосветящихся объектов оказывается довольно простой.
Видимость: глобальное освещение
Глобальное освещение (global illumination, GI) означает вычисление вторичных световых эффектов, таких как свет от лампы, дважды отражающийся от стен для обеспечения дополнительного освещения тех областей, куда не дотягиваются прямые световые лучи.
GI в Roblox крайне сложен, и большинство решений касательно него вынуждены жертвовать чем-то из динамического освещения, динамической геометрии, производительности, масштабных сцен. Любая из этих жертв непозволительна.
Неясно, какие решения GI будут практичными в условиях имеющихся жестких ограничений по контенту. Пока что GI на основе вокселей кажется более перспективным, чем другие подходы.
Конечно, наличие GI на основе вокселей не означает, что прямое освещение вычисляется с их использованием: большинство исследований в области GI на основе вокселей сегодня подразумевают использование теневых карт для вычисления прямого света и улучшения результатов с помощью вокселей.
Резюме
Основываясь на приведенном выше анализе, составим сводную таблицу по эффективности обоих решений. Ячейки, выделенные курсивом, предполагают, что можно улучшить эту область с помощью дальнейших исследований. В таблице действует следующая градация: Ужасно < Плохо < Нормально < Хорошо < Отлично.
Итак, воксели прекрасно подходят для моделирования непрямого освещения, но уже не так хороши, когда речь заходит о прямом. При этом они весьма ресурсозатратны, что плохо коррелирует с задачей поддержания широкого пула устройств.
Это привело к решению создать систему на основе теневых карт для прямого освещения. Решение проблемы skylight и глобального освещения пока однозначно не найдено, но, скорее всего, окажется неким гибридом той и другой системы.