Cascaded Shadow Mapping & Poisson Disk filtering

A place to show off your latest screenshots and for people to comment on them. Only start a new thread here if you have some nice images to show off!
foxbat
Greenskin
Posts: 131
Joined: Sun Sep 25, 2005 2:44 am
Location: Melbourne, Australia

Cascaded Shadow Mapping & Poisson Disk filtering

Post by foxbat » Thu Jul 26, 2012 2:03 pm

I've released a demo of my shadowing implementation for large outdoor scenes, based on the technique used in Crysis. My implementation uses custom ShadowCameraSetup and shaders.

Here are details on the two techniques used. Each technique may be used independently, but I've included both in this demo.

Stable Cascaded Shadow Mapping
- Remains stable in world space, independent of camera translation and rotation
- Shadows rendered in multiple cascades (implementation uses 4 cascades) giving good shadow resolution over view range
- Blending between cascades

Implementation limitations:
- Only works with directional lights
- Branching is required in fragment shader for cascade selection (could be eliminated by packing cascades into single shadow map)


Rotated Poisson Disk sampling
- Poisson Disk filter is rotated per pixel using a jitter rotation map
- Eliminates shadow edge jaggies at the expense of adding some noise
- filtering is stable in world space to minimise buzzing
- More samples (texture lookups) gives less noise. Implementation uses 8 samples, but can easily be modified for more
- IMO looks better than PCF for similar number of texture lookups (mileage may vary)

Image

Image
Self shadowing

Image
Debug Visualisation of cascades (note blending)

Image
Rotated Poisson Disk filtering (8 samples)


Download windows demo and cross-platform source (MIT license).
0 x

User avatar
Mind Calamity
Ogre Magi
Posts: 1255
Joined: Sat Dec 25, 2010 2:55 pm
Location: Macedonia

Re: Cascaded Shadow Mapping & Poisson Disk filtering

Post by Mind Calamity » Thu Jul 26, 2012 2:39 pm

Kudos to you! This is very, very awesome! Probably the best shadowing technique I've seen lately. Quite good on performance too. Thanks a lot for sharing it :)
0 x
BitBucket username changed to iboshkov (from MindCalamity)
Do you need help? What have you tried?
- xavier
---------------------
HkOgre - a Havok Integration for OGRE | Simple SSAO | My Blog | My YouTube | My DeviantArt

User avatar
DavlexDesign
Gnome
Posts: 397
Joined: Thu Apr 23, 2009 7:23 am
Location: Australia
Contact:

Re: Cascaded Shadow Mapping & Poisson Disk filtering

Post by DavlexDesign » Thu Jul 26, 2012 2:51 pm

Kudos to you foxbat,

I've been looking at this very same approach for close up scene shadows in my project, this should really help me out.
thank you very much.

Alex
0 x

bstone
OGRE Expert User
OGRE Expert User
Posts: 1920
Joined: Sun Feb 19, 2012 9:24 pm
Location: Russia

Re: Cascaded Shadow Mapping & Poisson Disk filtering

Post by bstone » Thu Jul 26, 2012 3:53 pm

Unbelievable! I just mentioned this method a week ago as the best one for terrains and here you go - foxbat to the rescue :D.

If somebody manages to implement the UV packing of the shadow atlas now then this will be the uber shadows method for large scenes in Ogre.
0 x

User avatar
scrawl
OGRE Expert User
OGRE Expert User
Posts: 1119
Joined: Sat Jan 01, 2011 7:57 pm
Location: Germany
x 2

Re: Cascaded Shadow Mapping & Poisson Disk filtering

Post by scrawl » Thu Jul 26, 2012 4:39 pm

Very nice, the demo works in Wine on Linux as well btw.

The only problem I can see with it is that near shadows (first split) have more blur (in world space) than far shadows (last split). Not that much of a problem anyway, since you have blending between that. But couldn't that be solved easily by considering the texture size for the blur radius?

Why do you use BitBucket to upload a source zip file, instead of the source itself? That kind of defeats the purpose of version control.
0 x

foxbat
Greenskin
Posts: 131
Joined: Sun Sep 25, 2005 2:44 am
Location: Melbourne, Australia

Re: Cascaded Shadow Mapping & Poisson Disk filtering

Post by foxbat » Fri Jul 27, 2012 10:18 am

If somebody manages to implement the UV packing of the shadow atlas now then this will be the uber shadows method for large scenes in Ogre.
I agree, that would be an awesome feature. I looked at this briefly a while back. I think the most efficient way to do it would be to render each map into a different rect within the same texture, but that's a fairly low level render system feature and as far as I know Ogre doesn't currently support this (correct me if I'm wrong). Second best option would be to render each separately and then pack on the CPU or GPU. The cost of packing would need to be weighed against the cost of branching.
Why do you use BitBucket to upload a source zip file, instead of the source itself? That kind of defeats the purpose of version control.
I uploaded the source archive for convenience in case there are people who want to download the source once-off and don't want to install a Mercurial client. But you're right; version control is the much better option for most people.
0 x

al2950
OGRE Expert User
OGRE Expert User
Posts: 1104
Joined: Thu Dec 11, 2008 7:56 pm
Location: Bristol, UK
x 45

Re: Cascaded Shadow Mapping & Poisson Disk filtering

Post by al2950 » Fri Jul 27, 2012 10:25 am

@foxbat

Checked out the demo and it is very impressive. Would like you to see yout shadow camera system added to the Ogre repo :). As for the texture atlas thing the RTSS can do that, well sort of. There is a sub render state called instanced viewports, which will allow you to render several viewports to a single texture using one set of render calls. However its not part of the RTSS component but part of the sample (not sure why!).
0 x

bstone
OGRE Expert User
OGRE Expert User
Posts: 1920
Joined: Sun Feb 19, 2012 9:24 pm
Location: Russia

Re: Cascaded Shadow Mapping & Poisson Disk filtering

Post by bstone » Fri Jul 27, 2012 10:35 am

foxbat wrote:render each map into a different rect within the same texture, but that's a fairly low level render system feature and as far as I know Ogre doesn't currently support this (correct me if I'm wrong)
I don't see any issues here. Get texture's render target, clear it before rendering the first shadow map, configure the viewport to cover the packed bounding box and clear no buffers (can overlap the bounding box of the previous cascade, no problem), render to the texture, move to the next cascade. Something like that.
0 x

foxbat
Greenskin
Posts: 131
Joined: Sun Sep 25, 2005 2:44 am
Location: Melbourne, Australia

Re: Cascaded Shadow Mapping & Poisson Disk filtering

Post by foxbat » Sun Jul 29, 2012 1:39 pm

al2950 wrote:Would like you to see yout shadow camera system added to the Ogre repo
I think that's a good idea. Adding an additional ShadowCameraSetup option should be pretty straight forward.

More complicated would be deciding what to do with the shared GPU parameter set used for passing the cascade transform offsets to the shader. This is used as an optimisation since there's no need to pass the complete matrix for every cascade (due to partial similarity of the matrices). The user should still be able to pass full matrices using the existing Ogre functionality if they don't want to use the offsets method. Perhaps the easiest solution would be to provide a hook to let the user get the cascade offsets and setup their own GPU parameters. Another way would be to add an auto parameter for the cascade offsets, only to be used in CSM mode.

The Poisson Disk filtering is implemented in shader only, so it can happily exist outside of the Ogre repo unless it would be useful to have as a demo.
0 x

bstone
OGRE Expert User
OGRE Expert User
Posts: 1920
Joined: Sun Feb 19, 2012 9:24 pm
Location: Russia

Re: Cascaded Shadow Mapping & Poisson Disk filtering

Post by bstone » Mon Jul 30, 2012 1:22 pm

See how PSSM shadow camera setup handles plane split points. I think you should be able to use the same approach for passing cascade offsets and it will be coherent across shadow setups.
0 x

foxbat
Greenskin
Posts: 131
Joined: Sun Sep 25, 2005 2:44 am
Location: Melbourne, Australia

Re: Cascaded Shadow Mapping & Poisson Disk filtering

Post by foxbat » Tue Jul 31, 2012 10:54 am

I believe OGRE's PSSM implementation requires texWorldViewProjMatrix0 through texWorldViewProjMatrix3 to be sent to the fragment shader (one matrix for each shadow texture). My CSM implementation can work this way also, but actually requires less information; just texWorldViewProjMatrix0 for the first cascade and then a vector for each additional cascade. Doing it this way means fewer calculations are required in the fragment shader (if you do your transforms in the fragment shader) or fewer texcoord registers used (if you do your transforms in the vertex shader) :)
0 x

bstone
OGRE Expert User
OGRE Expert User
Posts: 1920
Joined: Sun Feb 19, 2012 9:24 pm
Location: Russia

Re: Cascaded Shadow Mapping & Poisson Disk filtering

Post by bstone » Tue Jul 31, 2012 5:21 pm

That's totally controlled by the shadow receiver material declaration. You can pass whatever you want to the shadow receiver v/f programs. The texture projection matrix are supported by Ogre's material system via param_named_auto. But PSSM's split points are not for example. To work around that PSSM simply requires the "pssmSplitPoints" parameter to be set manually in the shadow receiver's material fragment program by the user code. You can do the same with your offset vectors. Hopefully that makes sense.
0 x

scratchyrice
Gnome
Posts: 324
Joined: Thu Apr 27, 2006 9:14 pm
Location: United Kingdom - England

Re: Cascaded Shadow Mapping & Poisson Disk filtering

Post by scratchyrice » Wed Aug 01, 2012 12:33 pm

This is great!

How would I go about using this with normal mapped objects?

Thanks

Scratchy
0 x
Intel I5 750 OC'd to 4.2Ghz per core, Geforce 580GTX 1.5Gb GPU, 280GTX for PhysX, 8Gb DDR 3 ram

User avatar
scrawl
OGRE Expert User
OGRE Expert User
Posts: 1119
Joined: Sat Jan 01, 2011 7:57 pm
Location: Germany
x 2

Re: Cascaded Shadow Mapping & Poisson Disk filtering

Post by scrawl » Wed Aug 01, 2012 11:01 pm

Carefully "merge" the normal mapping shader together with the shadow receiver shader from this demo. That's the only way to go.
0 x

foxbat
Greenskin
Posts: 131
Joined: Sun Sep 25, 2005 2:44 am
Location: Melbourne, Australia

Re: Cascaded Shadow Mapping & Poisson Disk filtering

Post by foxbat » Thu Aug 02, 2012 11:09 am

I agree; combining the two into a single shader is probably the easiest solution and should be quite efficient. If your scene has a lot of overdraw you may get a performance benefit by doing an early Z pass (add a minimal pass before the main pass and set colour_write off).
0 x

scratchyrice
Gnome
Posts: 324
Joined: Thu Apr 27, 2006 9:14 pm
Location: United Kingdom - England

Re: Cascaded Shadow Mapping & Poisson Disk filtering

Post by scratchyrice » Thu Aug 02, 2012 12:45 pm

Thanks foxbat and scrawl. I thought that might be the way forward but just needed to be sure. I will give this a go as i am currently using the rtss in my engine and the performance hit is just unacceptable considering all i want is some directional shadowing plus normal mapping. Im good with core engine mechanics, ai and physics - but when it comes to shaders i have not a clue! lol

Cheers

Scratchy
0 x
Intel I5 750 OC'd to 4.2Ghz per core, Geforce 580GTX 1.5Gb GPU, 280GTX for PhysX, 8Gb DDR 3 ram

User avatar
duststorm
Minaton
Posts: 921
Joined: Sat Jul 31, 2010 6:29 pm
Location: Belgium
Contact:

Re: Cascaded Shadow Mapping & Poisson Disk filtering

Post by duststorm » Tue Aug 07, 2012 11:26 am

Wow, amazing! :D I've been away for a week and look what's happened behind my back :wink:
I was seriously considering implementing this myself after bstone mentioned it.
Can't wait to test it out with Ogre::Terrain for real-time self-shadowing.

I'll probably have a try at incorporating it into RTSS, that will make it easy to combine it with eg. normal mapping.


EDIT: just tried the demo, it compiles without a hassle on linux thanks to the CMake setup.
One small mistake with the materials though: the textures for the skybox should have lowercase names (eg. "stormy_fr.jpg" instead of "stormy_FR.jpg"). On linux and OS X this matters, and will otherwise result in a white sky.

A quick hint: you can enable the cascade debug by uncommenting the "#define DEBUG_CSM" line in media/core/ShadowReceiver.cg
0 x
Developer @ MakeHuman.org

User avatar
duststorm
Minaton
Posts: 921
Joined: Sat Jul 31, 2010 6:29 pm
Location: Belgium
Contact:

Re: Cascaded Shadow Mapping & Poisson Disk filtering

Post by duststorm » Mon Aug 13, 2012 10:39 am

I did a quick test with it and I found an issue with normals when scaling models. Normalizing the normal in the shadow receiver shader fixes this. I made a pull request with a fix to your bitbucket repo.

I found that it was really easy to incorporate it into your own application, kudos to that. Just make sure that you create a CSMGpuConstants object BEFORE loading any materials, as some constants need to be set in advance (or shaders will fail to compile). In the example application framework you could do this by overriding the loadResources() method, as the demo illustrates.
0 x
Developer @ MakeHuman.org

foxbat
Greenskin
Posts: 131
Joined: Sun Sep 25, 2005 2:44 am
Location: Melbourne, Australia

Re: Cascaded Shadow Mapping & Poisson Disk filtering

Post by foxbat » Mon Aug 13, 2012 1:12 pm

Thanks for the fixes. I've pulled them into the repo :)
0 x

lygyue
Greenskin
Posts: 122
Joined: Wed Nov 29, 2006 4:07 pm

Re: Cascaded Shadow Mapping & Poisson Disk filtering

Post by lygyue » Wed Aug 15, 2012 11:32 am

How a nice job! Do you have shader code for point light? Please sent me if you have. Thanks alot.
0 x

User avatar
duststorm
Minaton
Posts: 921
Joined: Sat Jul 31, 2010 6:29 pm
Location: Belgium
Contact:

Re: Cascaded Shadow Mapping & Poisson Disk filtering

Post by duststorm » Fri Aug 17, 2012 4:41 pm

To give you a heads-up: I'm working on a modified TerrainMaterialGenerator that also supports this shadow technique. But as I don't have much time at the moment I work on it for short periods of time.

Having experimented with it a little more I really have to express praise for this wonderful shader. The poisson filtering does a wonderful job at smoothing out the shadows, and the fade between cascades is something that not even Crysis has but makes the shadows really fluent.
I'm really amazed at how incredibly stable the shadows are. Even with moving lights and objects it does a pretty decent job.

There are a few things I'd like to improve on it when I get the time, like how split points are set and how parameters are passed to the shader. I would also make it more configurable, like the texture resolution and number of cascades. It would also be nice to be able to enable or disable the debugging and poisson disk filtering from code. Apart from that it's great.

Here' s a teaser (it's not completely working yet):
screenshot08172012_172827517_small.jpg
Stable CSM on terrain (debug)
screenshot08172012_172827517_small.jpg (137.36 KiB) Viewed 27166 times
The intended end-result is a terrain with pagedGeometry trees and a dynamic day-night cycle using Caelum or SkyX. For this to look decent I need the shading of the tree impostors to vary with the changing lighting and terrain needs to cast dynamic shadows (as opposed to using pre-calculated lightmaps to store which part is shadowed). I'm confident that I'll be able to realize that with this shadow technique.
0 x
Developer @ MakeHuman.org

User avatar
amigoface
Greenskin
Posts: 132
Joined: Mon Oct 13, 2008 3:01 pm

Re: Cascaded Shadow Mapping & Poisson Disk filtering

Post by amigoface » Fri Aug 17, 2012 6:27 pm

very nice !

highly intersted to see the results

btw : using skyx with the volumetric clouds will look much better ;)
0 x

User avatar
Mind Calamity
Ogre Magi
Posts: 1255
Joined: Sat Dec 25, 2010 2:55 pm
Location: Macedonia

Re: Cascaded Shadow Mapping & Poisson Disk filtering

Post by Mind Calamity » Fri Aug 17, 2012 7:54 pm

Duststorm, that's just plain awesome! Without the colorful lights it'd look pretty realistic :)
0 x
BitBucket username changed to iboshkov (from MindCalamity)
Do you need help? What have you tried?
- xavier
---------------------
HkOgre - a Havok Integration for OGRE | Simple SSAO | My Blog | My YouTube | My DeviantArt

foxbat
Greenskin
Posts: 131
Joined: Sun Sep 25, 2005 2:44 am
Location: Melbourne, Australia

Re: Cascaded Shadow Mapping & Poisson Disk filtering

Post by foxbat » Sat Aug 18, 2012 12:37 am

Nice work Duststorm. Feel free to make all the improvements you want. :)
lygyue wrote:How a nice job! Do you have shader code for point light? Please sent me if you have. Thanks alot.
The CSM shadowing technique is designed for directional lights and very narrow spotlights (only directional lights have been implemented). You will need to use a different shadowing technique for point lights. The poisson filtering shader code is independent of shadow projection, so you should be able to use it on point lights without modification.
0 x

User avatar
DavlexDesign
Gnome
Posts: 397
Joined: Thu Apr 23, 2009 7:23 am
Location: Australia
Contact:

Re: Cascaded Shadow Mapping & Poisson Disk filtering

Post by DavlexDesign » Sat Aug 18, 2012 7:02 am

foxbat wrote:Nice work Duststorm. Feel free to make all the improvements you want.
I second that, for the closer up stuff, this would be really really nice.

Alex
0 x

Post Reply