Hi everyone,
I've been trying to implement a simple shadow mapping example with a directional light, but have so far been unable to get it working even though I'm pretty sure I followed the instructions correctly.
This is the tutorial I am trying to follow:
http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-16-shadow-mapping/I am using a deferred renderer, so initially I have a pass which generates textures for the world position, normal, specular and diffuse, and the directional light is rendered as a full screen quad which samples from the geometry buffer. I also have an initial pass which updates the shadow map, which looks like this:
I then run the lighting pass. For my directional light, I define the bias matrix as so:
biasMatrix = new Matrix4f(0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 0.0f, 0.5f, 0.0f, 0.0f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f);
To try and keep things as simple as possible, I am doing most of the work in the shaders, though once I have it working I will of course move things back onto the CPU where appropriate.
VERTEX
#version 440
layout(location = 0) in vec3 Position;
uniform mat4 pMatrix;
uniform mat4 vMatrix;
uniform mat4 mMatrix;
uniform mat4 biasMatrix;
out mat4 depthBiasMatrix;
void main()
{
mat4 depthMatrix = pMatrix * vMatrix * mMatrix;
depthBiasMatrix = biasMatrix * depthMatrix;
gl_Position = vec4(Position, 1.0);
}
FRAGMENT
#version 440
uniform vec2 gScreenSize;
uniform sampler2D gColorMap;
uniform sampler2D gNormalMap;
uniform sampler2D gShadowMap;
uniform sampler2D gPositionMap;
uniform vec3 lightColor;
uniform vec3 lightAngle;
uniform float lightBrightness;
in mat4 depthBiasMatrix;
out vec4 out_Color;
vec2 CalcTexCoord()
{
return gl_FragCoord.xy / gScreenSize;
}
void main()
{
vec2 texCoords = CalcTexCoord();
vec4 diffuse = texture(gColorMap, texCoords);
vec3 fPosition = texture(gPositionMap, texCoords).xyz;
vec4 ShadowCoord = depthBiasMatrix * vec4(fPosition,1.0);
vec3 vNormal = normalize(texture(gNormalMap, texCoords).xyz);
float brightness = max(dot(vNormal, lightAngle), 0);
vec3 DiffuseColor = lightColor * brightness * lightBrightness;
float visibility = 1.0;
if ( texture( gShadowMap, ShadowCoord.xy ).z < ShadowCoord.z){
visibility = 0.5;
}
out_Color = diffuse * vec4(DiffuseColor,1.0) * visibility;
}
As you can see, I first construct the depthBiasMatrix by using the same projection matrix, view matrix and model matrix I used to create the shadow map, and my bias matrix. I then pass this over to the fragment shader.
In the fragment shader I sample the position map to get the world position, multiply it by my depthBiasMatrix to create ShadowCoord, and then do a straight copy/paste of the tutorial to determine if that fragment is in shadow or not.
My problem is that it seems to always fail the condition, so everything is always fully visible. The directional lighting itself is correct (i.e. walls facing away from the light direction are dark, and the normal mapping works fine), but no shadows are cast.
I have no idea what I have done wrong here, I am certain my position map is correct as I populate it in the GBuffer as being modelMatrix * vertexPosition, i.e. its world position rather than local position. I also know my mvp matrix is correct as it is the same formula I use everywhere else.
Any pointers would be much appreciated!