You might post some details about how you are building your world-space-to-light-space transform, including how you are determining the bounds of your world-space and light-space frusta.
That we apparently see shadows “striping” across the scene suggests to me that possibly your shadow frusta doesn’t encompass the world-space bounds of your scene, so there we may be seeing texture border behavior. What do you have your GL_TEXTURE_WRAP_S and GL_TEXTURE_WRAP_T on your shadow map set to? GL_CLAMP_TO_EDGE? Just for grins try changing them to REPEAT. This isn’t going to fix anything, but does it stop your shadows from “striping” across the scene. Alternatively, what if in the shader you treat shadow map tex coordinates outside of (0…1,0…1) as “no shadow”. That should allow you to more easily see where in your scene your shadow map is projecting to, given your world-to-light-space transform. Alternatively, color your scene by the shadow map texcoords, with areas outside the shadow map bounds being black or grey.
This is my set up for constructing the world to lightspace matrix.
Shadow_Frag
#version 330 core
out vec4 FragColor;
in vec3 FragPos;
in vec3 Normal;
in vec2 TexCoords;
uniform mat4 MV;
uniform mat4 lightSpaceMatrix;
uniform sampler2D colourTex;
uniform sampler2D shadowTex;
uniform sampler2D positionTex;
uniform vec3 lightPos;
uniform vec3 viewPos;
float ShadowCalculation()
{
//view space position
vec4 wpos = vec4(texture(positionTex, TexCoords).rgb,1.0);
FragColor = wpos;//just for visualizing the "light space coords"
//NDC-space (not a problem with ortho projections)
vec3 projCoords = wpos.xyz / wpos.w;
// Transform to [0,1] range
projCoords = projCoords * .5 + .5;
// Get closest depth value from light's perspective (using [0,1] range fragPosLight as coords)
float closestDepth = texture(shadowTex, projCoords.xy).r;
// return vec3(texture(shadowTex, closestDepth).r);
// Get depth of current fragment from light's perspective
float currentDepth = projCoords.z;
// Check whether current frag pos is in shadow
vec3 lightDir = normalize(lightPos - FragPos);
float bias = max(0.05 * (1.0 - dot(Normal, lightDir)), 0.005);
//float bias = .01;
float shadow = 0.0;
vec2 texelSize = 1.0 / textureSize(shadowTex, 0);
for(int x = -1; x <= 1; ++x)
{
for(int y = -1; y <= 1; ++y)
{
float pcfDepth = texture(shadowTex, projCoords.xy + vec2(x, y) * texelSize).r;
shadow += currentDepth - bias > pcfDepth ? 1.0 : 0.0;
}
}
shadow /= 9.0;
// keep the shadow at 0.0 when outside the far_plane region of the light's frustum.
if(projCoords.z > 1.0)
shadow = 0.0;
return shadow;
}
void main()
{
float shadow = ShadowCalculation();
FragColor = vec4(texture(colourTex, TexCoords).rgb * (1-(shadow)),1.0);
//FragColor = lightSpaceMatrix*vec4(1);
}
}
Shadow_Vert
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texCoords;
layout (location = 2) in vec3 normal;
out vec3 FragPos;
out vec3 Normal;
out vec2 TexCoords;
uniform mat4 P;
uniform mat4 V;
uniform mat4 M;
uniform mat3 N; // This is the inverse transpose of the mv matrix
uniform mat4 MV;
uniform mat4 MVP;
void main()
{
gl_Position = MVP * vec4(position, 1.0);;
Normal = normalize(N * normal);
TexCoords = texCoords;
}
and when writing my position to lightspace to my sampler texture I perform the output:
// Compute the position of the vertex
gl_Position = MVP * vec4(VertexPosition,1.0);
Appologies for the large code dump.
I would be trustful of my shader however I’m doing the lightspace transformation on the vertex shader where I grab my positions from instead of the shadow vertex shader - this might be a mistake.
The texture coordinates you use to lookup into the shadow map with. The first occurrance in your fragment shader is: projCoords.xy
Until you have basic shadow mapping working, I’d comment out all that multi-sampling the shadow map stuff (PCF) you’ve got going on in your frag shader. Just sample it once, and then display the result of that on-screen. You can get fancy later.
Also, don’t have much time right now, but just scanning your shader I don’t see any reasonable logic to transform the input position from WORLD or CAMERA-EYE space to LIGHT-CLIP space to perform the shadow lookup. Unless I’m missing it, you need to add that.