I've read several articles here at stackoverflow and in some books. But I can't find the error in my code. I have an deferred renderer and saved albedo, depth and normals (including spec) inside the g-buffer. Moreover created an shadow map from a light source from top of the scene.
It looks like this:
Albedo (R8G8B8A8):
Normal (R8G8B8A8):
Linear Depth (F32):
Shadow map from light source (linear depth) (500 meter above camera):
Ok. My shader code of the deferred with shadow mapping look like this: I have uploaded row major matrices.
Vertex Shader:
layout(row_major) uniform UVSViewMatrix
{
mat4 m_ScreenMatrix;
};
layout(location = 0) in vec3 VertexPosition;
smooth out vec2 PSTexCoord;
void main()
{
vec4 Position = vec4(VertexPosition.xyz, 1.0f);
PSTexCoord = Position.xy;
gl_Position = Position * m_ScreenMatrix;
}
Fragment Shader:
#version 410
// -----------------------------------------------------------------------------
// Input from engine
// -----------------------------------------------------------------------------
layout(row_major) uniform UPSCameraProperties
{
mat4 m_ProjectionMatrix;
mat4 m_CameraView;
vec3 m_CameraPosition;
vec3 m_CameraDirection;
};
layout(row_major) uniform UPSLightProperties
{
mat4 m_LightProjection;
mat4 m_LightView;
vec4 m_LightPosition;
vec4 m_LightAmbientIntensity;
vec4 m_LightDiffuseIntensity;
vec4 m_LightSpecularIntensity;
};
uniform sampler2D PSTextureAlbedo;
uniform sampler2D PSTextureNormalSpecular;
uniform sampler2D PSTextureDepth;
uniform sampler2D PSTextureShadowMap;
// -----------------------------------------------------------------------------
// Input from vertex shader
// ----------------------------------------------------------------- ------------
smooth in vec2 PSTexCoord;
// -----------------------------------------------------------------------------
// Output to systembuffer
// -----------------------------------------------------------------------------
layout (location = 0) out vec4 PSOutput;
// -----------------------------------------------------------------------------
// Functions
// -----------------------------------------------------------------------------
vec3 GetViewSpacePositionFromDepth(float _Depth, vec2 _ScreenPosition, mat4 _InvertedProjectionMatrix)
{
// -----------------------------------------------------------------------------
// Information from:
// http://mynameismjp.wordpress.com/2009/03/10/reconstructing-position-from-depth/
// -----------------------------------------------------------------------------
vec4 ScreenPosition;
ScreenPosition.x = _ScreenPosition.x * 2.0f - 1.0f;
ScreenPosition.y = _ScreenPosition.y * 2.0f - 1.0f;
ScreenPosition.z = _Depth * 2.0f - 1.0f;
ScreenPosition.w = 1.0f;
// -----------------------------------------------------------------------------
// Transform by the inverse projection matrix
// -----------------------------------------------------------------------------
vec4 VSPosition = ScreenPosition * _InvertedProjectionMatrix;
// -----------------------------------------------------------------------------
// Divide by w to get the view-space position
// -----------------------------------------------------------------------------
return (VSPosition.xyz / VSPosition.w);
}
// -----------------------------------------------------------------------------
float GetShadowAtPosition(vec3 _WSPosition)
{
// -----------------------------------------------------------------------------
// Set worls space coord into light projection by multiply with light
// view and projection matrix;
// -----------------------------------------------------------------------------
vec4 LSPosition = vec4(_WSPosition, 1.0f) * m_LightView * m_LightProjection;
// -----------------------------------------------------------------------------
// Divide xyz by w to get the position in light view's clip space.
// -----------------------------------------------------------------------------
LSPosition.xyz /= LSPosition.w;
// -----------------------------------------------------------------------------
// Get uv texcoords for this position
// -----------------------------------------------------------------------------
vec3 ShadowCoord = LSPosition.xyz * 0.5f + 0.5f;
// -----------------------------------------------------------------------------
// Get final depth at this texcoord and compare it with the real
// position z value (do a manual depth test)
// -----------------------------------------------------------------------------
float DepthValue = texture( PSTextureShadowMap, vec2(ShadowCoord.x, ShadowCoord.y) ).r;
float Shadow = 1.0f;
if (ShadowCoord.z > DepthValue)
{
Shadow = 0.3f;
}
return Shadow;
}
// -----------------------------------------------------------------------------
// Main
// -----------------------------------------------------------------------------
void main()
{
// -----------------------------------------------------------------------------
// Get informations from g-buffer
// -----------------------------------------------------------------------------
vec2 TexCoord = vec2(PSTexCoord.s, 1.0f - PSTexCoord.t);
vec4 AlbedoColor = texture(PSTextureAlbedo , TexCoord);
vec4 NormalSpec = texture(PSTextureNormalSpecular, TexCoord);
float Depth = texture(PSTextureDepth , TexCoord).r;
vec3 VSPosition = GetViewSpacePositionFromDepth(Depth, TexCoord, inverse(m_ProjectionMatrix));
vec3 Normal = normalize(NormalSpec.xyz);
float SpecularExponent = NormalSpec.w;
vec4 WSPosition = vec4(VSPosition, 1.0f) * inverse(m_CameraView);
// -----------------------------------------------------------------------------
// Compute lighting (Light Accumulation)
// -----------------------------------------------------------------------------
vec3 CameraPosition = m_CameraPosition.xyz;
vec3 LightPosition = m_LightPosition.xyz;
vec3 EyeDirection = WSPosition.xyz - CameraPosition;
vec3 LightDirection = normalize(LightPosition - WSPosition.xyz);
vec3 LightReflection = normalize(-reflect(LightDirection, Normal));
vec4 AmbientColor = m_LightAmbientIntensity;
vec4 DiffuseColor = clamp(m_LightDiffuseIntensity * max(dot(Normal, LightDirection), 0.0f), 0.0f, 1.0f);
vec4 SpecularColor = clamp(m_LightSpecularIntensity * pow(max(dot(LightReflection, EyeDirection), 0.0f), SpecularExponent), 0.0f, 1.0f);
float Shadow = GetShadowAtPosition(WSPosition.xyz);
// -----------------------------------------------------------------------------
// Final result
// -----------------------------------------------------------------------------
PSOutput = vec4((AlbedoColor * (AmbientColor + DiffuseColor) * Shadow).xyz, 1.0f);
}
At the end my result look like this:
Did anyone can see my mistake?
Some measurement results:
ShadowCoord.xy is always 0.5, 0.5
ShadowCoord.z seams to be 1.0f
Here are some variable values:
LightProjection
(
1.29903805f, 0.0f, 0.0, 0.0f,
0.0f, 1.73205066f, 0.0f, 0.0f,
0.0f, 0.0f, -1.00024426f, -1.0f,
0.0f, 0.0f, -1.00024426f, 0.0f
);
LightView
(
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, -1500.0f, 1.0f
);
CameraProjection
(
1.29903805f, 0.0f, 0.0f, 0.0f,
0.0f, 1.73205066f, 0.0f, 0.0f,
0.0f, 0.0f, -1.00024426f, -1.0f,
0.0f, 0.0f, -1.00024426f, 0.0f
);
CameraView
(
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, -1000.0f, 1.0f
);
(0,0,-1000.0)
and the camera at(0,0,-1500.0)
with the same orientation for x/y/z-axes. You should consider moving the light around somewhere in the X or Y direction to see if that changes anything. – Andon M. Coleman