Sign in to follow this  
jacko13

VSM and bilinear filtering shader for ATI Radeon

Recommended Posts

Hi, I'm trying to implement VSM and I have one problem. My Radeon doesn't support bilinear filtering with floating point textures and I don't know how is the best method for solve them. I found this bilinear shader: http://www.ozone3d.net/tutorials/glsl_texturing_p02.php But on edges I have "lines" artifacts. Second problem is performance of it. Currently I use this bilinear function in blur horizontal and vertical (in each sample, so I use it 7+7 times, I use 7x7 gaussian blur) and I also use this when I get moments from floating point texture in shading shader. How can I optimize it and solve bilinear shader artifacts? Meybe You know better filtering shader for it or better solution for apply it (less than 7+7+1). Thanks,

Share this post


Link to post
Share on other sites
AFAIC your problem is that:
You're performing no hardware filtering and doing in shader "software" bilinear filtering of variance shadow map.
The main problem is that you don't need this - just turn on linear filtering while creating texture/renderbuffer on hardware (in OpenGL use GL_LINEAR as min and mag texture filter).
Then you won't need to filter offset values to get smooth blur, but you would need just to blur the image - you can do it with separable gaussian blur (which is the best solution).

Share this post


Link to post
Share on other sites
Quote:
Original post by jacko13
My Radeon doesn't support bilinear filtering with floating point textures and I don't know how is the best method for solve them. [...]

That is why he is doing software filtering in the first place, isn't it?


Share this post


Link to post
Share on other sites
Oh ... i missed that, I appologize ...

Anyway less than 7 + 7 samples is impossible, this is minimum for separable gaussian blur.
Although it is possible to filter VSM with Summed area tables - http://http.developer.nvidia.com/GPUGems3/gpugems3_ch08.html, but I really don't know how this will behave on GPU that is not able to do hardware bilinear filtering on fp textures.

Share this post


Link to post
Share on other sites
Quote:
Original post by Vilem Otte
Anyway less than 7 + 7 samples is impossible, this is minimum for separable gaussian blur.

There's no minimum size for separable Gaussian filter. A 5+5 works fine, for example. You just have to use more passes if you want an equally blurry result. Even a 3+3 is possible, but will have minimal effect, especially without leveraging hardware filtering on subtexel positions.

Also, keep in mind that a good VSM implementation(*) will profit much more from anti-aliasing of the shadowmap geometry, rather than from excessive blurring. If you blur too much, you'll lose a ton of detail, but you will always keep some flickering if you don't FSAA during the rendering pass. The other way round works much better: good FSAA and not too much blur.

Then again, FSAA'ing an FP render target will not work on hardware that doesn't even support bilinear filtering of FP textures. Maybe one should ask oneself if it makes sense to implement an advanced showing technique, which is clearly targeted at highend cards, on a low end GPU.

[offtopic]
(*) There is no such thing as 'good' VSM at this time. The technique is very interesting, but much more research is needed to really make it practicable. Plain VSM is unusable due to the extreme amounts of light bleeding it generates on overlapping geometry. All the papers that say that bleeding is 'acceptable' and 'easy to hide' lie. Simple as that. You might want to look into ESM (a bit better, but not top either), convolution shadowmaps (much better, but much more performance and memory hungry). Or something really nice, but from a completely different corner of maths, realtime stochastic refinement shadow maps. They have the best quality of all, but they're not easy to implement. To be entirely honest, you can get much better results (in terms of quality) by using traditional shadowmapping over a PSSM with 5 or 6 sections and 2k maps, than with any of the currently existing filterable solutions (except for convolution maps).
[/offtopic]

Share this post


Link to post
Share on other sites
Quote:
Original post by Yann L
[offtopic]
(*) There is no such thing as 'good' VSM at this time. The technique is very interesting, but much more research is needed to really make it practicable. Plain VSM is unusable due to the extreme amounts of light bleeding it generates on overlapping geometry. All the papers that say that bleeding is 'acceptable' and 'easy to hide' lie. Simple as that. You might want to look into ESM (a bit better, but not top either), convolution shadowmaps (much better, but much more performance and memory hungry). Or something really nice, but from a completely different corner of maths, realtime stochastic refinement shadow maps. They have the best quality of all, but they're not easy to implement. To be entirely honest, you can get much better results (in terms of quality) by using traditional shadowmapping over a PSSM with 5 or 6 sections and 2k maps, than with any of the currently existing filterable solutions (except for convolution maps).
[/offtopic]

That are some interesting thoughts about VSM. Here is my experience:
It is a really good idea to use EVSM (using exp(c * depth)) if you are going to use VSM. It is very easy to change your working VSM implementation and the lightbleeding is noticeably better without a big performance hit. Unfortunately the lightbleeding is still there, which might be a problem depending on your scene. Personally I am still sticking with VSMs for now, mainly because shadow-acne annoys me even more than lightbleeding in my scene. I have to admit though, that I spent more time tweaking my VSM than trying to minimize shadow-acne, which might be a mistake.
Blurring is not so bad. I sample the moments 5 times and use the average directly before I calculate the shadow-occlusion (no separate blurring). That is a definite visual improvement and considerably faster/ than FSAA on my system. It takes less memory, too. How do you solve the flickering problem with "standard" shadow mapping?

Are there any code samples for ESM around? I can't really find anything.

EDIT: I hope you don't mind me hijacking the thread.

Share this post


Link to post
Share on other sites
You can find code for ESM here:

]http://pixelstoomany.wordpress.com/2008/06/12/a-conceptually-simpler-way-to-derive-exponential-shadow-maps-sample-code/

It's slightly modified version but you can easily change it back to original form.

Share this post


Link to post
Share on other sites
Quote:

(*) There is no such thing as 'good' VSM at this time. The technique is very interesting, but much more research is needed to really make it practicable. Plain VSM is unusable due to the extreme amounts of light bleeding it generates on overlapping geometry. All the papers that say that bleeding is 'acceptable' and 'easy to hide' lie. Simple as that. You might want to look into ESM (a bit better, but not top either), convolution shadowmaps (much better, but much more performance and memory hungry). Or something really nice, but from a completely different corner of maths, realtime stochastic refinement shadow maps.

Definitely look at exponential variance shadow maps. They have few if any problems with light bleeding and 32-bit float textures. I agree that light bleeding in typical VSMs is a showstopped in a lot of cases, although it's untrue to say that they're "unusable" as there's a growing number of games that have happily shipped using even stock VSMs.

I'm also surprised that you suggest convolution shadow maps as an alternative... they have terrible problems with light bleeding near *all* occluders, not just second-occluders. They do a good job for stuff like foliage or other probabilistic stuff that you don't really want a precise shadow for, but as a general shadowing solution for non-trivial scenes, I'd even go as far to say that they are borderline unusable. Even layered VSMs - which are more theoretically interesting than anything - almost univerally outperfom them, and exponential VSMs do better pretty much everywhere at a much lower cost.

Do you happen to have a link to 'realtime stochastic refinement shadow maps' by the way? I'd be interested in reading about that.

Quote:
Original post by B_old
It is a really good idea to use EVSM (using exp(c * depth)) if you are going to use VSM. It is very easy to change your working VSM implementation and the lightbleeding is noticeably better without a big performance hit. Unfortunately the lightbleeding is still there, which might be a problem depending on your scene.

I'm surprised you're still getting much/any light bleeding with EVSM. In particular if you're choosing a depth range that fairly tightly bounds your camera frustum (or the specific cascade with CSM/PSSM, even better!) and using a c value of ~42 or similar, you should be getting very little, if any light bleeding (i.e. even clamping off 5% of the function should get rid of anything remaining). Note that you can definitely just bound the camera frustum and clamp objects offscreen to 0/1 - there's no point wasting depth precision on objects offscreen as all you need to know is that they're there, not how they compare to one another :)

In case you think I'm making this up, here's some examples of a scene that has crazy-bad light bleeding with stock VSM (and CSM, and some with ESM), but using EVSM and simple depth range clamping to the frusum (which you should always be doing regardless of the shadow technique), there's absolutely no visible light bleeding, even without any "light bleeding reduction" or visibility function clamping:

#1) EVSM, CSM, ESM

#2) CSM

#3) EVSM, CSM

Also note that 'filtering' and 'resolution management' of shadows are orthogonal topics. High quality shadows implementations make good use of both. VSM/ESM/EVSM/etc. work really well together with cascaded shadow maps. Furthermore the ability to use MSAA when rendering filterable shadow maps and anisotropic filtering when looking up into them means that you often get much higher quality for a cheaper cost than the equivalent resolution/# of "standard" cascaded shadow maps.

Back to the original question though, why are you trying to emulate bilinear filtering during the blurring pass? That pass shouldn't need bilinear filtering at all, and should be quite fast (Aside: if it's supported, you can of course use it to lower the number of taps you need to take when blurring, but that's not necessary). The only place you may need to emulate it is in the lookup shader, where there's only a single lookup. That said, if your hardware can't do anisotropic/mipmapped lookups into your shadow map you're losing a lot of the benefit of VSM et al. anyways... as Yann mentions, there's not a lot of point implementing these advanced shadowing techniques unless you're targetting GPUs with at the very least 16-bit filtering/MSAA support, and ideally 32-bit.

[Edited by - AndyTX on June 11, 2009 8:40:13 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by AndyTX
Definitely look at exponential variance shadow maps. They have few if any problems with light bleeding and 32-bit float textures. I agree that light bleeding in typical VSMs is a showstopped in a lot of cases, although it's untrue to say that they're "unusable" as there's a growing number of games that have happily shipped using even stock VSMs.

I should have mentioned that I already tried EVSM (the modifications to VSM are trivial). It depends on how you defined 'usable'. In my case, the scene is a large exterior urban environment, with the primary lightsource being the sun. As such, the depth complexity is very high, and the depth layer distribution matches quite precisely the worst case scenario for VSM. EVSM are certainly better, but the light bleeding is still noticeable to a degree making the results ugly (semi transparent shadows, visible 'layers' in overlapping shadows especially when the sun is moving, etc). I invested quite some time trying to tweak parameters, but couldn't really find anything that would get rid of the objectionable artifacts.

About games using it, well, have you seen the shadows in GTA4 ? They are horrific, and while not VSM (they're actually much worse than even a naive stock VSM implementation), it shows that production use of a certain technology doesn't necessarily mean said technology is really mature yet.

Quote:
Original post by AndyTX
I'm also surprised that you suggest convolution shadow maps as an alternative... they have terrible problems with light bleeding near *all* occluders, not just second-occluders.

That's surprising. I have had quite good results with CSM, after some fiddling around. They would show much less artifacts than any of VSM/ESM/EVSM, although I couldn't get entirely rid of ringing effects. From enduser tests, these artifacts were seen as much more acceptable than the light bleeding of the former algorithms. However, they were too heavy an both fillrate and memory footprint, due to the pretty high order I used for the signal reconstruction.

Quote:
Original post by AndyTX
and exponential VSMs do better pretty much everywhere at a much lower cost.

I have had almost opposite results. What order did you use on your tests for CSM ?

Quote:
Original post by AndyTX
Do you happen to have a link to 'realtime stochastic refinement shadow maps' by the way? I'd be interested in reading about that.

Here you go. That's a very basic paper, but it shows the ideas behind the technique. In a real application, the algorithm needs to be refined a bit (so to get nice soft shadows, better temporal filtering to get rid of remaining temporal noise, Monte-Carlo sampling of the shadow map and support for dynamic objects by partial invalidation of the temporal cache). This algorithm can be combined with PSSM and friends, and optionally with some form of post-perspective correction. The quality of the results far outperform everything I have ever seen with current filterable shadowing algorithms, and the cost is acceptable (assuming a fully deferred shadowing system). The only problem is that you need a more or less high framerate in order for the convergence to be unnoticeable (it gets problematic below 30 fps).

Quote:
Original post by B_old
I'm surprised you're still getting much/any light bleeding with EVSM.

It really depends a lot on your scene and its specific depth distribution. As I mentioned earlier, I still experience quite a lot of light bleeding with EVSM, with the light source being the sun. YMMV. I haven't tried (E)VSM on smaller artificial lightsources, which have a quite different depth distribution. Anyone did ?

Share this post


Link to post
Share on other sites
Quote:
Original post by AndyTX
I'm surprised you're still getting much/any light bleeding with EVSM. In particular if you're choosing a depth range that fairly tightly bounds your camera frustum (or the specific cascade with CSM/PSSM, even better!) and using a c value of ~42 or similar, you should be getting very little, if any light bleeding (i.e. even clamping off 5% of the function should get rid of anything remaining). Note that you can definitely just bound the camera frustum and clamp objects offscreen to 0/1 - there's no point wasting depth precision on objects offscreen as all you need to know is that they're there, not how they compare to one another :)

Actually I am using c = 20 right now. There was a discussion on beyond3d where someone (might have been you?) suggested that you need the negative moments (or something like that) as as well with c > 20 or you are going to run into a different kind of problem. I just took that persons word for it. :) I don't really want to spend the additional 2 channels.

Actually I don't clamp objects offscreen. I didn't even think about it, although it definitely sounds like a good idea.
How does it work? I calculate the near and far plane that around the camera frustum from the lights point of view so to speak. When generating the shadow map I do a clamp to those values in the vertexshader?

About MSAA: It sure looks nice, but the rendertarget is of bigger size, isn't it? Then it wouldn't be fair to compare it to shadowmaps of the "same" resolution.

Share this post


Link to post
Share on other sites
Browser ate my original post, so I'll make this quick :(

Quote:
Original post by Yann L
I should have mentioned that I already tried EVSM (the modifications to VSM are trivial). It depends on how you defined 'usable'. In my case, the scene is a large exterior urban environment, with the primary lightsource being the sun. As such, the depth complexity is very high, and the depth layer distribution matches quite precisely the worst case scenario for VSM. EVSM are certainly better, but the light bleeding is still noticeable to a degree making the results ugly (semi transparent shadows, visible 'layers' in overlapping shadows especially when the sun is moving, etc). I invested quite some time trying to tweak parameters, but couldn't really find anything that would get rid of the objectionable artifacts.

Are you doing depth range rescaling/clamping on each of the cascades? That's pretty key as it will sharpen the exponential considerably (given equal c-values) and eliminate all light bleeding from objects outside of the given frustum partition.

I'm surprised that you're having any trouble, as most of the work that I've been doing lately has been on scenes like you describe: big, urban, complex depth distributions, etc. and EVSM works exceptionally well.

Quote:
Original post by Yann L
About games using it, well, have you seen the shadows in GTA4 ? They are horrific, and while not VSM (they're actually much worse than even a naive stock VSM implementation), it shows that production use of a certain technology doesn't necessarily mean said technology is really mature yet.

Well sure, but your comment about it being "unusable" seem trivially false since people have "used" it :)

Quote:
Original post by Yann LI have had almost opposite results. What order did you use on your tests for CSM ?

M=16, so 8 full render targets of data... even with pretty aggresive depth range clamping it takes a *lot* of overdarkening to eliminate the "bleeding near occluder" artifacts, and with and equivalent amount of overdarkening, even stock VSM often has no light bleeding, and EVSM definitely doesn't.

Quote:
Original post by Yann L
Here you go.

Ah yes that paper, I have read it. Sure, temporal super-sampling can be applied to any variable in your shader (in fact the reprojection-caching papers are more general), whether it be a normal, filtered, warped, etc. shadow map lookup or something else. Same issues with other temporal caching apply; things that become visible will be aliased, moving lights over semi-complex geometry are problematic, etc. It's not a complete solution by itself - and at some point you might as well reprojection cache a much wider variety of parameters (at least all of the static lighting). Gears of War 2 for instance uses reprojection caching for their SSAO implementation so it's certainly far from useless, but the artifacts from it are fairly obvious to even an untrained eye in that game, and they are similar with any non-trivial shadowing.

So I agree that it's good to have another tool in the box, but it's really orthogonal to the use of good shadow filtering. You could temporally super-sampling textures instead of filtering them as well, but it's hardly efficient...

Quote:
Original post by Yann L
It really depends a lot on your scene and its specific depth distribution. As I mentioned earlier, I still experience quite a lot of light bleeding with EVSM, with the light source being the sun. YMMV.

We should maybe take the discussion offline, but as I mentioned I use EVSM with lots of big, complex scenes lately and it works amazingly well, with very little (if any) light bleeding. I'm curious as to how our implementations differ... I suspect mainly in clamping depth ranges to each partition (do you do that?), which as I mentioned does make a large difference and should be done with all shadowing techniques for precision reasons alone.

Quote:
Original post by B_old
Actually I am using c = 20 right now. There was a discussion on beyond3d where someone (might have been you?) suggested that you need the negative moments (or something like that) as as well with c > 20 or you are going to run into a different kind of problem. I just took that persons word for it. :) I don't really want to spend the additional 2 channels.

Right, that will make a difference. I typically use the +/- c (4 components) version of EVSM so I can ramp up the exponents much higher.

Quote:
Original post by B_old
Actually I don't clamp objects offscreen. I didn't even think about it, although it definitely sounds like a good idea.
How does it work? I calculate the near and far plane that around the camera frustum from the lights point of view so to speak. When generating the shadow map I do a clamp to those values in the vertexshader?

It's very simple actually: for each frustum partition (even if just 1), work out the light space depth range that it occupies (you can simply project each corner into light space) and use that range for your depth function in light space. i.e. map it to [-1, 1], clamp outliers and then pass the resulting depth through the exponential as usual. That way anything outside the camera frustum gets clamped to one end of the depth range and thus no matter how much complexity there is out there, it all gets variance = 0 and thus won't produce any light bleeding what-so-ever. It will also produce a much sharper exponential which will further reduce any bleeding.

Quote:
Original post by B_old
About MSAA: It sure looks nice, but the rendertarget is of bigger size, isn't it? Then it wouldn't be fair to compare it to shadowmaps of the "same" resolution.

It's worth it even if you use a smaller-sized render target, since MSAA gives you nicely jittered sampling (vs. regular sampling with a larger RT) which makes a *huge* difference in motion that more than makes up the lower resolution. Furthermore, MSAA is often better-optimized than simply rendering to a larger texture since the samples can often be compressed/written at high rates. (Not to mention on tiled renderers, MSAA is rediculously cheap since the high-resolution data gets resolved before being written into the render target, so you never need full backing storage for the MSAAed texture).

Share this post


Link to post
Share on other sites
Thanks for the answer AndyTX.
Do you map to [-1, 1] to get 1 extra bit or is there something else going on? Anyway, I believe I got it working and the result really are nice. But there is one huge BUT and I don't know what to do about it.
I'm using that BoundingBox approach to find the correct split when applying my PSSM. (The presentation about the frostbite engine talks about and there was a nice thread on this forum. I'll find it for you if you don't know what I mean.) So there is the problem. If I clamp to the camera-frustum of each split, the bounding box approach will sometimes get data from clamped sections of the shadowmap, resulting in false shadows. Have you run into something similar? It would be really cool to find a way around this. Maybe if I only clamp the shadows between the light and the camera and those beyond. Of course it won't be as pretty. :(

Share this post


Link to post
Share on other sites
Quote:
Original post by B_old
Do you map to [-1, 1] to get 1 extra bit or is there something else going on?

Nope, just might as well use the extra range :) Once you run it through the exp() function there's no reason not to use the [0, 1] range as well.

Quote:
Original post by B_old
I'm using that BoundingBox approach to find the correct split when applying my PSSM. [...] Have you run into something similar? It would be really cool to find a way around this. Maybe if I only clamp the shadows between the light and the camera and those beyond. Of course it won't be as pretty. :(

Yes, very simple to solve: you just also have to consider depth when comparing your bounding box. So projecting into a given split means scale/biasing all of (x, y, z), and comparing all of those to the bounding volume of that split (usually after being scale/biased, you just make sure they are in [0, 0, -1] -> [1, 1, 1] or whatever). FWIW this is precisely what I'm doing and it works great.

Share this post


Link to post
Share on other sites
Quote:
Original post by AndyTX
Are you doing depth range rescaling/clamping on each of the cascades? That's pretty key as it will sharpen the exponential considerably (given equal c-values) and eliminate all light bleeding from objects outside of the given frustum partition.

Yes, each cascade is depth clamped. I might be able to take a few screenshots, the EVSM implementation is still on the SVN somewhere. I don't remember the actual parameters that I used (there was a lot of tweaking going on), but I always stumbled over worst case situations where light bleeding would be very visible. Generally, the solution works fairly well, but the pathological cases were pretty common in the scenes I tested it in. Specifically when the sun was very low on the horizon, the depth complexity grew very high and light bleeding was very noticeable.

Quote:
Original post by AndyTX
Well sure, but your comment about it being "unusable" seem trivially false since people have "used" it :)

Well, true :)

Quote:
Original post by AndyTX
M=16, so 8 full render targets of data... even with pretty aggresive depth range clamping it takes a *lot* of overdarkening to eliminate the "bleeding near occluder" artifacts, and with and equivalent amount of overdarkening, even stock VSM often has no light bleeding, and EVSM definitely doesn't.

AFAIR, I used very similar parameters, but got significantly better results than with both VSM and ESM (and compared to the admittedly horrible results you got on your CSM screenshots). I didn't directly compare it to EVSM though. Well, you gave me a reason to retry the previous code :)

Quote:
Original post by AndyTX
Ah yes that paper, I have read it. Sure, temporal super-sampling can be applied to any variable in your shader (in fact the reprojection-caching papers are more general), whether it be a normal, filtered, warped, etc. shadow map lookup or something else. Same issues with other temporal caching apply; things that become visible will be aliased, moving lights over semi-complex geometry are problematic, etc.

Yes, but most of these problems have rather trivial solutions. I haven't used reprojection caches for anything else than shadowing (other than in pure tech demos), but for shadow mapping it works amazingly well. I was very skeptical at first (due to the issues you mentioned), but just sat down and implemented it. After some modifications and additions, the systems gives very pleasant shadows at very acceptable cost. Recently visible geometry is only noticeably aliased during the first two or three frames, because the iterative solution converges logarithmically. Even if I know what to look for, I'm pretty much unable to see the aliasing over the initial convergence phase. Another advantage over filterable solutions is the fact that you can get very sharp contact shadows without insanely high SM resolutions.

Quote:
Original post by AndyTX
Gears of War 2 for instance uses reprojection caching for their SSAO implementation so it's certainly far from useless, but the artifacts from it are fairly obvious to even an untrained eye in that game, and they are similar with any non-trivial shadowing.

It really depends on how the technique is implemented. I don't know how it reacts to things like SSAO or selective shader supersampling, but for shadows it works extremely well.

Quote:

We should maybe take the discussion offline, but as I mentioned I use EVSM with lots of big, complex scenes lately and it works amazingly well, with very little (if any) light bleeding. I'm curious as to how our implementations differ...

Yes, it might be interesting to investigate further.

Share this post


Link to post
Share on other sites
Quote:
Original post by Yann L
Generally, the solution works fairly well, but the pathological cases were pretty common in the scenes I tested it in. Specifically when the sun was very low on the horizon, the depth complexity grew very high and light bleeding was very noticeable.

Hmm, yeah those are certainly the worst cases for any shadowing algorithm (filtering, resolution, even ray tracing, are all the worst in those cases). Just for fun though I went and pulled up one of the huge scenes that I have and played with low light angles some more, trying to construct worst-case scenarios. I did manage to create some good perspective aliasing, but as far as light bleeding goes, my best efforts were generally foiled. I managed to get one case in which I was getting about 5% light bleeding (i.e. should be 0, was 0.05), but I couldn't get anything worst than that, and that amount is trivially clamped off. Maybe there's something unique in the scene you're playing with, but I really was getting the "skyscraper casting shadow overlapping ant shadow" cases and they were being handled just fine by EVSM + cascade depth ranges.

Quote:
Original post by Yann L
AFAIR, I used very similar parameters, but got significantly better results than with both VSM and ESM (and compared to the admittedly horrible results you got on your CSM screenshots). I didn't directly compare it to EVSM though. Well, you gave me a reason to retry the previous code :)

Yeah I dunno, maybe there's something wrong with my implementation, but it's not a particularly complex technique to implement, so I dunno. There was also a ton of light bleeding in the demo provided by the paper authors, which itself had a really tiny depth range, so I figured my results were fairly in line with that and didn't pursue it much further.

Quote:
Original post by Yann L
Yes, but most of these problems have rather trivial solutions. I haven't used reprojection caches for anything else than shadowing (other than in pure tech demos), but for shadow mapping it works amazingly well. [...] Another advantage over filterable solutions is the fact that you can get very sharp contact shadows without insanely high SM resolutions.

Yeah for sure, they are interesting. Similar arguments for getting insane sampling rates by capturing coherence for other stuff applies as well - geometry, shader, normal map, etc. aliasing can all be addressed similarly. Still, every time I've played around with it I've found the artifacts to be fairly objectionable in even moderately-paced scenes/games, but I haven't really given it a lot of work for shadows in particular, so maybe it works better than I imagined :) Curiously do you use it *together* with cascades as well? I'd imagine that would at least be usable, rather than in isolation, where it may required hundreds of samples or more to converge to screen resolution.

I'd still argue that it's orthogonal to filtering (you can never sample "enough" technically - band-limitting the signal is always necessary at some point to eliminate aliasing due to undersample/minification), but it may work well enough in practice to reduce or eliminate the need for any of the fancier filtering techniques.

Anyways it's good to hear that CSM is working out well for some people. I've yet to have any luck with it other than foliage sort of situations where admitadly the continuity of the visibility function that it provides is highly desirable there, since it's much more important to avoid spatial discontinuities than to get sharp shadows.

Share this post


Link to post
Share on other sites
Quote:
Original post by AndyTX
Hmm, yeah those are certainly the worst cases for any shadowing algorithm (filtering, resolution, even ray tracing, are all the worst in those cases). Just for fun though I went and pulled up one of the huge scenes that I have and played with low light angles some more, trying to construct worst-case scenarios. I did manage to create some good perspective aliasing, but as far as light bleeding goes, my best efforts were generally foiled.

Hmm. I'll have to recheck my EVSM implementation, maybe I have a bug somewhere. Maybe it's also differences in the cascade split schemes. I'm curious and have to investigate this a bit further. I'll report back when I have some results.

Quote:
Original post by AndyTX
Yeah I dunno, maybe there's something wrong with my implementation, but it's not a particularly complex technique to implement, so I dunno. There was also a ton of light bleeding in the demo provided by the paper authors, which itself had a really tiny depth range, so I figured my results were fairly in line with that and didn't pursue it much further.

I have to admit that I didn't follow the original algorithm proposal to the letter. I read about the math, thought yeah might be interesting to try, and basically derived everything from scratch. There could be some difference in the math somewhere.

Quote:
Original post by AndyTX
Yeah for sure, they are interesting. Similar arguments for getting insane sampling rates by capturing coherence for other stuff applies as well - geometry, shader, normal map, etc. aliasing can all be addressed similarly. Still, every time I've played around with it I've found the artifacts to be fairly objectionable in even moderately-paced scenes/games, but I haven't really given it a lot of work for shadows in particular, so maybe it works better than I imagined :) Curiously do you use it *together* with cascades as well? I'd imagine that would at least be usable, rather than in isolation, where it may required hundreds of samples or more to converge to screen resolution.

Yes, I use it together with a cascade (6 splits currently). Without one, the technique is quite impractical, as you mentioned. With the splits, however, the shadows converge in just a few milliseconds. By tuning some parameters, you can easily trade off temporal with spatial noise or vice versa. Dynamically modifying the convergence criteria depending on camera or object movement speed works very nicely. Fast moving lights are a bit of a problem, but there are ways around this. Simply increasing the convergence timestep on the moving light is often enough. It will create a kind of slight motion blur in the moving shadows, while still maintaining almost 0% aliasing. While objectionable from my point of view, that temporal blur was ironically appreciated by a majority of our beta testers ("wow, nice motion blur") !

Quote:
Original post by AndyTX
I'd still argue that it's orthogonal to filtering (you can never sample "enough" technically - band-limitting the signal is always necessary at some point to eliminate aliasing due to undersample/minification), but it may work well enough in practice to reduce or eliminate the need for any of the fancier filtering techniques.

Yeah, you still need filtering. A medium sized PCF kernel is usually OK. The thing is, that the probabilistic technique gives me both very sharp and soft shadows, while maintaining a very high non-MSAA rasterization speed on shadowmap rendering. I definitely like the smooth filtered look of EVSM and friends, but I really have to have FSAA enabled when rendering them. Otherwise, I either see the flickering, or the shadows become totally blurred by over-the-top Gaussian filtering. And FSAA is still quite expensive on current hardware, especially if you render six 2k/4k render targets per frame, only for shadowing.

Share this post


Link to post
Share on other sites
Quote:
Original post by Yann L
Hmm. I'll have to recheck my EVSM implementation, maybe I have a bug somewhere. Maybe it's also differences in the cascade split schemes. I'm curious and have to investigate this a bit further. I'll report back when I have some results.

Cool, I'd be interested in what you find. Feel free to PM/e-mail me if you want to chat further about the details, because I'm definitely interested in hearing your experiences and tracking down we have seen such different results with the various techniques.

Quote:
Original post by Yann L
Yes, I use it together with a cascade (6 splits currently). Without one, the technique is quite impractical, as you mentioned. With the splits, however, the shadows converge in just a few milliseconds.

Nice! Well maybe I should take a more seriously look at it then. I take it you find that the history buffer, etc. isn't a huge overhead to maintain? Do you do anything special to make it more SLI-friendly?

Quote:
Original post by Yann L
I definitely like the smooth filtered look of EVSM and friends, but I really have to have FSAA enabled when rendering them. Otherwise, I either see the flickering, or the shadows become totally blurred by over-the-top Gaussian filtering. And FSAA is still quite expensive on current hardware, especially if you render six 2k/4k render targets per frame, only for shadowing.

Yes I agree with that, you 100% need to use MSAA on your shadow maps with the filterable techniques, especially if you're varying your partitioning scheme from frame to frame, or else you'll see swimming and so forth along shadow edges. I've had fairly good success with the speed of rendering MSAAed textures on DX10+ class hardware up to at least 1024^2, but admittadly at 2048^2 all current hardware takes a rediculous speed hit with MSAA. I believe that's where you fall off the edge of NVIDIA's (still on-chip, yikes!) fast Z-cull metadata memory FWIW.

That said, MSAA is typically pretty cheap on tiled renderers (since it can be resolved in-core, so it's just math and no extra memory/bandwidth). There's at least one upcoming architecture that will be able to take advantage of this :)

Share this post


Link to post
Share on other sites
Quote:
Original post by AndyTX
Nope, just might as well use the extra range :) Once you run it through the exp() function there's no reason not to use the [0, 1] range as well.

Cool. That alone, does decrease the lightbleeding a little bit. I should have tried that earlier.
Quote:
Original post by AndyTX
Yes, very simple to solve: you just also have to consider depth when comparing your bounding box. So projecting into a given split means scale/biasing all of (x, y, z), and comparing all of those to the bounding volume of that split (usually after being scale/biased, you just make sure they are in [0, 0, -1] -> [1, 1, 1] or whatever). FWIW this is precisely what I'm doing and it works great.

After playing with this a little bit, I don't think my problem is in choosing the correct splits. One thing I found though, is that I was using the same zfar value for all splits, so obviously I was wasting some precision there. I now adjusted the zfar for the different splits and that again decreased the lightbleeding further. It is still noticeable in the worst spots though and I believe clamping the depth range would be helpful, but I still can't get it to work, although I think I have understood what it is about.
Actually I'm going quite off-topic here, but maybe you have some advice. To calculate the view- and projection matrix for the shadow for a given split I do roughly this:

//sceneAABB is the box around the scene and viewAABB is the box around the current frustum split
float center = dot(sceneAABB.getPos() - viewAABB.getPos(), light->getWorldDir());
float radius = dot(sceneAABB.getHalfsize(), abs(light->getWorldDir()));

float znear = center - radius;


Vector3 pos = viewAABB.getPos() + znear * light->getWorldDir();
Matrix4 view;
setLookAt(view, pos, pos + light->getWorldDir(), light->getWorldUp());
//My intention is, that I the camera is sitting at the edge of the sceneAABB (so that all shadows get generated) and looking directly at the viewAABB. It seems to work.

//Here I transform the viewAABB into the space of the newly created view
bounding::AABB transformedViewAABB;
viewAABB.getTransformed(transformedViewAABB, view);


transformedViewAABB.getMinMax(vmin, vmax);


center = dot(viewAABB.getPos() - pos, light->getWorldDir());
radius = dot(viewAABB.getHalfsize(), abs(light->getWorldDir()));

float zfar = center + radius;
//The intention here is to choose a zfar value for the projection that just fits the viewAABB
//Using vmax.z does not always work, which confuses me. :(

Matrix4 proj;
setOrtho(proj, vmax.x - vmin.x, vmax.y - vmin.y, 0.f, zfar);

viewProj = view * proj;


As I wrote In one comment, I am a little bit confused, that I cant the the largest z-value of the transformed viewAABB as the farplane. Do you know what that could be about?

Now If I wanted to clamp all depth values that are not "inside" the viewAABB I would compare against znear = center - radius and set every value that is smaller to 0.f or -1.f. If I do that though, I sometimes get false shadows. I expected it would work without further adjustments in the code that does the shadow comparison.
I don't know whether you have time to help me with this, but I appreciate your advice so far!

One small (and potentially stupid question):
Quote:
Original post by AndyTX
Yes I agree with that, you 100% need to use MSAA on your shadow maps with the filterable techniques

Are you suggesting that non-filterable techniques do fine without MSAA?

Share this post


Link to post
Share on other sites
Quote:
Original post by B_old
Are you suggesting that non-filterable techniques do fine without MSAA?

Non-filterable techniques don't even work with MSAA (on the shadow generation pass), since the MSAA resolve operation is a filter.

Share this post


Link to post
Share on other sites
Quote:
Original post by Yann L
Non-filterable techniques don't even work with MSAA (on the shadow generation pass), since the MSAA resolve operation is a filter.

I am aware of that. To me it almost sounded, like VSM and the likes are more in need of MSAA than other techniques, although this probably isn't what was meant.

Share this post


Link to post
Share on other sites
Quote:
Original post by B_old
I am aware of that. To me it almost sounded, like VSM and the likes are more in need of MSAA than other techniques, although this probably isn't what was meant.

Not really. It's more that VSM and friends need MSAA to look good, while non-filterable solutions don't need (ie. can't use) MSAA at all. Filterable techniques can also be used without MSAA, but their quality will be very significantly compromised in this case.

Share this post


Link to post
Share on other sites
Quote:
Original post by Yann L
Not really. It's more that VSM and friends need MSAA to look good, while non-filterable solutions don't need (ie. can't use) MSAA at all. Filterable techniques can also be used without MSAA, but their quality will be very significantly compromised in this case.

Hm, I don't think we mean the same thing. You almost make it sound like VSM will look worse without MSAA than "straight forward" shadow mapping. I hope this isn't true.
Anyway, I should concentrate on getting this depth-clamping to work.

Share this post


Link to post
Share on other sites
Quote:
Original post by B_old
You almost make it sound like VSM will look worse without MSAA than "straight forward" shadow mapping. I hope this isn't true.

Depending on how well the non-filterable algorithm is done, specifically what type of post-compare filtering is used, whether or not subtexel and/or rotational snapping is performed, then yes, non-filterable SM can indeed look better than filterable solutions without MSAA.

Share this post


Link to post
Share on other sites
Hmm. How does this rotational snapping work? And can't it be used with VSM? I already adjust the translation of the viewProj so that it snaps to pixels, but that only works when I translate the camera. Camera-rotation will still cause shadow swimming. And I suppose there is nothing that can be done against the swimming shadows cast by rotation objects.

I believe I got the depth clamping to work now. There are still some things I have to check, but generally it looks really good. Thanks for the tips and help so far!

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