   [D3D10] Variance Shadow Maps + MSAA, problem with the latter
  Hello,I have been trying to implement (parallel split) variance shadow maps and am quite pleased with the results (only drawback is the lightbleeding). Now I want to try to use multisampling on the shadows but don't know how to do it. I create both the depthstencil and the texture for the shadows with Samples = 4 and Quality = 1. In the shader I use Texture2DMS<float2, 4> instead of Texture2D and this is were the trouble starts. There is no Sample-method for Texture2DMS. Now I can't figure out how this is supposed to work.I know there are many articles about VSM and even some cool demos, but I can't get any source that actually shows me how to use MSAA with it. Does anybody have some experience with this?EDIT: Ah, I believe I found all the answers I need here: http://www.gamedev.net/community/forums/topic.asp?topic_id=449881Another question then:If I have to resolve the multisampled texture into another texture I have twice the memory footprint. There is no other way?[Edited by - B_old on April 26, 2009 9:27:18 AM]
  Yeah you don't want to sample the individual subsamples from your MSAA render target, just let the hardware resolve it for you.  It also won't double your memory footprint, since your non-MSAA render target will be 1/N the size of your MSAA target (where N is the number of subsamples, in your case 4).Also if you're having issues with light-bleeding, you should have a look at this.  The layered stuff is okay, but what's really cool is the bit about using an exponential warp towards the end of the paper.  It does a great job of reducing light bleeding.  I actually have it all implemented for the game I'm working on now, but I can't use it because R32G32F textures are just too damn slow on the 360.   ;  OK, the multi-sampling is working fine now. I wasn't really aware of the fact, that a multi-sampled surface needs that much memory...The original (I believe) VSM-paper states that you don't want to use anti-aliasing with normal shadow maps. Why is that? Or did I misunderstand. Right now it seems to me, that anti-aliasing would benefit every shadow-mapping technique. Maybe I will try it tomorrow and see for my self.Is it hard to implement this exponential warp? (In terms of coding- and performance-costs.) It sounds cool, but the paper did not give much details. There seem to be some papers on exponential shadow maps in general though. Maybe I will find something there.   ;Quote:Original post by B_oldOK, the multi-sampling is working fine now. I wasn't really aware of the fact, that a multi-sampled surface needs that much memory...Yeah the MSAA target has to store all the individual subsamples, so that later they can be resolved (which is usually done by averaging the subsamples with a box filter).  The same goes for an MSAA depthstencil surface, it will be Nx as big as the non MSAA version.  This is actually why MSAA has a performance hit at all, it takes more bandwidth to render write all that memory.Quote:Original post by B_oldThe original (I believe) VSM-paper states that you don't want to use anti-aliasing with normal shadow maps. Why is that? Or did I misunderstand. Right now it seems to me, that anti-aliasing would benefit every shadow-mapping technique. Maybe I will try it tomorrow and see for my self.It's the same reason you can't just do gaussian blur on a shadow map before you do the actual comparison: for shadow mapping you want avg(shadowMapDepth > lightDepth), not avg(shadowMapDepth) > lightDepth.  The former is typically done with PCF, where you do the comparison N times and average the results.  You would be doing the latter with any kind of pre-filtering, which includes a blur across the shadow map or using MSAA.  VSM works with pre-filtering, because you're not just storing depth for a particular texel in the shadow map.  Instead you store the first two moments of a distribution of depths across a texel, and you can actually pre-filter this.Quote:Original post by B_oldIs it hard to implement this exponential warp? (In terms of coding- and performance-costs.) It sounds cool, but the paper did not give much details. There seem to be some papers on exponential shadow maps in general though. Maybe I will find something there.No it's pretty simple to code actually, just a few minor changes to your shader code.  The only issue with it is that you really need 32-bit floating point surfaces for it to work well, so if you were getting away with 16-bit you'd have to double your bandwidth and storage costs (plus don't forget that not all GPU's will filter and MSAA R32G32F).    In fact the ideal variation of EVSM uses 4 components so you'd need R32G32B32A32F...but you can get away without that at the expense of some artifacts.Also don't confuse the technique with Exponential Shadow Maps...that's something different.  This is still VSM's.   ;  That about the filtering makes sense I suppose.I'm already R32G32F using, so that could be ok. I'm a bit reluctant to use a bigger format though, so would like to try it with what I am already using.When I generate the shadow maps, do I compute the exponential warp in the vertex shader and interpolate, or do I compute it in the pixel shader? Do you happen to have a code snippet?Thanks for the help.   ;  You do the warp in the pixel shader.  There's plenty of code snippets and related discussion in this thread, that should help you get started.   ;  Hm, I looked at the discussion and seem to have the same problem as a certain gjaegy who then goes on to explain that he has solved his problem but prefers not to share the solution "order to have some remaining credibility".I use 1.0f for c in exp(c * depth) (Any higher values and my problems get even worse) and the light bleeding is actually gone but I get shadow acne, that does not change how high I set the min variance.I will post some of my code, maybe it is some obvious mistake, but I can't figure it out://Generate the shadow map...float2 pixelShader_dir_vsm(VS_Output_Dir_Vsm input) : SV_Target{float depth = exp(1.0f * input.depth);float2 Moments;   //First moment is the depth itself.  Moments.x = depth;   //Compute partial derivatives of depth.  float dx = ddx(depth);  float dy = ddy(depth);   // Compute second moment over the pixel extents.  Moments.y = depth * depth + 0.25f * (dx * dx + dy * dy);  return Moments;}//Apply the shadow map...float2 shadowProj = pos.xy / pos.w;float2 moments = g_texture0.Sample(g_shadowSamplerVsm, shadowProj).xy;float depth = mul(float4(input.spos.xyz, 1.0f), g_shadowViews[split]).z;depth = exp(1.0f * depth);float shadow = ChebyshevUpperBoundE(moments, depth);//---float ChebyshevUpperBoundE(float2 moments, float t)  {  //One-tailed inequality valid if t > moments.x  float p = (t <= moments.x);//Compute Variancefloat variance = moments.y - (moments.x * moments.x);variance = max(variance, 10.0f);   //The value does not seem to make a differencefloat d = t - moments.x;float p_max = variance / (variance + d * d);//p_max = ReduceLightBleeding(p_max, 0.25f);return max(p, p_max);} It would be cool to get this working, but I don't know what is going on.   ;  OK, I have stepped back from using a linear depth metric and that greatly improved things.I use float depth = exp(16.0f * (input.depth.x / input.depth.y)); now and the light bleeding is considerably less (still there at if you really look for it and I still have to use reduceLightBleeding()) without introducing any new noticeable artifacts.I guess that can be considered a success. I'm still open for any ideas though...   