I'm still a bit unsure about the implementation of cascaded shadow mapping.

This is what it looks like at the moment:

https://puu.sh/emP0l/e405322704.jpg

At the top left are the 4 cascades - All of them encompass the same area for testing purposes.

This is without GL_COMPARE_REF_TO_TEXTURE, so all I'm doing is a depth lookup into the shadow map and multiplying the result with the diffuse fragment color. (Hence the different shadow intensities)

If I activate the comparison by setting the compare mode to GL_COMPARE_REF_TO_TEXTURE, this is the result:

https://puu.sh/emP0R/5bbce28fd2.jpg

This works, however, as you can see in the screenshot, there are several shadows that obviously don't belong there.

Here are my shaders:

Vertex Shader:

Code :

#version 330 core layout(location = 0) in vec4 vertPos; layout(location = 1) in vec2 vertexUV; layout(std140) uniform ViewProjection { mat4 M; mat4 V; mat4 P; mat4 MVP; }; out vec4 Position_worldspace; out vec4 Position_cameraspace; out vec2 UV; void main() { gl_Position = MVP *vertPos; Position_worldspace = M *vertPos; Position_cameraspace = V *M *vertPos; UV = vertexUV; }

Fragment Shader:

Code :

#version 330 core layout(std140) uniform CSM { vec4 csmFard; mat4 csmVP[4]; int numCascades; }; uniform sampler2D diffuseMap; uniform sampler2DArrayShadow csmTextureArray; in vec4 Position_worldspace; in vec4 Position_cameraspace; in vec2 UV; out vec4 color; float GetShadowTerm(sampler2DArrayShadow shadowMap) { int index = numCascades -1; mat4 vp; for(int i=0;i<numCascades;i++) { if(gl_FragCoord.z < csmFard[i]) { vp = csmVP[i]; index = i; break; } } vec4 shadowCoord = vp *Position_worldspace; 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(shadowMap,shadowCoord).x; } void main() { color = texture2D(diffuseMap,UV).rgba; color.rgb *= GetShadowTerm(shadowMap); }

This is essentially the same implementation as described in this document.

The only note-worthy difference, as far as I can tell, is in their shadow-map-lookup function:

Code :

float shadowCoef() { int index = 3; // find the appropriate depth map to look up in // based on the depth of this fragment if(gl_FragCoord.z < far_d.x) index = 0; else if(gl_FragCoord.z < far_d.y) index = 1; else if(gl_FragCoord.z < far_d.z) index = 2; // transform this fragment's position from view space to // scaled light clip space such that the xy coordinates // lie in [0;1]. Note that there is no need to divide by w // for othogonal light sources vec4 shadow_coord = gl_TextureMatrix[index]*vPos; // set the current depth to compare with shadow_coord.w = shadow_coord.z; // tell glsl in which layer to do the look up shadow_coord.z = float(index); // let the hardware do the comparison for us return shadow2DArray(stex, shadow_coord).x; }

More specifically, this line in particular:

They're using the view-space position, where I'm using the world-space position. In my case it only looks "right" with the world-space position, I can only guess that means my shadow matrices are incorrect?Code :

vec4 shadow_coord = gl_TextureMatrix[index]*vPos;

The projection matrix for all cascades is currently calculated like this:

Code :

glm::vec3 min(-1024.f,-512.f,-1024.f); // Area, in which all shadow casters are located glm::vec3 max(1024.f,512.f,1024.f); glm::mat4 matProj = glm::ortho(min.z,max.z,min.x,max.x,-max.y,-min.y);

As for the view matrix:

'pos' being the origin of the light (Which shouldn't matter(?), since we're using an orthographic projection), and 'dir' is its direction (Straight down).Code :

glm::vec3 pos = glm::vec3(176.f,432.f,-390.f); glm::vec3 dir = glm::vec3(0.f,-1.f,0.f); glm::mat4 matView = glm::lookAt( pos, pos +dir, glm::vec3(1.f,0.f,0.f) );

What am I missing?