Ошибка доступа к текстуре карты теней в OpenglGL

Я пытаюсь реализовать каскадную карту теней, и у меня возникает ошибка, когда я хочу получить доступ к соответствующей текстуре глубины каждого раздела моего усеченного конуса.

Чтобы быть более конкретным, моя проблема возникает, когда я хочу выбрать правильную текстуру тени, если я попробую этот код ниже, у меня есть артефакт, как на этом рисунке, вы смотрите на тень куба, артефакт - маленькая точка / квадрат между границами резаного усеченного конуса (красный цвет для ближнего среза и зеленый для дальнего среза)

uniform sampler2D   shadowMaps[10];         //GL_TEXTURE5

uniform float       cameraFrustumZPartitionning[10];
uniform int         cameraFrustumSize;

int getCSMlevel(float Z){
    for(int iZ = 0 ; iZ < cameraFrustumSize; ++iZ)
        if(Z < cameraFrustumZPartitionning[iZ])
            return iZ;
    return -1;
}


float ShadowCalculation(vec4 fragPosLightSpace[3], int shadowMapId, float NdotD) //WIP
{
    int csmLevel = getCSMlevel(ClipSpacePosZ);

    vec4 fragPosLS = fragPosLightSpace[csmLevel];
    vec3 projCoords = fragPosLS.xyz / fragPosLS.w;

    // Transform to [0,1] range
    projCoords = projCoords * 0.5 + 0.5;

    float closestDepth = 0.0;


    if(csmLevel == -1)
        return 0.0;
    closestDepth = texture(shadowMaps[csmLevel], projCoords.xy).r;

    return 1.0 - ((projCoords.z  > closestDepth)?1.0:0.0);
}

И если я попробую этот код, то все в порядке.

uniform sampler2D   shadowMaps[10];         //GL_TEXTURE5

uniform float       cameraFrustumZPartitionning[10];
uniform int         cameraFrustumSize;

int getCSMlevel(float Z){
    for(int iZ = 0 ; iZ < cameraFrustumSize; ++iZ)
        if(Z < cameraFrustumZPartitionning[iZ])
            return iZ;
    return -1;
}


float ShadowCalculation(vec4 fragPosLightSpace[3], int shadowMapId, float NdotD) //WIP
{
    int csmLevel = getCSMlevel(ClipSpacePosZ);

    vec4 fragPosLS = fragPosLightSpace[csmLevel];
    vec3 projCoords = fragPosLS.xyz / fragPosLS.w;

    // Transform to [0,1] range
    projCoords = projCoords * 0.5 + 0.5;

    float closestDepth = 0.0;



    if(csmLevel == 0)
        closestDepth = texture(shadowMaps[0], projCoords.xy).r;
    else if(csmLevel == 1)
        closestDepth = texture(shadowMaps[1], projCoords.xy).r;
    else if(csmLevel == 2)
        closestDepth = texture(shadowMaps[2], projCoords.xy).r;
    else
        return 0.0;

    return 1.0 - ((projCoords.z  > closestDepth)?1.0:0.0);
}

В GLSL мы можем создать массив sampler2D и получить правильный, обращаясь к массиву с помощью переменной, или я здесь совершил огромную ошибку?

1 ответ

Решение

От GLSL 4.50 спецификация:

При объединении в массивы внутри шейдера сэмплеры могут индексироваться только с помощью динамически однородного интегрального выражения, в противном случае результаты не определены.

Это означает, что все вызовы фрагментного шейдера должны использовать один и тот же индекс. Ваш первый код явно не удовлетворяет этому. Во второй версии исполнение явно расходится, поэтому для каждого пути кода индекс является динамически однородным.

Изменить: Так как ваши карты теней, вероятно, имеют одинаковый размер, вы можете использовать вместо текстуры массива. (Текстуры массивов не являются массивами сэмплеров.)

Другие вопросы по тегам