ПрограммированиеСтатьиГрафика

Software Occlusion Culling

Автор:

Оклюжен кулинга сейчас, наверное, нет только у ленивых. Некоторые используют HW OC, у которых есть очевидные недостатки в виде латентности и дополнительной нагрузки на GPU. Другие используют софтовую растеризацию. К примеру, мы можем растеризовать глубину близлежащих оклюдеров (специальной или прямо рендер геометрии), затем проверять баунд боксы отрисовываемых объектов относительно этой глубины. Радостей от такого подхода может быть несколько.

Во-первых, мы может рисовать это всё в уменьшенном разрешении. Во-вторых, такая отрисовка достаточно легко параллелится на несколько потоков, что в наше время непрерывного увеличения числа ядер у CPU является приятным бонусом. Для растеризации есть два основных алгоритма — сканлайны и халфспейсы. При использовании сканлайнов мы просто рисуем горизонтальные линии между ребрами треугольника. При использовании халфспейсов, строим вьюпорт спейс баунд рект треугольника, итерируемся по всем пикселям, которые в нём, и, если пиксель внутри треугольника, то рисуем его. Но в целом нам достаточно определить сам факт того, скрыта ли текстурируемая геометрия оклюдерами или нет.

softwareoccluder | Software Occlusion Culling

Тут вот на форуме, Петя предложил крутую технику оклюжен кулинга. Принцип прост: мы хотим записывать / тестировать максимальное количество пикселей треугольников за такт работы внутреннего цикла растеризатора с одной стороны. С другой стороны, нам, в общем-то, не нужна информация о глубине каждого пикселя в оклюжен буфере. Достаточно знать находится ли в этом пикселе оклюдер или нет, одного битика хватит за глаза. В традиционных софтовых оклюдерах сначала отрисовывались все оклюдеры и лишь затем проверялась тест-геометрия. Нам такой подход не подойдет по понятным причинам. Нам придётся сортировать все треугольники по Z (минимальный Z для тест геометрии и максимальный Z для оклюдер геометрии) и только потом рисовать. Зато, после сортировки, используя SSE, мы можем писать / тестировать аж 128 пикселей за итерацию внутреннего цикла растеризатора. В связи с тем, что мы можем писать фиксированное количество пикселов за шаг, имеет смысл разбить оклюжен буфер на тайлы. Ширина SSE регистров естественным образом задаёт ширину тайла, высота может быть выбрана произвольная. Моя реализация работает примерно так:

В общем-то, базовую версию алгоритма несложно реализовать и проверить самим. Моя текущая имплементация может рисовать 300к+ треугольников снапшота с игровой камеры Death Track примерно за 20мсек (12 мсек трансформаци + 8 мсек растеризация) в 720п, что неплохо. И надо понимать, что это однопоточная синхронная версия. Думаю, на архитектурах с большим числом регистров, будет чуть лучше. Если прикрутить потоки, опять же, думаю, станет ощутимо лучше. Очень органично ложится на концепцию Job Manager. Интересным также выглядит попытка автоматической генерации оклюдеров и тест геометрии. Респекты и уважухи Пете за крутую идею и обсуждение деталей реализации.

Пример реализации с исходниками: Реализация Software Occlusion Culling

unoccluded_wireframe | Software Occlusion Culling unoccluded_solid | Software Occlusion Culling

occluded_wireframe | Software Occlusion Culling occluded_solid | Software Occlusion Culling

#occlusion

3 апреля 2011

Комментарии [134]