I am attempting to implement shadow mapping using opengl, using a directional light.
I have confirmed that the depth texture is correctly rendered, like so:
And to perform a visual inspection, I also output the world space coordinates, transformed to light perspective:
Which again, seems to be ok.
However, when I sample the depth texture, using:
vec3 coord = vec3(shadowCoords.xy,shadowCoords.z/shadowCoords.w);
float depth = texture( shadowMap, coord);
I find that the comparison always fails. If I change uniform sampler2DShadow shadowMap;
to uniform sampler2D shadowMap;
, and sample the texture directly using texture( shadowMap, coord.xy).r
, I find that the sampled value is always zero, by outputting this result to the screen.
I created the depth texture like so:
glGenTextures(1, &m_DepthTexture);
glBindTexture(GL_TEXTURE_2D, m_DepthTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_DepthTexture, 0);
and my shader code is as follows(vertex):
#version 430
// Some drivers require the following
precision highp float;
layout (location = 0)in vec3 MSVertex;
layout (location = 4)in vec2 MSTexCoord;
out xferBlock
{
vec3 VSVertex;
vec2 VSTexCoord;
} outdata;
void main()
{
outdata.VSVertex = MSVertex;
outdata.VSTexCoord = MSTexCoord;
gl_Position = vec4(MSVertex,1.0);
}
and fragment shader:
#version 430 core
// Some drivers require the following
precision highp float;
layout (location = 0) uniform sampler2D positionMap;
layout (location = 1) uniform sampler2D normalMap;
layout (location = 2) uniform sampler2D colourMap;
layout (location = 3) uniform sampler2D specularMap;
layout (location = 4) uniform sampler2DShadow shadowMap;
struct DirLightData
{
vec4 colour;
float intensity;
vec4 direction;
};
uniform mat4 ShadowTransform;
uniform DirLightData dirLight;
out vec4 colour;
uniform vec3 WSCamPos;
in xferBlock
{
vec3 VSVertex;
vec2 VSTexCoord;
} indata;
vec3 computeLight(vec3 Ldirection, vec3 Vdirection, vec3 Lcolour, vec3 normal, float Lintensity, float specular)
{
vec3 diffCol = Lcolour * max(0.0,dot(normalize(normal),-Ldirection));
vec3 reflectVec = normalize(reflect(Ldirection,normal));
float specFactor = max(dot(reflectVec,Vdirection),0);
float specPow = pow(specFactor,specular*255.0);
vec3 specCol = Lcolour * specPow;
return (diffCol+specCol)*Lintensity;;
}
float computeOcclusion(vec4 shadowCoords)
{
float vis = 1.0;
vec3 coord = vec3(shadowCoords.xyz/shadowCoords.w);
float depth = texture( shadowMap, vec3(coord.xy,coord.z+0.05));
if ( depth < coord.z);
{
vis = 0.5;
}
return vis;
}
void main()
{
vec4 pcolour = texture(positionMap, indata.VSTexCoord).rgba;
vec4 ncolour = texture(normalMap, indata.VSTexCoord).rgba;
vec4 dcolour = texture(colourMap, indata.VSTexCoord).rgba;
vec4 scolour = texture(specularMap, indata.VSTexCoord).rgba;
vec4 shadowCoord = ShadowTransform * pcolour;
float visibility = computeOcclusion( shadowCoord );
//float depth = texture(shadowMap, shadowCoord.xy).z;
vec3 vToEye = WSCamPos - pcolour.xyz;
vToEye = normalize(vToEye);
vec3 outColour = vec3(0.0,0.0,0.0);
outColour = computeLight(dirLight.direction.xyz,vToEye,dirLight.colour.rgb,ncolour.rgb,dirLight.intensity,scolour.r);
colour = vec4(visibility*(dcolour.rgb*outColour),1.0);
}
Can anyone spot where this is going wrong?
Problems like this are hard to spot so here are a few things that you need to take a look at:
You are using a samplerShadow
which is special in it's own way, you need to set COMPARE_R_TO_TEXTURE
and with that you don't need that if
statement. Alternatively you can use sampler2D
, but you need to do an if
statement in the shader, something similar to what you did, but the coord has to be vec2
not vec3
consider using textureProj
with vec4
texture coord. because it's much easier to transform world position in light space using a matrix multiplication. It's the same matrix that you use for rendering the shadow map in the first place. In your case it's this value vec4 shadowCoord = ShadowTransform * pcolour;
; use shadowCoord
directly with textureProj
.