Cascaded Shadow Mapping & Poisson Disk filtering
-
- Greenskin
- Posts: 131
- Joined: Sun Sep 25, 2005 2:44 am
- x 20
Cascaded Shadow Mapping & Poisson Disk filtering
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)
Self shadowing
Debug Visualisation of cascades (note blending)
Rotated Poisson Disk filtering (8 samples)
Download windows demo and cross-platform source (MIT license).
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)
Self shadowing
Debug Visualisation of cascades (note blending)
Rotated Poisson Disk filtering (8 samples)
Download windows demo and cross-platform source (MIT license).
- Mind Calamity
- Ogre Magi
- Posts: 1255
- Joined: Sat Dec 25, 2010 2:55 pm
- Location: Macedonia
- x 81
Re: Cascaded Shadow Mapping & Poisson Disk filtering
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
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
Do you need help? What have you tried?
- xavier
---------------------
HkOgre - a Havok Integration for OGRE | Simple SSAO | My Blog | My YouTube | My DeviantArt
- DavlexDesign
- Orc
- Posts: 400
- Joined: Thu Apr 23, 2009 7:23 am
- Location: Australia
- x 19
- Contact:
Re: Cascaded Shadow Mapping & Poisson Disk filtering
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
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
-
- OGRE Expert User
- Posts: 1920
- Joined: Sun Feb 19, 2012 9:24 pm
- Location: Russia
- x 201
Re: Cascaded Shadow Mapping & Poisson Disk filtering
Unbelievable! I just mentioned this method a week ago as the best one for terrains and here you go - foxbat to the rescue .
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.
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.
-
- OGRE Expert User
- Posts: 1119
- Joined: Sat Jan 01, 2011 7:57 pm
- x 216
Re: Cascaded Shadow Mapping & Poisson Disk filtering
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.
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.
-
- Greenskin
- Posts: 131
- Joined: Sun Sep 25, 2005 2:44 am
- x 20
Re: Cascaded Shadow Mapping & Poisson Disk filtering
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.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 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.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.
-
- OGRE Expert User
- Posts: 1227
- Joined: Thu Dec 11, 2008 7:56 pm
- Location: Bristol, UK
- x 157
Re: Cascaded Shadow Mapping & Poisson Disk filtering
@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!).
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!).
-
- OGRE Expert User
- Posts: 1920
- Joined: Sun Feb 19, 2012 9:24 pm
- Location: Russia
- x 201
Re: Cascaded Shadow Mapping & Poisson Disk filtering
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.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)
-
- Greenskin
- Posts: 131
- Joined: Sun Sep 25, 2005 2:44 am
- x 20
Re: Cascaded Shadow Mapping & Poisson Disk filtering
I think that's a good idea. Adding an additional ShadowCameraSetup option should be pretty straight forward.al2950 wrote:Would like you to see yout shadow camera system added to the Ogre repo
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.
-
- OGRE Expert User
- Posts: 1920
- Joined: Sun Feb 19, 2012 9:24 pm
- Location: Russia
- x 201
Re: Cascaded Shadow Mapping & Poisson Disk filtering
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.
-
- Greenskin
- Posts: 131
- Joined: Sun Sep 25, 2005 2:44 am
- x 20
Re: Cascaded Shadow Mapping & Poisson Disk filtering
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)
-
- OGRE Expert User
- Posts: 1920
- Joined: Sun Feb 19, 2012 9:24 pm
- Location: Russia
- x 201
Re: Cascaded Shadow Mapping & Poisson Disk filtering
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.
-
- Gnome
- Posts: 358
- Joined: Thu Apr 27, 2006 9:14 pm
- Location: United Kingdom - England
- x 15
Re: Cascaded Shadow Mapping & Poisson Disk filtering
This is great!
How would I go about using this with normal mapped objects?
Thanks
Scratchy
How would I go about using this with normal mapped objects?
Thanks
Scratchy
Intel i7 4790k, Gigabyte Nvidia GeForce 3080 10GB, 16GB DDR3
-
- OGRE Expert User
- Posts: 1119
- Joined: Sat Jan 01, 2011 7:57 pm
- x 216
Re: Cascaded Shadow Mapping & Poisson Disk filtering
Carefully "merge" the normal mapping shader together with the shadow receiver shader from this demo. That's the only way to go.
-
- Greenskin
- Posts: 131
- Joined: Sun Sep 25, 2005 2:44 am
- x 20
Re: Cascaded Shadow Mapping & Poisson Disk filtering
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).
-
- Gnome
- Posts: 358
- Joined: Thu Apr 27, 2006 9:14 pm
- Location: United Kingdom - England
- x 15
Re: Cascaded Shadow Mapping & Poisson Disk filtering
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
Cheers
Scratchy
Intel i7 4790k, Gigabyte Nvidia GeForce 3080 10GB, 16GB DDR3
- duststorm
- Minaton
- Posts: 921
- Joined: Sat Jul 31, 2010 6:29 pm
- Location: Belgium
- x 80
- Contact:
Re: Cascaded Shadow Mapping & Poisson Disk filtering
Wow, amazing! I've been away for a week and look what's happened behind my back
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
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
Developer @ MakeHuman.org
- duststorm
- Minaton
- Posts: 921
- Joined: Sat Jul 31, 2010 6:29 pm
- Location: Belgium
- x 80
- Contact:
Re: Cascaded Shadow Mapping & Poisson Disk filtering
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.
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.
Developer @ MakeHuman.org
-
- Greenskin
- Posts: 131
- Joined: Sun Sep 25, 2005 2:44 am
- x 20
Re: Cascaded Shadow Mapping & Poisson Disk filtering
Thanks for the fixes. I've pulled them into the repo
-
- Greenskin
- Posts: 122
- Joined: Wed Nov 29, 2006 4:07 pm
Re: Cascaded Shadow Mapping & Poisson Disk filtering
How a nice job! Do you have shader code for point light? Please sent me if you have. Thanks alot.
- duststorm
- Minaton
- Posts: 921
- Joined: Sat Jul 31, 2010 6:29 pm
- Location: Belgium
- x 80
- Contact:
Re: Cascaded Shadow Mapping & Poisson Disk filtering
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): 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.
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): 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.
Developer @ MakeHuman.org
- amigoface
- Greenskin
- Posts: 132
- Joined: Mon Oct 13, 2008 3:01 pm
Re: Cascaded Shadow Mapping & Poisson Disk filtering
very nice !
highly intersted to see the results
btw : using skyx with the volumetric clouds will look much better
highly intersted to see the results
btw : using skyx with the volumetric clouds will look much better
- Mind Calamity
- Ogre Magi
- Posts: 1255
- Joined: Sat Dec 25, 2010 2:55 pm
- Location: Macedonia
- x 81
Re: Cascaded Shadow Mapping & Poisson Disk filtering
Duststorm, that's just plain awesome! Without the colorful lights it'd look pretty realistic
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
Do you need help? What have you tried?
- xavier
---------------------
HkOgre - a Havok Integration for OGRE | Simple SSAO | My Blog | My YouTube | My DeviantArt
-
- Greenskin
- Posts: 131
- Joined: Sun Sep 25, 2005 2:44 am
- x 20
Re: Cascaded Shadow Mapping & Poisson Disk filtering
Nice work Duststorm. Feel free to make all the improvements you want.
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.lygyue wrote:How a nice job! Do you have shader code for point light? Please sent me if you have. Thanks alot.
- DavlexDesign
- Orc
- Posts: 400
- Joined: Thu Apr 23, 2009 7:23 am
- Location: Australia
- x 19
- Contact:
Re: Cascaded Shadow Mapping & Poisson Disk filtering
I second that, for the closer up stuff, this would be really really nice.foxbat wrote:Nice work Duststorm. Feel free to make all the improvements you want.
Alex