PDA

View Full Version : basic shadow mapping - removing artifacts



Triangle
11-06-2012, 09:50 AM
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 (http://imageshack.us/a/img689/7224/shadowaic.jpg)

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 (http://imageshack.us/a/img513/6603/shadowbq.jpg)
and in the light:
Image3 (http://imageshack.us/a/img37/3116/shadowci.jpg)

I read (http://hacksoflife.blogspot.com/2009/01/polygon-offset-and-shadow-mapping.html) 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. ?

Kopelrativ
11-07-2012, 02:14 AM
1. Is it possible to calculate a dynamic bias in the shader which gives better results than glPolygonOffset ? (How to do it ? )
In general, see many good ideas at http://www.opengl-tutorial.org/intermediate-tutorials/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 http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-16-shadow-mapping/#Shadow_acne for more details.


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. ?

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.

Triangle
11-07-2012, 09:35 AM
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.

Dark Photon
11-07-2012, 03:14 PM
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).

Triangle
11-20-2012, 06:14 AM
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 (http://imageshack.us/a/img255/3769/shadownb.jpg). The amount of artifacts in the light is similar screen2 (http://imageshack.us/a/img194/5376/shadownf.jpg), 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 ?