PDA

View Full Version : Cascaded shadow mapping - Texture lookup and depth comparison



Silverlan
08-28-2014, 02:04 PM
I'm trying to implement cascaded shadow mapping in my game engine, but I'm somewhat stuck at the last step. For testing purposes I've made sure all cascades encompass my entire scene. The result is currently this:
http://puu.sh/bbK9r/6b2a09a075.jpg (http://puu.sh/bbIZz/4a59d3d3d4.jpg)

At the top the texture of each cascade is displayed.
As you can see the shadows are rendered properly, however each cascade gets darker the bigger the area for the orthographic projection is. (Shouldn't it get lighter instead?)

This is how I do the texture lookup for the shadow maps inside the fragment shader:



layout(std140) uniform CSM
{
vec4 csmFard; // far distances for each cascade
mat4 csmVP[4]; // View-Projection Matrix
int numCascades; // Number of cascades to use. In this example it's 4.
};

uniform sampler2DArrayShadow csmTextureArray; // The 4 shadow maps

in vec4 csmPos[4]; // Vertex position in shadow MVP space

float GetShadowCoefficient()
{
int index = numCascades -1;
vec4 shadowCoord;
for(int i=0;i<numCascades;i++)
{
if(gl_FragCoord.z < csmFard[i])
{
shadowCoord = csmPos[i];
index = i;
break;
}
}
shadowCoord.w = shadowCoord.z;
shadowCoord.z = float(index);
shadowCoord.x = shadowCoord.x *0.5f +0.5f;
shadowCoord.y = shadowCoord.y *0.5f +0.5f;
return shadow2DArray(csmTextureArray,shadowCoord).x;
}


Right now I'm simply using the return value and multiply it with the diffuse color. Since I'm grabbing the depth value directly from the texture, that explains the different coloration of each cascade on the world. So either this is the wrong approach, or my cascade textures are incorrect to begin with.
For that reason I ended up trying it with a depth comparison instead, but only had limited success:


[...] // Same code as above
shadowCoord.w = shadowCoord.z;
shadowCoord.z = float(index);
shadowCoord.x = shadowCoord.x *0.5f +0.5f;
shadowCoord.y = shadowCoord.y *0.5f +0.5f;
float z = shadow2DArray(csmTextureArray,shadowCoord).x;
if(z < shadowCoord.w)
return 0.25f;
return 1.f;
}


While this resolves the different intensity of each cascade, it only works for the first cascade, all others are blank:

http://puu.sh/bbKap/60d91cc759.jpg (http://puu.sh/bbJYT/5d444a9a47.jpg)

(I colored the cascades because otherwise the transitions wouldn't be visible in this case)

What am I missing here?

Ed Daenar
08-28-2014, 07:46 PM
Your second approach is not correct. Shadow samplers return 1 or 0, depending on the result of the compare operation. They will, however, return an averaged value if PCF is enabled by setting the sampling of the texture to LINEAR. You may find easier to debug shadowing by setting it to NEAREST so you ensure the behavior is the 0 or 1 return value.

This brings me to the possible problem: did you activate depth compare on your sampling parameters for your texture? Did you define the compare function? If you didn't, I'm guessing the shadow sampler is just acting like a normal sampler and giving you the actual value on the texture, which means all you are doing at this point is projective texturing.

If you have, then what you may be seeing in your first image is simply heavy aliasing. I cannot really tell with this low resolution though. The banding that shows the different cascades could be due to the change in precision per cascade, so the aliasing has a different "pattern", so to speak. You are projecting shadows of the plane on the plane itself. The non linear nature of the standard z buffer makes it a pain when it comes to precision.

Silverlan
08-29-2014, 03:11 AM
I had the compare function set to GL_LEQUAL, but apparantly I forgot to actually enable it. The parameters are now:


glTexParameteri(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_MIN _FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_MAG _FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_COM PARE_MODE,GL_COMPARE_R_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_COM PARE_FUNC,GL_LEQUAL);


Not entirely sure what I have to change in the shader. For now this is the result:

1407 1408

Silverlan
09-24-2014, 03:03 PM
Still got some trouble with this, but I'm a step further now. The reason for the different 'brightness' of the shadow for each cascade was because I hadn't specified the compare mode for the textures:

glTexParameterf(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_COM PARE_MODE,GL_COMPARE_REF_TO_TEXTURE);

However the addition of that parameter also resulted in this:

http://youtu.be/JJN8EsXOPBk

So there's still something else going wrong...