Jump to content
  • Advertisement
Sign in to follow this  
sorairo2

Shadow mapping artifacts

This topic is 4872 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi there - I've implemented shadow mapping using the method in Game Programming Gems 1 and am having a problem with the texture tiling. I generate texture coordinates myself (by choice) and for the most part, the shadow projects nicely (I'd love to make them perspective correct but have no clue how). I'm having a problem with texture tiling artifacts. They appear to come up where the generated texture coordinates go from positive to negative and vice versa. This must be a common problem with texture coordinate generation, so I was hoping someone knew of a solution or could point me to a thread covering this issue. I've read many places to set the coordinates to (-1, -1) if the point lies behind the light, or if the receiving face is back-facing, etc., etc.. but they never talk about the fact that by doing so, you're going to be moving from positive to negative coordinates at some point, causing the visible shadow texture to draw. Here's a screenshot of 2 artifacts: 1) Shadow lines on the ground caused by small tiling going from positive to negative coordinates. 2) Shadow projected behind the light. Image hosted by Photobucket.com

Share this post


Link to post
Share on other sites
Advertisement
The shadow being projected behind the light is an unfortunate side effect of the standard technique (which is basically a dynamic projected texture). You could fix it by using something like depth shadow maps to prevent geometry behind the shadow-caster being shadowed, or you could try to avoid rendering things behind the light for your shadow pass.

Share this post


Link to post
Share on other sites
One thing you could try is enclosing the shadowcaster inside a frustum/cone/pyramid with the point being at the light's position, and when rendering the scene, mask part of the image by rendering the shape with the stencil buffer set a certain way (like a shadow volume), then invert the mask and render the object and scene while adding the results. Sorry if that isn't very clear, but if I had more experience with stencil buffers it would be.

Alternatively, you could just spit out a shadow result of 1 behind the light.

Share this post


Link to post
Share on other sites
The most general solution, as superpig suggests, is to introduce depth into the shadow calculation.

The easiest solution is simply to make a 2x1 texture with white in the left texel and black in the right one. Map your light space Z direction to this texture coordinate, and add the value from the texture to your existing texture map. This way anything behind the light won't receive a shadow.

Bonus points if you move the clamping texture coordinates to just before the caster's bounding sphere in light space.

You will still have artifacts if there is an object really close to the caster, but there's no solution to that other than using depth or id-based shadows.

Share this post


Link to post
Share on other sites
Wouldn't simply clamping the texture Q coordinate to [0,1] in the pixel shader be sufficient? AFAIK, all hardware that supports the OGL shadow mapping extension also has pixel shader support.

Share this post


Link to post
Share on other sites
Thanks for the helpful replies! I've tried a few techniques since then, based on what many of you have recommended, but if it's not one artifact, it's another.

Clipping negative W values has eliminated full shadows behind the light, but it also causes transitions from positive to negative shadow texture coordinates to occur in different areas.

A few questions:

- What is depth or ID-based shadow mapping? I've seen it mentioned elsewhere too but I can't find any info on it.

- Would using the 2-texel shadow mask be the equivalent to modulating with the vertex diffuse alpha yield the same effect? I've done the latter so that textures behind the light are faded out. This works fine except where a triangle moves from positive to negative space, in which case the shadow artifact gradually fades out as it reaches behind the light. I'm guessing I'd get a very similar effect with a 2 texel shadow mask, except that the transition would be more abrupt... which can be good in some cases and bad in others.


Note that I'm deliberately limiting myself to the DX7-era mainstream hardware (and pre-era in some cases). I'm also keeping stencil buffers out of the equation to ensure maximum compatibility and performance with older hardware, hence the choice for shadow mapping instead of volumetric shadows. I'm surprised that the former is so much more complicated.

Thanks!

Share this post


Link to post
Share on other sites
Quote:
Original post by sorairo2
I'm also keeping stencil buffers out of the equation to ensure maximum compatibility and performance with older hardware, hence the choice for shadow mapping instead of volumetric shadows.


Odd, since hardware stencil buffers are far more widely supported than per pixel depth compares.

Unless, of course, you are not actually doing shadow maps but instead texture shadows.

Share this post


Link to post
Share on other sites
Quote:
Original post by sorairo2
Thanks for the helpful replies! I've tried a few techniques since then, based on what many of you have recommended, but if it's not one artifact, it's another.

Clipping negative W values has eliminated full shadows behind the light, but it also causes transitions from positive to negative shadow texture coordinates to occur in different areas.

A few questions:

- What is depth or ID-based shadow mapping? I've seen it mentioned elsewhere too but I can't find any info on it.

Depth shadows are real shadow maps. They can be implemented in several ways, from hw z buffer shadow maps, to alpha test or pixel shader shadow maps.
I am using alpha-test based depth shadows, which work on dx6 hw and above.

ID-based shadows work by drawing each object with a different color in the shadow map, and then for each shadow receiver, check if its color is in the shadow map at that pixel or not. These don't have problems with limited depth range, but they are bad for small objects.

These can be implemented with alpha test as well, again on older hw.

Quote:

- Would using the 2-texel shadow mask be the equivalent to modulating with the vertex diffuse alpha yield the same effect? I've done the latter so that textures behind the light are faded out. This works fine except where a triangle moves from positive to negative space, in which case the shadow artifact gradually fades out as it reaches behind the light. I'm guessing I'd get a very similar effect with a 2 texel shadow mask, except that the transition would be more abrupt... which can be good in some cases and bad in others.


As you say, vertex attributes do not clamp properly, so a texture or shader approach is preferred when it really is a sharp transition. Clearly an object can't shadow something on the other side of light that it is on, so a sharp transition is required. You can use bilinear filtering to soften the transition slightly, but point sampling should work fine as well.

Quote:


Note that I'm deliberately limiting myself to the DX7-era mainstream hardware (and pre-era in some cases). I'm also keeping stencil buffers out of the equation to ensure maximum compatibility and performance with older hardware, hence the choice for shadow mapping instead of volumetric shadows. I'm surprised that the former is so much more complicated.

Thanks!


Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!