Hi, I have been trying to implement cascading shadow maps. I have mostly been following this tutorial I found: Alex Tardif: Graphics Engineer and I have made decent progress. I have gotten the cascading working for the most part except for one small bug. It seems like there is a shadow gap showing up in between my shadow map split. I attached a picture below (ignore the shadow acne lol)
I am a little confused on why this is happening. In my glsl shader I uploaded the distances between my splits and check them against the gl_Position.z value like so:
//depth_value is gl_Position.z taken from the vertex shader.
for(int i = 0; i < 3; i++){
if(depth_value <= shadow_dists[i]){
shadow_sheet = i;
break;
}
}
This seemed to be working mostly fine. I think the issue is maybe I am misunderstanding how the distances are calculated between the shadow map splits. Below is some code with how I calculate the projection matrices for each shadow map and then the distances I use to check against.
f32 close_start = 0.1;
f32 med_start = 20;
f32 far_start = 80;
f32 far = 200
float aspect = (float)WINDOW_WIDTH / (float)WINDOW_HEIGHT;
Mat4 close_shadow_proj = mat4_perspective(close_start, med_start, 67.0f, aspect);
Mat4 med_shadow_proj = mat4_perspective(med_start, far_start, 67.0f, aspect);
Mat4 far_shadow_proj = mat4_perspective(far_start, far, 67.0f, aspect);
f32 shadow_dist [3];
shadow_dists[0] = med_start;
shadow_dists[1] = far_start;
shadow_dists[2] = far;
I will also attach my function which I use to generate the view * projection matrix values for each shadow map.
Mat4 calc_light_proj(Mat4* view, Mat4* perspective, V3 directional_light_pos)
{
V3 frustum_corner [8] =
{
{-1.0, 1.0, 0.0},
{ 1.0, 1.0, 0.0},
{ 1.0,-1.0, 0.0},
{-1.0 -1.0, 0.0},
{-1.0, 1.0, 1.0},
{ 1.0, 1.0, 1.0},
{ 1.0,-1.0, 1.0},
{-1.0,-1.0, 1.0},
};
Mat4 proj_view = mat4_mat4_mul(perspective, view);
Mat4 inv = mat4_inverse(&proj_view);
for(u32 i = 0; i < 8; i++)
{
V4 corner = {frustum_corner[i].x, frustum_corner[i].y, frustum_corner[i].z, 1.0f};
corner = mat4_v4_mul(&inv, &corner);
corner.x = corner.x / corner.w;
corner.y = corner.y / corner.w;
corner.z = corner.z / corner.w;
frustum_corner[i] = (V3){corner.x, corner.y, corner.z};
}
V3 center = {0};
for(u32 i = 0; i < 8; i++)
{
center = v3_add(¢er, &frustum_corner[i]);
}
center = v3_mul(1.0f/8.0f, ¢er);
V3 temp = v3_sub(&frustum_corner[0], &frustum_corner[6]);
f32 radius = v3_mag(&temp);
radius = radius / 2.0f;
f32 texels_per_unit = (f32)TEXTURE_SIZE / (radius * 2.0f);
Mat4 scalar =
{
texels_per_unit, 0, 0, 0,
0, texels_per_unit, 0, 0,
0, 0, texels_per_unit, 0,
0, 0, 0, 1
};
V3 neg_light_dir = v3_normalize(directional_light_pos);
V3 light_dir = v3_mul(-1.0f, &neg_light_dir );
Mat4 look_at = mat4_look_at(&(V3){0,0,0}, &light_dir, &(V3){0,1,0});
look_at = mat4_mat4_mul(&scalar, &look_at);
Mat4 inv_look_at = mat4_inverse(&look_at);
V4 center_4 = {center.x, center.y, center.z, 1.0f};
center_4 = mat4_v4_mul(&look_at, ¢er_4);
center_4.x = center_4.x / center_4.w;
center_4.y = center_4.y / center_4.w;
center_4.z = center_4.z / center_4.w;
center_4.w = 1;
center_4.x = floor(center_4.x);
center_4.y = floor(center_4.y);
center_4 = mat4_v4_mul(&inv_look_at, ¢er_4);
center_4.x = center_4.x / center_4.w;
center_4.y = center_4.y / center_4.w;
center_4.z = center_4.z / center_4.w;
center_4.w = 1;
center = (V3){center_4.x, center_4.y, center_4.z};
temp = v3_mul((radius * 2.0f), &light_dir);
V3 eye = v3_sub(¢er, &temp);
Mat4 light_view = mat4_look_at(&eye, ¢er, &(V3){0,1,0});
Mat4 light_proj = mat4_ortho(-radius, radius, -radius, radius, -radius * 6.0f, radius * 6.0f);
return mat4_mat4_mul(&light_proj, &light_view);
}
Am I misunderstanding where the cutoff for each projection matrix would be? I thought the that the first one would end at a depth of 20, the second at 80 and the third at 200?