Каскадные тени наносят на карту швы между расколами - PullRequest
0 голосов
/ 12 апреля 2020

Итак, я решил внедрить CSM для улучшения разрешения теней в моих сценах. Это работает довольно хорошо, как можно увидеть здесь: enter image description here Прямо сейчас я передаю количество разделений в качестве аргумента, но отношение каждого разделения довольно жестко закодировано. Мне интересно, есть ли хорошее обобщенное c решение для вычисления расщепления для лучших теней на основе чего-либо, или это больше искусство, чем что-либо еще, и мне просто нужно поиграть со значениями?

Также я получаю швы теней на границы каждой карты теней, потому что разрешение карты теней, очевидно, изменяется из-за того, что световой усеченный размер увеличивается после каждого каскада, уменьшая разрешение go: enter image description here

Теперь я не мог не понимаю, что я могу с этим поделать. Я читал в Интернете, что я должен сэмплировать карты расщепления теней и линейную интерполяцию их ... но я даже не уверен, как?

Способ, которым я сейчас делю каскады, - это жестко заданное фиксированное отношение. первый сплит 0.0366... * far. второй сплит - 0.5 * far. второй сплит - 1.0 * far.

Эти значения были предназначены только для тестирования и демонстрации швов между первым и вторым разделением.

Я выбрал правильную карту теней, рассчитав положение фрагмента z в пространстве клипа и передайте его фрагментному шейдеру:

    vs_out.v_FragPosClipSpaceZ = (u_Projection * u_View * u_Model * vec4(position, 1.0).z;

Я передаю универсальный uniform float u_CascadeEndClipSpace[NR_LIGHT_SPACE]; фрагментному шейдеру, который является всеми дальними плоскостями каждой области обзора, которую CSM разделяет в пространстве клипа камеры. Затем я проверяю, меньше ли v_FragPosClipSpaceZ, чем u_CascadeEndClipSpace[i], и, если да, то сэмплируем uniform sampler2D u_ShadowMap[NR_LIGHT_SPACE]; в соответствии с i в шейдере фрагментов:

    float shadow = 0.0f;
    for (int i = 0; i < NR_LIGHT_SPACE; i++) {
        if (fs_in.v_FragPosClipSpaceZ <= u_CascadeEndClipSpace[i]) {
            shadow = isInShadow(fs_in.v_FragPosLightSpace[i], normal, lightDirection, i);
            break;
        }
    }

Все расщепления имеют одинаковое разрешение карты прямо сейчас исправлено 8192.

Помощь по этому вопросу была бы признательна!

EDIT1:

Пытался смешаться следующим образом, но получил тот же результат:

float shadow = 0.0
    for (int i = 0; i < NR_LIGHT_SPACE; i++) {
        if (fs_in.v_FragPosClipSpaceZ <= u_CascadeEndClipSpace[i]) {
            shadow = isInShadow(fs_in.v_FragPosLightSpace[i], normal, lightDirection, i);
            float diff = u_CascadeEndClipSpace[i] - fs_in.v_FragPosClipSpaceZ;
            float frustumLength = u_CascadeEndClipSpace[i] - (i > 0 ? u_CascadeEndClipSpace[i - 1] : 0.0);
            float diffRatio = clamp(diff / frustumLength, 0.0, 1.0) * 0.1;
            if (i < NR_LIGHT_SPACE - 1 && diffRatio < 1.0) {
                float nextShadow = isInShadow(fs_in.v_FragPosLightSpace[i + 1], normal, lightDirection, i + 1);
                shadow = mix(shadow, nextShadow, diffRatio);
            }
            break;
        }
    }
...