basic shadow mapping - removing artifacts

I implemented a basic shadow mapping. I have a scene illuminated by one directional light.
I use an orthographic projection:


(glm::ortho(-70.0f, 70.0f, -50.0f, 90.0f, -50.0f, 100.0f));

which is sufficient to cover the scene from the light point of view. LightViewMatrix looks like this:


glm::lookAt(glm::normalize(glm::vec3(0.0f, 1.0f, 1.0f)), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));

Here are parameters for a depth texture:


glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 1024, 1024, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
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_MODE, GL_COMPARE_REF_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); 

In a shader I use sampler2Dshadow so I get a basic PCF filter.

I removed an ambient light and artifacts are more visible. First I used front face culling during saving depth values. That removed artifacts
from the illuminated part of the object, but then I got many artifacts in the shadow.
Image1

Next I set glPolygonOffset(4.0f, 20.0f) during saving depth values instead of the front
face culling and I got better results but some artifacts were still visible in the shadow:
Image2
and in the light:
Image3

I read that glPolygonOffset gives better results than using a constant bias in the shader because
it takes into account a polygon slope.

  1. Is it possible to calculate a dynamic bias in the shader which gives better results than glPolygonOffset ? (How to do it ? )
  2. Is something what I can do better to remove artifacts using only the basic shadow mapping concept or the only way is using more advanced techniques such as cascaded shadow mapping etc. ?

[QUOTE=Triangle;1244238]

  1. Is it possible to calculate a dynamic bias in the shader which gives better results than glPolygonOffset ? (How to do it ? )[/QUOTE]
    In general, see many good ideas at Tutorial 16 : Shadow mapping.
    Specifically, yes, there are ways to get a dynamic bias. In principle, you want a small bias for surfaces that have normals pointing to the light source, and bigger bias for surfaces that have normals pointing 90 degrees away from the light source.
    The link above proposes a bias computed as:
float bias = 0.005*tan(acos(cosTheta)); // cosTheta is dot( n,l ), clamped between 0 and 1
bias = clamp(bias, 0,0.01);

This is a solution I use, and I think it is quite good. See Tutorial 16 : Shadow mapping for more details.

  1. Is something what I can do better to remove artifacts using only the basic shadow mapping concept or the only way is using more advanced techniques such as cascaded shadow mapping etc. ?

There is no simple answer to this, it depends on your application and your requirements. But you will find several good proposals at the site I referenced to.

Please give feedback of your findings, I am interested myself.

Thanks for tips. I tried a dynamic bias mentioned above but generally I got a bit worse effect than when using glPolygonOffset. Artifacts in the light were more visible. In the shadow some very small artifacts became less visible, but I got a bigger artifact in the other place of the object. Experimenting with glPolygonOffset seems to be the best solution in this case.

Some more advanced techniques for reducing a shadow edge aliasing might help to hide artifacts. I also think that cascaded shadow mapping might be a good solution for a directional light.

If your scene doesn’t have a large depth range (the example you have above doesn’t), it’s not going to help. That’s the whole point of Cascaded Shadow Mapping (aka Parallel-split Shadow Mapping).

I made one more test. I changed an orthographic projection to

glm::ortho(-10.0f, 10.0f, 20.0f, 40.0f, 10.0f, 50.0f)

Now it contains only the object and a small area of the ground plane, not the whole ground plane and the object. I also modified glPolygonOffset for the new projection (glPolygonOffset(2.5f, 10.0f)). That removed almost all artifacts in the shadow screen1. The amount of artifacts in the light is similar screen2, moreover shadow edges looks much better, so maybe CSM is a good solution even for that scene and a directional light source.

But if not CSM what else can help ?