4

I'm trying to implement the cascaded shadow map, and I have a bug when I want to access to the corresponding depth texture of each partition of my frustum.

To be more specific my problem occur when I want to select the correct shadow texture, if I try this code below, I have an artifact like in this picture, you are looking at the shadow of a cube, the artifact are the little dot/square between the limits of the cutted frustum (red color is for near cut and green is for far cut)

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);
}

And if I try this code everything is fine.

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);
}

In GLSL we are able to make array of sampler2D and get the correct one by accessing the array with a variable or I making a huge mistake here?

Peter O.
  • 32,158
  • 14
  • 82
  • 96

1 Answers1

2

From GLSL 4.50 spec:

When aggregated into arrays within a shader, samplers can only be indexed with a dynamically uniform integral expression, otherwise results are undefined.

Which means that all fragment shader invocations shall evaluate to use the same index. Your first code clearly does not satisfy that. In the second version the execution is explicitly diverging, so for each code-path the index is dynamically uniform.

Edit: Since your shadow-maps are probably of the same size, you can use array textures instead. (Array textures are not arrays of samplers.)

Yakov Galka
  • 70,775
  • 16
  • 139
  • 220
  • I thought this was only for the declaration of the array, they do this in this tutorial (http://ogldev.atspace.co.uk/www/tutorial49/tutorial49.html), I miss something or I don't really understand what a dynamically uniform integral expression stand for. – guillaume voisin Oct 29 '16 at 22:10
  • Unfortunately They are not of the same size. – guillaume voisin Oct 29 '16 at 22:17
  • That quote speaks of *indexing*. The sizes of arrays, on the other hand, have to be *constant expressions*, which is stronger than *dynamically uniform expressions*. Also tutorials might be wrong. – Yakov Galka Oct 29 '16 at 22:17
  • I manage to make it work thank to you, I was looping over an uniform int so my index wasn't a dynamically uniform integral expression. Instead I loop over a constant value in the main function and it's working. Thank a lot ! – guillaume voisin Oct 29 '16 at 22:23
  • I looked at the tutorial and all the shadow maps there are of the same size, so texture arrays sound like a viable solution for you. – Yakov Galka Oct 29 '16 at 22:25