
Devblog. Часть 3 — Учим глобальное освещение быстро реагировать на изменения сцены
Не так давно мы выпустили HD Renderer, который обеспечивает возможности современной реалистичной графики, а одним из главных факторов является глобальное освещение (GI), которое в EdenSpark было взято из движка Dagor Engine.
При интеграции глобального освещения мы столкнулись с проблемой: новые статические объекты в сцене не получают почти никакого глобального освещения до полного перерасчёта.
Вот так выглядела сцена Sponza после спавна:

А после инвалидации GI и полного перерасчета:

Мы могли бы просто сделать инвалидацию, но это происходило не плавно:
В целом, можно было оставить и так, но делать полную инвалидацию глобального освещения при любом изменении было бы непрактично.
Причина проблемы в том, что глобальное освещение получает новые данные только с экранного пространства (информация о геометрии, альбедо, освещение).
Для контекста, вот как GI видит сцену
Для контекста, вот как GI видит сцену
На изображении ниже поверхность сцены представлена SDF с наложенной освещенной сценой.
Шарики — это первый каскад сетки излучения (radiance grid).

Если сцена предварительно настроена и больших изменений в ней не предполагается, такой подход приемлем. Однако, в EdenSpark сцена может произвольно меняться и это нужно было это учесть, причём желательно как для редактирования сцены, так и для геймплея (динамические источники света, движущиеся конструкции).
Базовые улучшения
Сначала мы просто добавили возможность перевокселизации измененных частей, чтобы, по крайней мере, сцена всегда была синхронизирована по глобальному освещению.
Мы также удалили освещенную сцену, которая кэшировала детальное глобальное освещение в пространстве экрана в мировом пространстве, потому что она блокировала распространение глобального света.
Из-за этого удаления обнаружились более сильные утечки света, которые мы исправили, добавив некоторые хаки со смещением, сдвигая выборку излучения (irradiance sampling) от стен (хотя утечки света все еще остаются серьезной проблемой и мы работаем над ней).
Теперь можно было увидеть обновление глобального освещения:
Однако полное сведение стало занимать около 20 секунд, что неприемлемо для любой динамически меняющейся сцены. Причина такой задержки — очень низкий вес, с которым зонды излучения (radiance probes) получают новые семплы.
После того как зонд изначально протрассирован всего с одним семплом на каждую из 64 секций (8x8 текселей), новые семплы добавляются таким образом, что секция постепенно сводится к среднему значению между всеми семплами, а это означает, что i-й семпл вносит вклад с весом 1/i, ограниченным минимумом 1/32.
Кроме того, после начального семплирования зонд обновляется в среднем раз в 16 кадров в нашей конфигурации — зонды выбираются случайным образом. При условии, что окружающее освещение не меняется, это правильная интеграция по Монте-Карло, которая переключается на скользящее среднее после достижения лимита. Но наше освещение *меняется*, а кроме того, зонды дополняют друг друга.
В результате не только окружающие зонды медленно улавливают само исчезновение света, но они также постоянно распространяют старое освещение друг на друга, делая обновление крайне медленным.
Ускорение обновления излучения
Чтобы исправить положение, мы добавили новое состояние для зондов, в котором N новых семплов вносят гораздо больший вклад: первый — с предустановленным максимальным весом, а N-й — с предустановленным минимальным весом.
В этом состоянии начальный индекс семпла определяется близостью к области, где изменился статический меш или источник света, чтобы более удаленные зонды оставались нетронутыми, поскольку их вклад из этой области намного меньше.
Чтобы решить проблему низкой частоты обновления зондов (которая используется для распределения дорогостоящей трассировки излучения по кадрам), мы дали зондам в этом состоянии приоритет над другими зондами, что означает, что при том же количестве выбранных зондов «ускоренные» могут обновляться каждый кадр.
В итоге мы получили следующее:
Теперь глобальное освещение мгновенно реагирует на движение источников света/геометрии с задержкой в пару секунд для полной сходимости (ускорение в 10 раз на той же сцене).
При изменении освещения все еще заметен шум. Мы пытались найти баланс между скоростью обновления и шумом. Улучшения здесь потребовали бы выполнения большего количества трассировок за кадр с ударом по производительности, что мы, вероятно, сможем предоставить в виде настройки после того, как завершим изменения глобального освещения