Добавил пробы для расчета глобального освещения в 2D

Продолжаю спамить апдейтами моей реализации динамического глобального освещения для своего 2D проекта на расте, wgpu и wgsl. На прошлой неделе изучил новую статью от GPUOpen "GI-1.0" и позаимствовал пару приемов.

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

В двух словах о подходе.

Допустим, у вас есть окно 1024x1024. Вам нужно получить цвет в каждом пикселе, что может быть дорого, если вы делаете трассировку лучей с несколькими отражениями. Вместо этого вы делите экран на тайлы 8x8. Итого 128x128 тайлов. Затем вы случайным (можно напр. использовать Halton Sequence) образом размещаете пробу внутри каждого тайла и запускаете алгоритм для сбора света для этой пробы. Поскольку у вас есть только 128x128 проб (по одной на каждый тайл), вы можете использовать область 128x128 пикселей для сбора всех данных, отобранных в одном кадре. Поскольку ваше исходное окно имеет размер 1024x1024, вы можете использовать ту же текстуру в качестве атласа для хранения 8 строк и 8 столбцов изображений хранящих 128x128 проб. Таким образом, вы можете позволить себе кэшировать до 8x8=64 кадров или, другими словами, для каждой пробы вы можете хранить 64 значения. Полное демо (не влезло в превью):

Полное демо.

Как и раньше, сама трассировка делается в пространстве SDF.

Для размещения проб внутри тайла можно использовать псевдо-случайные посдедовательности (гифка отсюда):

Разные способы генерировать псевдо-случайные последовательности.

Атлас с кешем проб выглядит примерно так:

Кольцевой буфер для 64x64 карты свечения.

Что замечательно, без каких-то особых оптимизаций реализация пока что укладывается в 1-2ms GPU time на мобильном GPU M1 и работает везде где есть Vulkan 1.1, DX12 или Metal. Расчет проб где-то 600 микросекунд:

Дебагер шейдеров в XCode
Дебагер шейдеров в XCode

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

Кстати я теперь в твиттере:

7676
7 комментариев