Sign in to follow this  
marco1475

Summed Area Variance Shadow Maps

Recommended Posts

Hi! I got my implementation of variance shadow maps (VSM) done on DirectX 9 (see this thread) and as next step I'd like to improve on the blurring by using summed area tables. I read the GPU Gems 3 chapter, looked at the provided code (which is btw. extremely obfuscated and unfortunately in DirectX 10) and started snooping around how to generate the SATs on the GPU and how blur them. However, my first tries weren't that successful - I think I got the shaders down, but as usual they don't do what I want :) What is the high level of operations here? 1. Generate variance shadow map. 2. Pass it as a texture to a GenerateSAT shader that creates a new texture filled with sums (what format in Direct X is best suited for it?). 3. Pass the sum texture and the original variance shadow map to a SATBlur shader that blur whatever is in the shadow map according to the sum texture? Am I missing something, not understanding something correctly? (Sorry for being kind of cross-forum-like, asking about high level theory and then throwing in some Direct X specific questions ...) Thanks for any help.

Share this post


Link to post
Share on other sites
Quote:
Original post by marco1475
I read the GPU Gems 3 chapter, looked at the provided code (which is btw. extremely obfuscated and unfortunately in DirectX 10)

Sorry ;), but I blame a lot of that on the absolute inadequacy of HLSL/Fx to provide a sufficiently flexible dynamic code generation framework for connecting and combining different shader kernels. Usually I'd use RapidMind or something custom for that sort of thing, but I didn't want to "obfuscate" the code even more with external library dependencies ;) To be fair, the DX10 implementation is significantly cleaner than the hoops that DX9 makes you jump through!

Quote:
Original post by marco1475
2. Pass it as a texture to a GenerateSAT shader that creates a new texture filled with sums (what format in Direct X is best suited for it?).

Note that the SAT generation step is separable, so you'll do it in vertical and horizontal pass, each of which will generally be done about log(n) times. It is a direct implementation of Horn's algorithm for generating SAT's (see one explanation here). If you want to be even more efficient, you can implement Lefohn's hybrid scan algorithm, although with some more implementation effort.

Regarding formats this is discussed in the Gems 3 chapter. Namely, INT32 is your best bet, but if you're not on DX10, you'll have to settle for FP32 and try to avoid the numeric problems. Again, this is discussed in the chapter so I'll point you to that for more info.

Quote:
Original post by marco1475
3. Pass the sum texture and the original variance shadow map to a SATBlur shader that blur whatever is in the shadow map according to the sum texture?

No! There's no "blurring the SAT" at all. All blurring does with a regular VSM is effectively clamp the minimum filter width (box blur that is). This can be implemented directly in the sampling shader with SATs... simply enforce a minimum filter size.

Quote:
Original post by marco1475
Am I missing something, not understanding something correctly? (Sorry for being kind of cross-forum-like, asking about high level theory and then throwing in some Direct X specific questions ...)

Yes indeed I'm not sure you're understanding how SATs work. The point is that they allow you to compute sums/averages over arbitrary rectangular regions of the shadow map in O(1) time. Thus there's no need to pre-blur the shadow map, and they entirely replace hardware texture filtering, so there is no need for that either. All of the filter logic is done in the sampling shader, as you can note from the Gems 3 source code.

Share this post


Link to post
Share on other sites
Thank you very much for replying :)

Quote:
Original post by AndyTX
Quote:
Original post by marco1475
Am I missing something, not understanding something correctly? (Sorry for being kind of cross-forum-like, asking about high level theory and then throwing in some Direct X specific questions ...)

Yes indeed I'm not sure you're understanding how SATs work. The point is that they allow you to compute sums/averages over arbitrary rectangular regions of the shadow map in O(1) time. Thus there's no need to pre-blur the shadow map, and they entirely replace hardware texture filtering, so there is no need for that either. All of the filter logic is done in the sampling shader, as you can note from the Gems 3 source code.


Ok, so what you are saying is that I:

1. Create the variance shadow map as usual.
2. Based on said shadow map generate a SAT texture in two passes (horizontal and vertical).
3. When rendering sample the SAT texture which returns the average value of the shadow map for a particular pixel, i.e. the averaged moments.
4. Use these moments to compute the shadow in the scene.

So in other words the scene shader is interested only in the SAT texture and does not need the shadow map anymore, correct?

Thanks again for helping me understand.

Share this post


Link to post
Share on other sites
Quote:
Original post by AndyTX
Sorry ;), but I blame a lot of that on the absolute inadequacy of HLSL/Fx to provide a sufficiently flexible dynamic code generation framework for connecting and combining different shader kernels. Usually I'd use RapidMind or something custom for that sort of thing, but I didn't want to "obfuscate" the code even more with external library dependencies ;) To be fair, the DX10 implementation is significantly cleaner than the hoops that DX9 makes you jump through!


YOU are Andrew Lauritzen?
Oh my, I had no idea! Your article was one of the main reasons why I bought GPU Gems 3! Great job!
(Sorry about the off-topicness)


Share this post


Link to post
Share on other sites
Quote:
Original post by marco1475
3. When rendering sample the SAT texture which returns the average value of the shadow map for a particular pixel, i.e. the averaged moments.

Yes but to "sample" a SAT texture you query the four corners of the filter region that you are interested in and do some basic math (see the Gems 3 chapter). This in turn gets you the average value over that whole region in the shadow map.

Quote:
Original post by marco1475
So in other words the scene shader is interested only in the SAT texture and does not need the shadow map anymore, correct?

That's correct. Once you have generated the SAT you don't need the original texture anymore... indeed you could reconstruct it from the SAT if you were so inclined, but there's generally no need.

Quote:
Original post by Harry Hunt
Oh my, I had no idea! Your article was one of the main reasons why I bought GPU Gems 3! Great job!

Cool, well I hope it lived up to your expectations :) I thought it came out pretty well and have received some positive feedback, but it's nice to hear that people are interested in reading it.

Share this post


Link to post
Share on other sites
One more question :)

Quote:
Original post by marco1475
2. Based on said shadow map generate a SAT texture in two passes (horizontal and vertical).


How exactly do I accomplish these two passes? Is it one pass (horizontal) over the original shadow map and then the second pass (vertical) over the new, horizontally-filtered texture? Or is it supposed to be one pass (horizontal) over the original texture, the second pass (vertical) over the original texture as well, and then combine the two textures? (If so, how do I combine two textures?)

Thanks.

Share this post


Link to post
Share on other sites
Quote:
Original post by marco1475
Is it one pass (horizontal) over the original shadow map and then the second pass (vertical) over the new, horizontally-filtered texture?

Yes - the point is that the generation step is separable in dimension (like blurring for instance). Seriously on this one just check out the referenced paper on how to generate SATs or just rip out the code from the demo.

Share this post


Link to post
Share on other sites
Quote:
Original post by AndyTXYes - the point is that the generation step is separable in dimension (like blurring for instance). Seriously on this one just check out the referenced paper on how to generate SATs or just rip out the code from the demo.


Thanks. I did look at the paper, but wasn't sure about the generation on the GPU. Unfortunately there were no shaders back in 1987 :) Anyway, that was the way I understood and implemented it, however, it still doesn't work so I wanted to make sure. I guess the problem lies somewhere else.

Thanks for now, I'm gonna spend some quality time debugging my shaders to see where it goes wrong.

Share this post


Link to post
Share on other sites
Quote:
Original post by marco1475
Thanks. I did look at the paper, but wasn't sure about the generation on the GPU. Unfortunately there were no shaders back in 1987 :)

Fair enough :) Granted I did skim over that part, but the expectation was that people would check the references for the details on that algorithm.

Quote:
Original post by marco1475
Thanks for now, I'm gonna spend some quality time debugging my shaders to see where it goes wrong.

No problem; good luck with your debugging!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this