I am trying to add real time shadow mapping to my Minecraft-like clone as per the tutorial: here
First what happens:

From what I can tell, the shadow map is rendering correctly? The problem seems to be during the final pass.
I create the depth texture:
glGenFramebuffers(1, &m_frameBufferId);
glBindFramebuffer(GL_FRAMEBUFFER, m_frameBufferId);
glGenTextures(1, &m_depthTexture);
glBindTexture(GL_TEXTURE_2D, m_depthTexture);
glTexImage2D(GL_TEXTURE_2D, 0,GL_DEPTH_COMPONENT16, 1024, 1024, 0,GL_DEPTH_COMPONENT, GL_FLOAT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_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_NONE);
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_depthTexture, 0);
glDrawBuffer(GL_NONE);
Note: I also tried using GL_COMPARE_R_TO_TEXTURE with sampler2DShadow in the shader. Same outcome.
Then run both passes:
// ==================== Shadow =====================
glBindFramebuffer(GL_FRAMEBUFFER, m_frameBufferId);
glViewport(0, 0, 1024, 1024);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
ShadowShader->Bind();
VCSceneGraph::Instance->RenderGraph();
// ==================== Final =======================
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, 1280, 800);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
VoxelShader->Bind();
VCSceneGraph::Instance->RenderGraph();
Shadow Shader code:
// ==================== Vert =====================
#version 330 core\n
in vec4 vertexPosition_modelspace;
uniform mat4 depthMVP;
void main()
{
gl_Position = depthMVP * vertexPosition_modelspace;
}
// ==================== Frag =====================
#version 330 core\n
out float fragmentdepth;
void main()
{
fragmentdepth = gl_FragCoord.z;
}
Final-Pass (Voxel Shader) code:
// ==================== Vert =====================
#version 330 core\n
in vec3 position;
in int normal;
in vec4 color;
out vec4 colorVarying;
out vec4 ShadowCoord;
uniform mat4 modelViewProjectionMatrix;
uniform mat4 DepthBiasMVP;
void main()
{
gl_Position = modelViewProjectionMatrix * vec4(position, 1);
ShadowCoord = DepthBiasMVP * vec4(position, 1);
colorVarying = color;
}
// ==================== Frag =====================
#version 330 core\n
in vec4 colorVarying;
in vec4 ShadowCoord;
out vec4 color;
uniform sampler2D shadowMap;
void main()
{
float visibility = 1.0;
if ( texture(shadowMap, ShadowCoord.xy).z < ShadowCoord.z)
{
visibility = 0.5;
}
color.xyz = colorVarying.xyz * visibility;
color.w = colorVarying.w;
}
I suspect my issue is in the code that updated the uniforms for the final pass:
// Re-create the exact same MVP matrix that was used for the shadow pass
glm::mat4 depthProjectionMatrix = glm::ortho<float>( -30, 30, -30, 30, -100, 100);
glm::mat4 depthViewMatrix = glm::lookAt(glm::vec3(0.5f, 2, 2), glm::vec3(0,0,0), glm::vec3(0,1,0));
depthViewMatrix = glm::translate(depthViewMatrix, -15.0f, 30.0f, 0.0f);
glm::mat4 depthMVP = depthProjectionMatrix * depthViewMatrix;// * modelMatrix;
// Multiply it be the bias matrix
glm::mat4 biasMatrix
(
0.5, 0.0, 0.0, 0.0,
0.0, 0.5, 0.0, 0.0,
0.0, 0.0, 0.5, 0.0,
0.5, 0.5, 0.5, 1.0
);
glm::mat4 depthBiasMVP = biasMatrix * depthMVP;
// Create Camera's MVP
VCCamera* currentCamera = VCSceneGraph::Instance->CurrentRenderingCamera;
glm::mat4 ProjectionMatrix = currentCamera->ProjectionMatrix;
glm::mat4 ViewMatrix = currentCamera->ViewMatrix;
glm::mat4 MVP = ProjectionMatrix * ViewMatrix;// * modelMatrix;
// Update uniforms
glUniformMatrix4fv(m_unifMVP, 1, GL_FALSE, &MVP[0][0]);
glUniformMatrix4fv(m_unifDepthMVP, 1, GL_FALSE, &depthBiasMVP[0][0]);
EDIT:
I fixed the problem by making the Shadow texture the same resolution as the window. I cannot however explain WHY this fixes it. If anyone else want to take a crack at it I will accept your answer. The expected output is this:

I should have also noted that full source is available at: GitHub.
I compare your and my shadows and I suggest you tu use sampler2DShadow instead of sampler2D. This sampler is for shadows only and there are some functions for shadow projection (shadow2DProj and more). You can use it like this.
in vec4 colorVarying;
varying vec4 ShadowCoord;
out vec4 color;
uniform sampler2DShadow shadowMap;
float offset_lookup(sampler2DShadow map, vec4 loc, vec2 offset) {
//Texture size (1024 x 1024)
vec2 texmapscale = vec2(1.0/1024.0, 1.0/1024.0);
//Set bias as you need (it corrects shadow acne)
float bias = 0.001;
vec4 result = shadow2DProj(map, vec4(loc.xy + offset * texmapscale * loc.w, loc.z, loc.w));
if (loc.z > result.z + bias) {
return 0.5;
} else {
return 1.0;
}
}
void main() {
float shadowFactor;
shadowFactor = offset_lookup(shadowMap, ShadowCoord, vec2(0, 0));
color = colorVarying * shadowFactor;
}
What is last parameter offset? You can make some shadow blur. 3x3 shadow blur:
//3x3 blur
for (y = -1.5; y <= 1.5; y += 1.0)
for (x = -1.5; x <= 1.5; x += 1.0)
sum += offset_lookup(shadowMap, ShadowCoord, vec2(x, y));
//I am no sure why 16 (insted of 9) but I use this and it works :D
float shadeFactor = sum / 16.0;
Try it, maybe result will be exactly what you expect.
PS: Sorry for my English.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With