GPSM: Geometry Pitch Shadow Map
Автор: Аврелий
GPSM (Geometry Pitch Shadow Map) — еще один метод рендеринга теневых карт, дающий возможность реализовать тени, покрывающие огромные территории, используя всего одну текстуру, в которую происходит рендеринг (render target). Метод GPSM даёт для теней вдали от камеры наблюдения качество хуже, а вблизи — лучше. Этот метод я изобрел для своего движка и уже использую в двух проектах, решил поделится с вами, надеюсь, кому-то пригодится.
Вступление
Привет всем обитателям GameDev.ru!
Возможно, всем вам известны мучения выбора метода рендеринга теней для своего проекта или движка. Такой выбор я для себя когда-то сделал, и это были PCF + Cascade.
Свет, конечно же, для OutDoor, т.е. directional
Больше всего в каскадных тенях мне не нравилось, что необходимо рендерить сцену несколько раз, и соблюдать условие, что геометрия иногда попадает и на одну и на другую теневую карту.
Поставил перед собой задачу — сделать рендер теней в одну текстуру, чтобы она накрывала более или менее качественно то, что вблизи, и то, что вдали менее качественно.
Сразу бросились в глаза, еле оторвал PSM LiPSM XPSM TSM... времени было мало, со всеми по-быстрому ознакомился, погонял демки и понял, что даже если использовать подобный метод, то придется делать с нуля, чтобы обойти проблемы увиденные в этих методах.
Убив три дня на настройку своего TSM, я был у цели, но у того подобия, что я реализовал было несколько минусов, которые в конце пути я обвешал костылями, которые не спасли ситуацию... и за 5 минут «начудил» GPSM. Потестировал, дал пафосное название, и взялся за написание статьи, возможно найдутся люди, заинтересовавшийся в использовании и развитии метода.
Теория
Суть проста, чем дальше геометрия, тем ближе ее надо притянуть к центру теневой карты. Делать это надо в шейдере глубины, используемой для рендера теневой карты, а также в шейдере наложения теней, для того, чтобы так же приближать текстурные координаты. Первое, что приходит в голову: найти дистанцию к точке, и по мере возростания дистанции приблизить к центру, выглядить это будет примерно так: