   Shadow maps, missing by fractions and desperation
  About time to face the ugly topic of "how best to fake shadows in a completely unsuitable rendering method (rasterizing)". Implementing shadow mapping was quickly done. A little while later it actually worked.But there is one really ugly issue when it comes to self shadowing that I can't find a decent solution for. Getting wrong depth values by slighly missing the right texel at the edge.First reaction: no problem, just fix the texture coords by the usual half pixel. Uhm, slightly better on one side, much worse on the other. Wait, on both side? That wasn't the problem then.As far as I can piece it together I would a partially covered pixel/texel not to have any depth written to (makes sense to some degree, you wouldn't want it to be red if only the tiniest fraction of it was covered by a red polygon). In other words: rasterization will begin at the next pixel instead. But when it's time for the lookup and we end in the same position, we will now read the texel that wasn't written to. I really hope that's wrong and it's just a stupid mistake I can't find.I tried fiddling around in different ways, shifting coordinates here and there, even adjusting the lookup coordinates based on face normal and angle between normal and light (ie. the closer this is getting to 90°, the more I correct the position "inwards", hoping to get the texel with an edge depth value instead of 1). Needless to say that most of these attempts just screwed up the whole depth comparison until it took a drastic bias to work at all.Bias, another issue. Too little poly offset and there a flickering black lines, too much and the nose shadow has a hole in it. I got somewhat decent results fiddling with that in the shader (constant offset and offset based on dot(normal,light)).Anyway, there is now a lame trick in place until I figure out a real solution: abuse the angle between light and normal. Not perfect, not looking very natural, but hiding the artifacts at the silhouette...Using a smaller value softens the edge. Unfortunately this only hides only one half of the jagged shadow effect and fixing the cause instead of symptoms would be better.To play around: TestAppd, h, l are the more important keys in this to show shadow or depth, fully lit or shadow only and turn the ugly hack on or off.   
  Generally, the solution you suggested is the one that's used to "fix" the problem: When N.L is less than zero, make the pixel fully shadowed, regardless of the shadow test.  This makes sense when you think about it - if a face is facing away from the light, the light isn't going to influence its color at all, so it might as well be fully shadowed!The cause of this issue can not easily be fixed, not without some strange geometry manipulation or something to pull the silhouette edges out to give them more texels in the shadow map.   ;Quote:Original post by PfhorSlayerGenerally, the solution you suggested is the one that's used to "fix" the problem: When N.L is less than zero, make the pixel fully shadowed, regardless of the shadow test.That was the idea, though once I stopped looking at the isolated shadow it became almost pointless, as my shadow only removes diffuse and specular. Diffuse is already dark or zero for these cases. Specular was the only reason I saw the difference at all, because the shininess value was screwed up (very close to zero).Quote:The cause of this issue can not easily be fixed, not without some strange geometry manipulation or something to pull the silhouette edges out to give them more texels in the shadow map.Somehow I was afraid of that. No decent on-the-fly solution. Maybe clever filtering of the shadow map. Or I revisit my attempt to nudge the look-up coordinates half a pixel * (1-NL) to the "inside". But that will probably shift too many coordinates not just on but also close to the edge... where z changes rapidly and preventing problems would require so much z-bias that it causes trouble everywhere else. Ah, computer graphics.. a world of compromises.   ;  Using a bias is extremely fragile - there's cases where the bias is too large AND too small for different bits of the same scene, and you get both "surface acne" and the "Peter Pan effect" at the same time.You can usually solve this by making multiple samples into the shadow map and offsetting by a pixel in each direction. Then only shadow the object if all the samples are in shadow. It makes your shadows shrink a little, but the effect is not too noticeable, and it gets rids of the "edge acne".Alternatively (and almost equivalently), you can preprocess your shadowmap to "shrink" the depth values in by a texel by sampling all the depth values in a square of texels (in theory 2x2 should do it, but you might have to use a 3x3), and taking the furthest one. Haven't tried this in practice, but it might be slightly faster than doing multiple samples - not sure.There's some more details in talks I've given, available at http://www.eelpi.gotdns.org/papers/papers.html, specifically the one called "Yet More Shadowbuffers".   ;Quote:Original post by TomForsythUsing a bias is extremely fragile - there's cases where the bias is too large AND too small for different bits of the same scene, and you get both "surface acne" and the "Peter Pan effect" at the same time.I couldn't even get rid of that for the default object (with PolygonOffset). Either wrong shadows or a whole in the nose shadow. Manual fiddling helped, but obviously you can always have geometry that's too "thin" or too close to each other.From the rest it seems I've been going the wrong way, trying to expand instead of shrinking, thinking about using the smallest instead of largest value. I'll have to try it the other way when I come back. Enough time to think about whether this might shift the whole problem "inwards" or fix it (PCF obviously just blurred it, but not nearly enough to hide it).Quote:There's some more details in talks I've given, available at http://www.eelpi.gotdns.org/papers/papers.html, specifically the one called "Yet More Shadowbuffers".Bookmarked. Seems to be quite a few interesting papers to have a look at.   