2D Raytracing игра с искажениями

Статья о том как работает 2D Raytracing, примеры его необычного использования для создания эффектов, а также WebGl демка и ассет для Unity Urp.

Почему рейтрейсин?

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

Ссылки на WebGl демку и репозиторий для Unity Urp в низу статьи.

Дисклеймер

Cтатья направлена на то чтобы простыми словами объяснить как что работает 2D Raytracing реализованный через фрагментный шейдер. Тема расширяется игрой искажениями для создания эффектов что можно попробовать самому в WebGl демке или самому скачав ассет с GitHub для Unity Urp.

Контент

Идея - в чем вся суть?

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

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

  • Отрисовать цвет объектов в Gi текстуру для того чтобы потом находить их при Ray Maching’е
  • Подготовить карту расстояний (Distance Map) для оптимизации поиска
  • Посчитать лучи для Gi текстуры применяя к ней текстуру шума

DistanceMap — оптимизация поиска

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

Луч берет дистанцию до ближайшего объекта из карты расстояний чтобы совершать меньше проверок
Луч берет дистанцию до ближайшего объекта из карты расстояний чтобы совершать меньше проверок

Считается следующим образом. В буфер рисуются координаты объектов в экранном пространстве, потом заполняют собой ближайшее пространство с помощью с помощью Flood Fill алгоритма (заполнение жидкостью) , а точнее его оптимизированной версией для видеокарт JFA (Jump Flood Algorithm) алгоритма.

Видео с простым объяснением как он работает. Суть такова что текстура несколько раз накладывается сама на себя, уступая место пикселю который имеет минимальное расстояние. (в шейдере это реализовано через Screen Space UV координаты)
2D Raytracing игра с искажениями

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

Часть лучей не достигает своей цели, от чего получается такой эффект.
Distance Map в динамике

Текстура Шума — искажения лучей

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

Видно неравномерное распределение света

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

Случайный шум при разном количестве лучей

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

Пример разных текстур шума для создания абстракций

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

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

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

Художественные применения

Играясь с параметрами, такими как

  • содержание и анимация текстуры шума
  • максимально количество шагов для каждого луча
  • изначальное смещение лучей
  • и разрешение текстуры

Можно найти довольно интересные эффекты и применения. Сделать что то абстрактное или стилизованное. Вот некоторые примеры. Больше можно посмотреть и поэкспериментировать в WebGl демке на itch.io

Игра с параметрами на разных сценках

Ссылки

6363
13 комментариев

Выглядит очень здорово, но на маке 3fps (это же счетчик fps справа сверху?)

1

Да, это он 👍, чтобы демка нормальна работала нужна средняя видеокарта

1

Комментарий недоступен

1

спс, поправил
* и много чего еще 👁

1

Классно сделал, крутая работа)

Будем следить за твоими успехами)

1

Нихуя не понятно, но очень интересно. Будет свободное время в исходниках покопаюсь

1

Очень круто, странно что так мало лайков. Своя система освещения это всегда уважуха) Я делал что-то подобное и тоже писал на DTF обзор:

1) https://dtf.ru/gamedev/1519228-obzor-samopisnoy-2d-sistemy-osveshcheniya-dlya-top-down-pixel-art-igr-na-raste-i-wgsl
2) https://dtf.ru/indie/1546633-dobavil-normalnyy-sheyding-obektov-nad-polom

Мне кажется у тебя картинка круче (у меня явно баг в самой трассировке). Я еще делал "пробы как в лумене" чтобы только для 1/64 пикселей считать и потом переиспользовать фреймы.

1