Omnidirectional shadow mapping

Started by
8 comments, last by Pilpel 8 years, 3 months ago

This GPU Gems article about this technique suggests to use a single cubemap texture for all light sources.

We use a single shadow map for all light sources, creating an image with multipass rendering and performing one pass for each light source.

Can anyone explain that? In my head it's only possible to have a single cubemap for every light source in the scene.

How can I render the depth of all light sources to one cubemap?

Advertisement

The key is the latter half of the sentence " multipass rendering and performing one pass for each light source". Rendering each light is a separate pass, you iterate thorugh the list of lights and do the following:
- Clear the shadow map
- Render the shadow map for the current light
- Render your scene with the current light and the rendered shadowmap (Or if you do deferred rendering, that just calculate lighting for the current light using the gbuffer)
- Additive blend it into an accumulation buffer

- Do this for every light you have

It's good because it doesn't use much memory, the disadvantage is it eats fillrate for breakfast even if you do some kind of clever stencil + light bounding volume based optimization.

It's good because it doesn't use much memory, the disadvantage is it eats fillrate for breakfast even if you do some kind of clever stencil + light bounding volume based optimization.

Another disadvantage is that involves a lot of SetRenderTarget calls which are relatively expensive CPU side. (Normally for N lights you would need N+1 SetRenderTarget calls; but with this method you need N*2 calls. Though you can amortize if you work on 2 cubemaps at once)

- Additive blend it into an accumulation buffer

What do you mean? I thought accumulation buffers are deprecated wacko.png

Also, can you explain the next sentence from the article?

To reduce overdraw and improve performance, we render a depth-only pass first. This standard technique ensures that all subsequent lighting passes occur only on visible pixels.

Does this refer to the shadow-map pass or the main pass?


What do you mean? I thought accumulation buffers are deprecated

It's just a simple color render target, nothing fancy about it, you just blend each lighting passes result into it. (You accumulate lighting results into it, thats why I called it a accumulation buffer.) You don't even need a separate render target for this, you could blend each passes result into the main backbuffer if it's setup right. (I wouldn't recommend it, but it's certainly doable.)


Also, can you explain the next sentence from the article?
Quote
To reduce overdraw and improve performance, we render a depth-only pass first. This standard technique ensures that all subsequent lighting passes occur only on visible pixels.
Does this refer to the shadow-map pass or the main pass?


It refers to the main pass, they basicly render the whole frame with color writes turned off and with the pixel shader set to null, before any lighting is calculated. After this the depth buffer is filled with the scene's "final" depth values, so when later you're rendering your scene, the GPU can reject pixels before the pixel shading pass whose depth value would be bigger than what's in the depth buffer. (Given that it's guaranteed that you won't be tampering with the depth value in the pixel shader, which you can do, but usually is a bad idea.) Because you basicly render the scene twice, it adds overhead quite obviously, and this overhead can be bigger than the gain from not shading and outputing occluded pixels. If you leave out the mentioned prepass, order your objects that you want to render front-to-back, and render them in that order, you can have similar gains, but without rendering everything twice. It's important to mention that all of this only works for opaque objects, handling transparent object are a whole new level of pain.

If all this is still confusing, you can download the contents of the CD that was given with GPU Gems from here: ftp://download.nvidia.com/developer/GPU_Gems/CD_Image/Index.html
It looks like this chapter of the book had sample code, seeing that would probably make it easier to understand what they were doing.

The omnidirectional part has no source code. sad.png

I'm having a hard time finding a good article on this. It makes me wonder, is this the "standard" method for doing point light shadowing?

How else would you approach it ? The lack of source code / articles on the subject does NOT imply that is non standard. There is no magical way to render to a cubemap, hence why most articles will just leave it at that.

The omnidirectional part has no source code. sad.png

I'm having a hard time finding a good article on this. It makes me wonder, is this the "standard" method for doing point light shadowing?

There is multiple ways to do point light shadow maps (dual paraboloid shadow mapping, using simple cubemaps, using a simple 2d texture instead of a cubemap and treating it's sections like the faces of a cubemap, etc. there's probably a bunch more), one of the simplest way is using a cubemap and just render the scene depth into it from the light's position. Rendering a shadow map is really similar to rendering an environment map, but instead of the color, you store the depth in some way. Sampling it during shading is again really similar to what you do with environment maps, you just sample the cubemap with the vector pointing from the light's coordinate to the shaded points coordinate. From this point it's classic shadow mapping, you do the same thing you would do if you had a spotlight instead of a point light. The first step is to implement this with one point light, if you have this, then you can think about how to extend it to handle multiple lights, and how to optimize that case.

If you can do spot light shadow mapping doing this for point light should not be a problem. Have you tried spot lights first?

If you can do spot light shadow mapping doing this for point light should not be a problem. Have you tried spot lights first?

Spot light shadow mapping is just one direction - there's no need in a cubemap. How is this similar?

I've tried regular shadow mapping, not spotlight, to be honest... Did I miss something?

This topic is closed to new replies.

Advertisement