Сообщение от pepel
круто. по какому принципу это все делается. всегда было интересно
|
Я рассмотрел много вариантов, и для меня самый гибкий вариант - это логика и простейшие пересечения отрезков.
По сути есть кастер (отрезок, линия). И есть источник света имеющий радиус. Исходя из радиуса мы рисуем квадрат вокруг. Далее проверяем на пересечение боундинг боксов источника света и отрезков, далее если они пересекаются, проверяем дальне на пересечение всех боков бокса света с кастером. Находим все точки пересечения. Есть сценарий когда все точки кастера в боксе и не пересекаются с боксом света. Иногда пересечение одно, а иногда их два.
Исходя из разницы пересечений уже идёт разделение логики по категориям.
Далее исходя из категорий, проводим новые отрезки на пересечения с боксом света - это края теней. Исходя из боков с которыми пересекается, и точек пересечения кастера, в некоторых сценариях есть разные под категории.
Например бывает 1 угол в тени, бывает 2. Бывает ни одного. Для каждой категории и суб категории отрисовка идёт чуток по разному.
Вся сложность теней в нахождении этих всех сценариев.
PDF в приложении, я делал давно исследование всех сценариев. И решил написать тени на canvas. Делал их ранее на другом движке, но там были баги. Тут же подошёл серьёзнее, и провёл две итерации с рефакторингом, в результате пашет как надо.
Тут в PDF описываются дополнительные сценарии когда источник света бывает не посередине самого квадрата источника света. Это бывает если квадрат ограничивается самим экраном для оптимизации. Я сделал без, т.к. было лень описывать доп. сценарии. Да и это очень мелкий прирост. Но всё равно сделаю в будущем.
Что нужно будет ещё сделать, это строить сперва массив кастеров в радиусе источника света, и затем уже делать проверку начиная с самых близких. Далее проверять если каждый последующий не перегораживается ранее обработанными - это не так и просто будет замутить, но даст огромный прирост в indoor ситуациях, где много деталей за стенками.
Можно прикрутить также порталы сюда.
А ещё НУЖНО прикрутить octree или т.п. для поиска отрезков.