Comments 27
Недостаток, который пришёл в голову на первый взгляд: надо ввести ограничение на минимальный угол между лучами. Иначе, в случае наличия окружности (помимо прямых рёбер), производительность может получиться ниже, чем в случае изначального метода.
За счёт того, что окружность обычно рисуется большим количеством маленьких отрезков (треугольники, в случае 3D), которые будут иметь очень много "углов".
Лучше просто уменьшить количество "сторон" в окружностях. Хотя бы для расчетов.
Представьте как 3D-сцена попадает в 2-мерный Z-буфер, и положите одну из координат строго равной нолю.
При желании можно написать вершинный шейдер, который будет переводить (х, у) в полярные координаты, (r, phi) и использовать r как глубину. (Хотя у меня есть подозрение, что люди не заморачиваются и просто рисуют в 4 камеры с углом обзора 90 градусов каждая)
Эффективный расчёт области видимости...
Для десятков или сотен NPC отрисовывать в бекбуффер очень накладно получится. Тем более, что такой рендеринг это просто "базовый алгоритм" из статьи, где каждый фрагмент (пиксель) получает свой луч.
Зеленое — поле видимости, желтое — частичное скрытие (т.е. можно достаточно просто рендерить разные виды препятствий).
Геометрия препятствия — по сути 4 полигона с нулевой площадью вокруг квадратной «дыры» в центре. В шейдер передается положение «глаза» и геометрия препятствий просто тянется по направлению от «глаза» на какое-то большое расстояние, заведомо больше, чем дальность видимости. Препятствия рисуются с отключенным Color buffer с заполнением Stencil buffer разными числами. Последним рендерится геометрия поля видимости с автомаскировкой по Stencil buffer. Со стороны кода нужно только обновлять положение «глаза», все остальное делает GPU.
Ого. Я с помощью глубины делал — но у меня "источник" был только один. Рисовал объекты уровня на глубине 0, а у четырёхугольников-теней две вершины имели z=-1, и такой четырёхугольник "перекрывал" все другие объекты. маленькое видео
В видео подменяю материал, чтобы было видно как вытягивается геометрия — это делалось на CPU. Вытянутая геометрия рисуется первой и немного выше по Z, чем геометрия поля зрения.
В том видео, что выше — все делается уже на GPU. Каждое препятствие выглядит примерно вот так:

В центре дыра, по периметру 4 полигона, внешние вертексы расскрашены в белый цвет, внутренние в черный — это используется как маркер для того, чтобы различить в шейдере, что нужно тянуть. На картинке полигоны видимы, на самом деле их перед экспортом в движок нужно ставить максимально близко (но без слияния) к внутреннему краю. Размер внутреннего пустого «квадрата» — 1х1, чтобы в движке можно было проще подгонять под любой размер препятствия. Ну и в шейдере просто считается разница между «глазом» и каждым вертексом, нормализуется и смещается на большую дистанцию. Интенсивность смещения берется из цвета вертекса. Получается достаточно неплохо и, самое главное, быстро.
Впрочем, адекватная жертва скорости.
1) Отсортировать все вершины граней препятствий по часовой стрелке
2) Двигать заметающую прямую по кругу вокруг NPC — отслеживать ближайшую грань препятствий
3) на каждом участке до следующей вершины определять зону видимости в этой части сектора (по расположению ближайшей грани относительно сектора видимости: либо полный кусочек сектора, либо обрезанный гранью)
В результате должна получиться область видимости.
Оценка эффективности — O(N*log(N)), где N — количество вершин препятствий около NPC (можно предварительную выборку сделать ограничивающим прямоугольником).
Мне пока не доводилось решать задачу определения области видимости, могу что-то упускать.
Вы не рассматривали такой алгоритм, и если да — то чем не подходит?
Это реализованно на двухмерном массиве?
Если это массив то как мы пускаем луч? по формуле? или метод есть какой?
И как именно проверяется пересечение лучей?
Буду очень благодарен ибо инфу очень сложно добыть.
Спасибо!
Эффективный расчёт области видимости и линии взгляда в играх