Shadow Mapping - aliasing and merging

I’m adding shadows to an OpenGL 2.1 project using the Shadow Mapping method outlined in Paul’s Projects (http://www.paulsprojects.net/tutorials/smt/smt.html).

All well and good, but I have several problems.

Poor aliasing (see below):

Increasing the shadow map size reduces the blockiness (see below), but is there another method?

Multiple light sources and multi-directional light: I can’t work out how to generate and merge multiple textures/frame buffers. Any pointers?

Thanks in advance.

Carl

You can try several methods: PCF, Variance shadow-mapping, cascading shadow-mapping…

But if you keep the pong game, then I advice you to forget about cascading shadow-maps. You can also try to give linear filtering instead of nearest for your texture parameters. Depending on your hardware and driver this might or not do like PCF.

Also, as a side-note you can try to place you light camera as close as possible to the scene.

I’m hoping to keep things simple, for now at least, as I’m still trying to understand the detail of how it’s done.

I’ve tried moving the light closer to the scene but this changes the shadows’ positions and it’s proving difficult to set the lighting frustum.

I’ll try linear filtering and look at the other methods, but may move on and revisit this later.

I’d certainly like to work out how to generate and merge multiple textures/frame buffers, though.

Thanks.

Keep things simple? You wanted shadows. Shadows are never simple in a rasterizer :wink:

A very good NV presentation from GDC08 maybe worth reading for you:
http://developer.download.nvidia.com/presentations/2008/GDC/GDC08_SoftShadowMapping.pdf

Heh, quite, all relative, I suppose. :confused:

I know that each persons/games/programs requirements are different, but I highly recommend moving to Variance Shadow Maps.

You can then use simple blurring to smooth your shadows and gain effective penumbra. It is also possible to eliminate shadow acne with VSM and the only drawback of VSM (light areas near overlapping objects) can easily be overcome.

Indeed, but this is as much a learning exercise as anything else, so all suggestions welcome.

If you want to keep things really simple, and you don’t need self-shadowing (e.g. merely render silouettes to a grayscale texture), then you could do the following:

When rendering to texture…

  1. Render casters as solid polygons.
  2. Render the shadow casters a second time, as wireframe with GL_LINE_SMOOTH enabled. This will give you nicely anti-aliased silouettes.
  3. Optionally, blur the texture (various ways to do this, Google for it).
    You can do all of this with FFP on GL1.2 (though certainly check out GLSL if you want something future-proof, as FFP is becoming obsolete).

And you may also check out the automatic mipmap generation functions: http://www.opengl.org/wiki/Texture#Automatic_mipmap_generation

None of this will work when you require self-shadowing and are rendering to a depth texture. In that case follow the suggestions of the above posts.

Oops! Maybe I should’ve mentioned I’m trying to avoid shaders (at least for this iteration). :stuck_out_tongue:

Sadly, I do need self shading.

Well, what you’re primarily looking at in those pictures is projection aliasing. And that’s a tough nut to crack with shadow mapping.

As suggested, you can apply better filtering and try to blur the jaggies out of it.

But a better first step is to ensure that your shadow map is as tightly fit to the in-eye-frustum shadow receivers in light space as possible (or more generally, the 2D intersection between your light space shadow casters and shadow receivers, in light space). This reduces your shadow texel size, reducing the size of the shadow jaggies. Check out Managing Visibility for Per-Pixel Lighting in GPU Gems 1.

I’d look carefully into how you are computing the light-space bounds of your shadow map and question whether those bounds could be tighter.

Note that if camera animation is a factor (usually is), you have to think about shadow edge crawling artifacts too (if your shadow map res is low, quantizing the shadow origin works pretty well here, but results in larger shadow texels than you’d otherwise get).