Shadow Mapping - merging textures

ok, (moving on from my previous post) I’m adding shadows to a OpenGL 2.1 (without shaders) 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, in particular, with multiple light sources and multi-directional light, I can’t work out how generate and merge multiple textures/frame buffers. Any pointers?

Thanks in advance.

Carl

Why are you trying to merge multiple shadow maps?

Having multiple shadow maps works just the same as one. You just do the same thing, multiple times.

I assume you mean an omnidirectional point light source.

Cube shadow maps are often used for these. Check the archives for details and code.

Apologies for the delay, I was ill over Christmas and had limited computer access. Anyway…

I’m trying to simulate multiple light sources.

I was hoping for a bit detail than that. Don’t I need to do some accumulation, at least?

Yes, I probably do. Not 100% on the terminology.

I’ll look into that. Thanks.

Carl

What Alfonse means is that you should loop through the light sources in your GLSL shader when drawing the shadow receiver. Compute the lighting (N dot L etc) and sample the per-light source shadow depth map.
Each light source contribution (including shadowing) should be computed independent of another. You can’t merge depth textures like you can combine baked lightmaps or non-depth shadow mapping because the shadow sampling depends on the projection of each light source. If the projection differs, there’s no way to merge them in any meaningful way (there is also deferred shading/forward rendering, but not sure this is what you’re after).

As for omni-directional shadow maps, I believe depth-shadow cubemaps are more widely supported now. You might also want to check out ‘dual paraboloid shadow mapping’.

I was hoping for a bit detail than that. Don’t I need to do some accumulation, at least?

Use additive blending between each light pass. For example, this pseudo-code does this:


glEnable (GL_BLEND);
glBlendFunc (GL_ONE, GL_ONE);

for_each (light){
   // render the scene using the light 'light' and the shadow-map 'light->shadow_map'
   render_scene (light, light->shadow_map);
}

glDisable (GL_BLEND);

This works whether you use shaders or not, and you can also use more than 8 lights, with a little trick with the light (ie always use GL_LIGHT0).

OK, after Christmas and a bout of ‘flu’ I’ve finally been able to take a crack at this.

So far, I’ve added:
2 shadow map textures
2 lightpositions
2 light view matrices
but I can’t get them to blend correctly.

I’ve split the process into 3 functions:
1st pass - Draw from light’s point of view into shadow map texture
2nd pass - Draw from camera’s point of view with a dim light
3rd pass - Draw with bright light applying shadow calculations

And, I’ve wrapped
glEnable (GL_BLEND);
glBlendFunc (GL_ONE, GL_ONE);
:
glDisable (GL_BLEND);
around various call combinations.

The best result is shown below (I’ve edited the screen grab to make the shadows darker, they’re almost too light to see otherwise) when I wrap the 3rd pass. Only one set of shadows is visible, except the small dark patch to the right where they overlap. So I’m guessing that I’m at least “facing in the right direction”…?

Pseudo code is something like this:

  Draw from light1's point of view into shadow_map_texture1 using light_view_matrix1
  Draw from light2's point of view into shadow_map_texture2 using light_view_matrix2

  Draw from camera's point of view with a dim light at lightpos1
  Draw from camera's point of view with a dim light at lightpos2

  glEnable (GL_BLEND);
  glBlendFunc (GL_ONE, GL_ONE);
    Draw with bright light applying shadow calculations (shadow_map_texture1)
    Draw with bright light applying shadow calculations (shadow_map_texture2)
  glDisable (GL_BLEND);

Should the shadow map textures be blended? Should the results of the third pass be blended?

Probably all a bit too vague, but any help would be most appreciated.

Regards,

Carl

I’ve been playing around with this. Won’t each blend pass make the resulting image lighter? (This is what my experimentation points to.) Or am I missing something?

I’ve been playing around with this. Won’t each blend pass make the resulting image lighter? (This is what my experimentation points to.) Or am I missing something?

No. Only where lights overlap will the image become brighter.
Saturation can occur but that why tone mapping exists.

Am I right in thinking that ambient lighting will be summed each pass and so should only be rendered once?

Are you using fixed function lighting? If you are you are on a hiding to nothing. The lighting model is really hanicapped at best. In real life there is only 1 ‘global ambient’ that we detect in a typical situation, so in your rendering you should try and simplify things to achieve that too. Each glLight has it’s own ambient term, so it’s really up to you how you want to combine these. If the ambient terms are set and you are using fixed function, then yes ambient is included along with diffuse and specular. You define the contributions of these with the various light parameters - so set them to black if you don’t want them on the other lights.

Yes, I am using fixed function lighting.

Still, I seem to have it working now, although admittedly I’m not quite sure why.

Ta da!

There was an errant glDisable(GL_LIGHTING), which certainly didn’t help. :frowning:

And, during the final pass I set ambient to black. Further experimentation points to the green channel saturating. :confused:

I’m just glad to have it working, I nerd-sniped myself with this little beauty several months ago. Now I can get back to some “real” work. :smiley:

Many thanks to all who provided help, pointers and suggestions.

FYI Two other snafu’s…
Materials were ambient rather than diffuse so the render was overly bright.
I was clearing the depth buffer before it was enabled leading to pixel artifacts and apparent z-fighting. D’oh.