Ограничения предварительно обожженных мягких теней
Я работаю в течение 2 месяцев над предварительным выпеканием PCSS nVidia с cubeTextures в WebGL. Мне удалось реализовать зверя в режиме реального времени. Предварительная выпечка, наконец, тоже работает, но с некоторыми очевидными артефактами.
Короче говоря, ниже я выделяю основной артефакт, который у меня есть, и объясняю, почему я его получаю, в общем случае, с которым должен столкнуться каждый, если он попытается заранее выпекать мягкие тени. Подводя итог этой теме, каждый совет по этому вопросу может помочь мне:
Как мы можем иметь дело с предварительно обожженными мягкими тенями?
Давайте упростим ситуацию, поговорив о мягких тенях вместо того, чтобы сосредоточиться на PCSS. Это означает, что мы работаем с shadowMap, содержащим значение видимости от 0 до 1 для каждого текселя (тогда как жесткие тени генерируют shadowMaps только с 2 возможными значениями: 0 или 1).
Поскольку мы не в режиме реального времени, мы должны зафиксировать точку зрения вместо того, чтобы использовать точку обзора камеры в каждом кадре. Мои мягкие тени рассчитаны с точки зрения света. Чтобы построить их, я:
- Вычислить базовую карту теней со всеми блокировщиками (окклюдерами)
- Во втором проходе, содержащем только приемники, я вычисляю мягкие тени, используя shadowMap, и сохраняю видимость для каждого пикселя.
Это дает мне предварительно вычисленную карту теней, которую я могу отобрать в режиме реального времени.
Первое ограничение предварительно запеченных мягких теней заключается в том, что блокаторы не могут быть частью приемников. Представьте себе комнату, полную окклюдеров, тогда единственным приемником, безусловно, будет комната. В противном случае вы потеряете тени на сетке комнаты. Причина в том, что мы застряли в легкой точке зрения, поэтому мы не можем видеть то, что стоит за блокировщиком, если мы тоже ставим его в качестве приемника.
Это ограничение приводит к получению карты теней с хорошим значением видимости для комнаты, но явно не для теней на блокаторах. Я не возражаю, чтобы получить правильное значение видимости на блокаторах, я надеялся, что смогу использовать тень комнаты как приближение для тени на блокаторах. Но на практике вы получите жесткие тени на блокаторах, потому что за блокатором значение видимости для тени комнаты полностью черное.
Вот график, чтобы проиллюстрировать, почему это происходит.
В верхнем случае я принимаю только комнату в качестве приемника. В нижнем случае я использую блокиратор как приемник тоже. Вы можете легко увидеть, что проблема появляется в обоих случаях. Поскольку для одного и того же текселя shadowMap нам нужны два разных значения видимости: точка в комнате полностью черная, а точка на блокере - в полутени.
У меня много идей для борьбы с этим артефактом:
- Отправка шейдерам meshId для каждой сетки и оценка этого идентификатора, чтобы узнать, скрываем ли мы блокатор или нет.
- Сделайте проход PCSS для каждого блокировщика отдельно и смешайте все карты теней в конце.
- Сделайте пропуск PCSS для каждого получателя отдельно (с учетом блокировщиков).
- Предварительно вычислите половину расчета и сделайте вторую половину в реальном времени.
- Предварительно вычисляйте shadowMap с нескольких точек зрения, кроме легкой.
Я потерпел неудачу в отношении 1 и 2. Идея 3 кажется такой же, как и идея 2. 4 глупо, это уже не предварительное вычисление. И я боюсь, что не смогу сделать идею 5 родовой.
Существует очень мало документации по этому вопросу. И большинство документов, которые я нашел, работали с идеальными сценами без блокировщика, скрывающего другого блокировщика, как если бы это был не обычный случай. Так может кто-то здесь уже сталкивался с этой проблемой или интересуется темой? Надеюсь, это поможет другим людям после меня тоже.
Тем не менее, спасибо за рассмотрение вопроса.