PDA

View Full Version : Cascaded shadow mapping and determining the split



TheKaiser
04-09-2014, 04:39 AM
Reposting, as previous topic seems to have imploded.

For most of the part, the cascaded shadow mapping works as intended, but at certain angles shadows are cut. I believe it might be because of how I determine what split to use.

I do the split comparison in view space, see below:


#version 420

const float DEPTH_BIAS = 0.00005;

layout(std140) uniform UnifDirLight
{
mat4 mVPMatrix[4];
mat4 mCamViewMatrix;
vec4 mSplitDistance;
vec4 mLightColor;
vec4 mLightDir;
vec4 mGamma;
vec2 mScreenSize;
} UnifDirLightPass;

layout (binding = 2) uniform sampler2D unifPositionTexture;
layout (binding = 3) uniform sampler2D unifNormalTexture;
layout (binding = 4) uniform sampler2D unifDiffuseTexture;
layout (binding = 6) uniform sampler2DArrayShadow unifShadowTexture;

out vec4 fragColor;

void main()
{
vec2 texcoord = gl_FragCoord.xy / UnifDirLightPass.mScreenSize;

vec3 worldPos = texture(unifPositionTexture, texcoord).xyz;
vec3 normal = normalize(texture(unifNormalTexture, texcoord).xyz);
vec3 diffuse = texture(unifDiffuseTexture, texcoord).xyz;

vec4 camPos = UnifDirLightPass.mCamViewMatrix * vec4(worldPos, 1.0); // putting the world position in the main cameras view space

int index = 3;
if (camPos .z > UnifDirLightPass.mSplitDistance.x)
index = 0;
else if (camPos .z > UnifDirLightPass.mSplitDistance.y)
index = 1;
else if (camPos .z > UnifDirLightPass.mSplitDistance.z)
index = 2;

vec4 projCoords = UnifDirLightPass.mVPMatrix[index] * vec4(worldPos, 1.0);
projCoords.w = projCoords.z - DEPTH_BIAS;
projCoords.z = float(index);
float visibilty = texture(unifShadowTexture, projCoords);

float angleNormal = clamp(dot(normal, UnifDirLightPass.mLightDir.xyz), 0, 1);

fragColor = vec4(diffuse, 1.0) * visibilty * angleNormal * UnifDirLightPass.mLightColor;
}

When I calculate the split frustrum I also store the current splits far distance for use in the shader above


CameraFrustrum CalculateCameraFrustrum(const float minDist, const float maxDist, const Vec3& cameraPosition, const Vec3& cameraDirection, Vec4& camFarDist, const Mat4& camView)
{
CameraFrustrum ret = { Vec4(1.0f, 1.0f, -1.0f, 1.0f), Vec4(1.0f, -1.0f, -1.0f, 1.0f), Vec4(-1.0f, -1.0f, -1.0f, 1.0f), Vec4(-1.0f, 1.0f, -1.0f, 1.0f),
Vec4(1.0f, -1.0f, 1.0f, 1.0f), Vec4(1.0f, 1.0f, 1.0f, 1.0f), Vec4(-1.0f, 1.0f, 1.0f, 1.0f), Vec4(-1.0f, -1.0f, 1.0f, 1.0f), };

const Mat4 perspectiveMatrix = glm::perspective(70.0f, 1920.0f / (float)1080.0f, minDist, maxDist);
const Mat4 invMVP = glm::inverse(perspectiveMatrix * camView);

for (Vec4& v : ret)
{
v = invMVP * v;
v /= v.w;
}

camFarDist= ret[4];
camFarDist+= ret[5];
camFarDist+= ret[6];
camFarDist+= ret[7];
camFarDist/= 4;
camFarDist = camView * camFarDist; // putting it in main camera view space
// camFarDist.z is used as this splits far distance for the comparison in the shader

return ret;
}

Does this look correct?