i have a strange problem with shadow acne. It occurs when the light direction is parallel to a plane. Here is my code and a few images of the problem:
//this calculates the shadow matrix
//########## 1st phase ##########
float rangeX = globalData::windowWidth;
float rangeY = globalData::windowHeight;
m_ProjectionMatrix = glm::ortho<float>(-rangeX,rangeX,-rangeY,rangeY, 0.1f,(float)globalData::zFar); // zfar is 500.0f here
m_viewProjection = glm::lookAt(
glm::vec3(lightPosition.x,lightPosition.y,lightPosition.z),
glm::vec3(
((lightDirection.x==lightPosition.x) ? lightDirection.x+0.1f : lightDirection.x),
((lightDirection.y==lightPosition.y) ? lightDirection.y+0.1f : lightDirection.y),
((lightDirection.z==lightPosition.z) ? lightDirection.z+0.1f : lightDirection.z)
),
glm::vec3(0,1,0)
);
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 depthModelMatrix = glm::mat4(1.0);
//this is used in the 2 phase, when i render the world objects
mDepthBiasMVP = biasMatrix * m_ProjectionMatrix * m_viewProjection * depthModelMatrix;
//Now for each object in the "world", i use another function like this:
glm::mat4 depthMVP = m_ProjectionMatrix * m_viewProjection * objectModelMatrix;
shader.sendUniform4x4("depthMVP", &depthMVP);
//########## 2nd pahase ##########
//for each object in the world, i send this uniform
shader.sendUniform4x4("DepthBiasMVP", mDepthBiasMVP);
//in the shader i use this function to get the shadow "visibility"
float getVisibility(sampler2D shadowMap, vec4 vShadowCoord, float windowWidth, float windowHeight)
{
float visibility = 1.0;
float bias = 0.0001;
float highResolutionShadowNearDistance = 20.0f;
int PCF = 0;
int blurRange = 1;
float shadowFactor = 0.01;
vec2 texelSize = 1.0 / textureSize(shadowMap, 0);
for(int x = -blurRange; x <= blurRange; ++x)
{
for(int y = -blurRange; y <= blurRange; ++y)
{
int index = (PCF==1) ? int(4.0*random(floor(vWorldPos.xyz*100.0), y))%4 : y%16;
vec4 vShadowSmooth = vec4(vShadowCoord.x + poissonDisk[index].x/windowWidth, vShadowCoord.y + poissonDisk[index].y/windowHeight, (vShadowCoord.z-bias)/vShadowCoord.w, 1.0);
float pcfDepth = texture(shadowMap, vShadowSmooth.xy + vec2(x, y) * texelSize).r;
visibility += vShadowSmooth.z - bias > pcfDepth ? -shadowFactor : shadowFactor;
}
}
return visibility;
}
and the results are here:
the problems are marked with a red circle. Thanks a lot!
EDIT: this is the result of Peethor suggestion (maybe i havent implemented it well, please help :) ):
and this is de modified shader function:
float getVisibility(sampler2D shadowMap, vec4 vShadowCoord, float windowWidth, float windowHeight, camera _camera, vec3 vNormal)
{
float visibility = 1.0;
float bias = 0.0001;
float highResolutionShadowNearDistance = 20.0f;
int PCF = 0;
int blurRange = 2;
float shadowFactor = 0.01;
vec2 texelSize = 1.0 / textureSize(shadowMap, 0);
for(int x = -blurRange; x <= blurRange; ++x)
{
for(int y = -blurRange; y <= blurRange; ++y)
{
int index = (PCF==1) ? int(4.0*random(floor(vWorldPos.xyz*100.0), y))%4 : y%4;
vec4 vShadowSmooth = vec4(vShadowCoord.x + poissonDisk[index].x/windowWidth, vShadowCoord.y + poissonDisk[index].y/windowHeight, (vShadowCoord.z-bias)/vShadowCoord.w, 1.0);
float pcfDepth = texture(shadowMap, vShadowSmooth.xy + vec2(x, y) * texelSize).r;
visibility += vShadowSmooth.z - bias > pcfDepth ? -shadowFactor : 0.001;
}
}
// vNormal is a vertex normal and _camera.direction is the current light direction
float parallelLightFactor = dot(vNormal, _camera.direction);
visibility *= parallelLightFactor;
return visibility;
}