Создание точечного источника света с помощью многоугольника видимости

Технические подобности реализации системы освещения в 2D-игре.

Французский инди-разработчик Пьер Вигьер в своём блоге подробно описывает процесс создания собственной RPG Vagabond. Автор детально разбирает технические аспекты каждого элемента игры, поэтому его пример может быть полезен начинающим разработчикам. В одном из постов Пьер уделил внимание созданию системы освещения в 2D-пространстве — мы выбрали из публикации самое главное.

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

Создание точечного источника света с помощью многоугольника видимости

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

Гифка, которая показывает этот процесс

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

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

​I — интенсивность; C — цвет; attenuation — ослабление света; attenuation(0) = 1; attenuation(d) = 0 для d>r.
​I — интенсивность; C — цвет; attenuation — ослабление света; attenuation(0) = 1; attenuation(d) = 0 для d>r.

Изначально Пьер использовал другую формулу для ослабления — она предназначалась для точечных источников света в 3D-пространстве.

Создание точечного источника света с помощью многоугольника видимости

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

Создание точечного источника света с помощью многоугольника видимости

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

Создание точечного источника света с помощью многоугольника видимости

Главный плюс этой формулы — освещённость пикселей за пределами радиуса равна нулю. Но затухание возле границы круга всё ещё немного жёсткое.

Создание точечного источника света с помощью многоугольника видимости

Чтобы получить более плавное затухание, Пьер просто возводит в квадрат предыдущую формулу, чтобы получить квадратичное ослабление.

Создание точечного источника света с помощью многоугольника видимости

Такой результат выглядит значительно лучше.

Создание точечного источника света с помощью многоугольника видимости

Наконец, Пьер советует использовать текстуру, которая поддерживает HDR с tone mapping. В ином случае отображение цвета будет зависеть от аддитивного блендинга.

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

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

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

А вот пример в пещере.

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

В игре Пьера будут и другие источники света, но точечные строятся по описанным правилам.

183183
17 комментариев

Когда них*я не понял, но выглядит потрясно!

22
Ответить

Когда все понял и понял, что здесь описаны очевидные вещи.

Но да - гифки прикольные.

14
Ответить

Да не выглядит оно потрясно. У него очень острые тени, будто вырезанные ножницами. В реальной жизни они выглядят куда мягче. Посмотрите на пример Олега пару сообщениями ниже.

9
Ответить

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

3
Ответить

Подобное использовалось в старой игрушке NOX

8
Ответить

Кстати, вот пример отличного точечного 2d-освещения на пиксельных шейдерах:

https://www.shadertoy.com/view/4dfXDn

6
Ответить

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

2
Ответить