Pull to refresh

Comments 22

Как выяснилось, удара по производительности нет.

А бенчмарки есть?
Нужно бы выпустить демку, но на это нет времени :)

К сожалению, у меня сейчас нет доступа к актуальным компьютерам, работаю на ноутбуке. Поэтому — никаких графиков и замеров. У меня — видеокарта GeForce 540M, но поскольку даже на ней всё вполне себе работает, судите сами.

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

В любом случае, дело ДАЛЕКО не в тенях. Производительность — это прежде всего оптимизация сцены. Отсечение геометрии, разбиение на зоны. Если уделять этому внимание, производительность будет на высоте. Если не уделять — то какой бы простой ни был алгоритм у теней, игра будет ужасно тормозить.

Сам по себе движок Unity хорошо оптимизирован только под Outdoor, то есть единственный динамический Directional light, деревья, заменяемые на billboard'ы, и occlusion culling. Но в коридорных играх отсечение геометрии работает плохо, приходится прятать невидимые комнаты скриптом, вручную выключать источники света за закрытыми дверями, и в конечном счёте можно и вовсе вырубить на фиг встроенное отсечение геометрии, производительность от этого только вырастет.

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

На мобильниках наверняка можно что-нибудь упростить. Например, делать не PCF4x4 (25 выборок), а PCF 2x2 (9 выборок, т.е. четыре пикселя плюс ещё один ряд для ручной фильтрации). Можно сделать дизеринг опять же. Всё это надо пробовать и тестировать.

Я своим шейдером и этой статьёй только хотел показать, что совершенствовать графическую часть Unity можно и нужно. Но мой подход в конкретном алгоритме прямолинеен. Я в шейдерах новичок и не знаю всех тонкостей. Поэтому и прошу помощи, совета и особенно лУчшей реализации у более знающих людей.
Ещё можно переключать далёкие «лампочки» на упрощённый алгоритм. Скажем, в конце коридора пусть будет 4 выборки с дизерингом, а вблизи — честные 25 выборок. Какой-то небольшой прирост производительности это даст.
Тени одно из самых больных мест Unity, головной боли с ними сполна. Я давно мечтаю о PCSS для directional light, жаль я в шейдерных программах мало что понимаю…
Вообще-то, можно попробовать. Алгоритм directed-теней лежит в том же файле, там выше — такая же небольшая и очень простая функция. Если вы знаете кого-то, кто может сделать реально честный PCSS, пусть заглянет в тот файлик и допишет туда свою реализацию. Буду очень рад таким подвижкам. У меня, к сожалению, сейчас нет на это времени. Я этот алгоритм-то сделал полгода назад, в новогодние праздники. А сейчас просто оформил в статью :)
Вы наверняка видели NVidia ShadowWorks? Библиотека и её исходный код лежит в открытом доступе и существует даже проект с интегрированным в Unity HBAO+. Я думаю вполне можно было бы использовать их решение.
Слышал про NVidia ShadowWorks, смотрел демки, но ещё не заглядывал «под капот». Но обязательно попытаюсь разобраться, хотя быстрого результата можно не ждать. К сожалению, сейчас я на той ступени освоения шейдеров, что мне легче написать свой велосипед, чем вникнуть в готовые алгоритмы, особенно хитро оптимизированные. Я заниматься этим буду в любом случае, но выкладывая эту статью, я в первую очередь хотел участия в этой проблеме тех людей, которые хорошо разбираются в алгоритмах теней. Реализацию PCSS я видел ещё лет десять назад, наверняка на Хабре есть какой-нибудь профессионал, который по моей наводке с лёгкостью преобразит графику в Unity.

(а ещё больше мне хотелось бы, чтобы этой проблемой занялись сами разработчики Unity и хотя бы сделали возможность как-то менять алгоритмы, добавлять новые ползунки в настройки источника света и выложили какой-нибудь туториал у себя в документации… а ещё лучше, сделали бы пять презентов различных алгоритмов на выбор… эх, мечты...)
Последние новости.

Я получше изучил алгоритмы AMD CHS и nVidia PCSS и пришёл к выводу, что мой алгоритм (разрабатываемый, как велосипед) является подобным CHS, т.е. есть минимальный уровень размытия и есть максимальный, выше которого «размазать» тень не получится. Угол размера источника света (penumbra) действует только рядом с затенителем, а вдали уровень размытия у всех теней одинаков и максимален. В отличие от моего алгоритма у CHS нет эффекта shapen (т.е. он сохраняет детали в резком варианте), у меня была такая версия алгоритма, но мне не понравилась. При этом CHS использует мипмапы теневой карты, которые я не могу использовать (Unity их изначально не считает, я со своей стороны не могу их добавить). И фильтрация в CHS используется «родная», что в Unity недоступно для кубической текстуры. То есть в сравнении с CHS мой алгоритм актуален.

В результате я решил впилить PCSS во все типы источников света. Вроде бы, не так уж он и сложен: есть массив точек для выборок, распределённых по принципу poisson, по этим координатам идёт LookUp с замером дальности и сама выборка. Отлаживаю потихоньку, как впилю в Unity, можно будет написать вторую статью на эту тему.

Правда, появилась новая проблема. В файле «UnityShadowLibrary.cginc» лежат алгоритмы для Spot и Point источников света. Directed лежит где-то ещё. Что-то там автопоиском по файлам я нашёл, но пока не удаётся «нащупать» тот самый кусок с выборкой из теневой карты. Но будем надеяться на лучшее :(
Посмотрите в AutoLight.cginc, тени для directional light модифицируются именно в нём насколько я знаю.
Я в нём и смотрю, но как-то там всё запутано.

А в этом видео корейский разработчик вообще прям поверх жестких теней своё решение использует.
Ничего себе! Выглядит круто.
Вообще-то, надо и правда попробовать вырубить все каскады, включить самую простую тень и попробовать модифицировать её. У меня такое ощущение, что каскады прописаны в хардкоде движка, потому что в шейдерах на них я не видел ни одного намёка. Именно так поступил автор видео. Но с другой стороны, было бы неплохо использовать каскады. Что ж, будем эксперементировать.
Чтобы PCSS давал красивые тени, нужно много сэмплов, что сильно бьет по филлрейту, а это слабое место GPU среднего уровня.
Судя по демке от nVidia, PCSS нагружает видеокарту тогда, когда очень много размытых теней. Например, радиус максимального пятна — в четверть экрана. При том же числе максимальных выборок в настройках, большой параметр penumbra просаживает FPS относительно маленького penumbra на удалённых от затенителя участках. Это значение всегда можно ограничить.

Пока я планирую так: выборок сделаю всего 25 (самый минимальный параметр в демке от nVidia). Большое пятно в таком случае похоже на множество повторяющихся контуров, чтобы устранить это, в демке nVidia делали параметр в 100 выборок. Но я хочу попробовать оставить 25 выборок, но поворачивать паттерн случайным образом, тогда повторяющихся паттернов не будет видно, вместо этого на месте них будет виден едва различимый шум. Точнее, на белом фоне различить его будет возможно, но в сцене с хорошо проработанными текстурами, уверен, это не будет заметно.
Ради большого количества размытых теней PCSS и используют. Возможно, вам будет интересно попробовать вот эту модификацию PCSS.
Спасибо, интересно. Хотя для начала нужно запустить PCSS в Unity хоть каком-то виде.

Я согласен, что PCSS требует больших вычислительных мощностей, но всегда ведь можно выключить их в настройках.
Теперь уже честное PCSS, 48 выборок, Poisson Disk. Добавил немножко дизеринга туда, где не хватает выборок. На белом фоне сильно заметно, но с текстурами будет не особо. Была мысль, как сделать переходы плавнее, скрестив две техники, но не получилось, нужно было сделать больше выборок, были артефакты… В данном алгоритме, который на Гифке, моя собственная реализация PCSS, из примера nVidia я взял только координаты для poisson disk, а в остальном разобраться так и не смог (особенно зачем нужны функции ddx и ddy, там так намудрили, что жесть), поэтому сделал вот такой велосипед. Выборки делал через Sampler.Load, по-другому не выходило (Юнити по умолчанию настроил теневую выборку, лукап делать с помощью стандартного Sample не получалось… может быть, работать из-за этого будет чуть медленнее, а может, и нет, у меня вроде нормально отрисовывается). С Cubemap Pointlight тенями такой проблемы не было, там обыкновенные выборки. Пока сделал только под DirectX, а с OpenGL ещё надо повозиться. Также на гифке можно заметить косяки, которые я надеюсь исправить.

image
Выглядит здорово, много заняло времени?
Конкретно этот шейдер написан за пару ночей, он несложный. Но до этого я целый месяц пытался понять, почему не получается вставить код из демки nVidia, и в конце концов просто сделал с нуля так, как сам понял.
Sign up to leave a comment.

Articles