Is there a reason shadows aren’t rendered as a post filter?
I’m probably way off base here, but it seems the only difference would be adding an extra render to quad and then you would gain the benefit of being able to do blurring from the users PoV, removing the stretching from the bur and making shadows look a heck of a lot nicer at lower shadow map resolutions.
Am I mistaken here? Probably…
Actually we talked about something similar used in the cryengine 2 in the deferred rendering thread.
The idea is to have a filter and reconstruct viewspace position from depth, project shadows, and create a screen space shadow mask that is then modulated in to the final render.
I’m considering trying it for Forward rendering too as it would save a geometry pass. But that would be optional, because the classic way is more likely to be supported on low hardware.
I’m thinking of android where making an additional geometry pass tend to be faster than a full screen complex shading.
Also, blurring shadows in full screen is known to give bad results : shadow/light bleeding and evenly spread penumbra no matter how far is the shadow from the viewer. Maybe with a bilateral blur it could work, but that means you need the normal sampling too…and in the end, it may be expensive.
This is handy for saving a geometry pass though. But…an easier way would be to render shadows in the lighting shader during the lighting pass…
So i made some experimentation with this and the results are very interesting.
All of what’s coming is not committed (and may never be) and is still in a WIP stage.
So i made some changes in the PSSMShadowProcessor to have the post shadow pass as a post filter. The ShadowProcessor initialize a Filter that is then passed to the FilterPostProcessor.
This filter reconstruct the fragment position in worldspace (not view space in the end) and the shadow computation are done according to this position.
Computing the shadowTexcoord in now done per pixel instead of per vertex though and everything that write depth receive shadows (making the Recieve shadow mode useless).
The good new is that it is significantly faster when you have a fair amount of shadowed objects in the scene.
I made a test case, that is the worst case scenario for PSSM. Lot of objects, very close to one another, 4 splits and 1024 (1024 could be worst but nvm) filtering is PCF4.
1 new object is added every second, from 0 to 300. I made some perf bench with the classic way of rendering shadows and the post filter one.
Here is a screenshot of the scene :
And here is a graph of how FPS vary with the 2 approaches while adding objects to the scenes.
here is a link to the google spread sheet
https://docs.google.com/spreadsheet/ccc?key=0AsE_ydpoOkOhdF9MRjh4cUo1T3gwby1kaU1lcDhIX1E&pli=1#gid=1
I put a logarithmic scale for the FPS so that the graph is readable.
As you can see the classic approach is faster until you have around 10 objects in the scene…then the post filtered one becomes faster.
In the end with 300 objects i have around 60 fps with the classic approach and around 90 with the post filtered approach.
The filter has some draw backs, but it would be a solid base to implement temporal reprojection.
Then I’d like to test how we could put the shadow calculation in the main render pass, i guess it would be a lot faster too.
@nehon said:
So i made some experimentation with this and the results are very interesting.
All of what's coming is not committed (and may never be) and is still in a WIP stage.
So i made some changes in the PSSMShadowProcessor to have the post shadow pass as a post filter. The ShadowProcessor initialize a Filter that is then passed to the FilterPostProcessor.
This filter reconstruct the fragment position in worldspace (not view space in the end) and the shadow computation are done according to this position.
Computing the shadowTexcoord in now done per pixel instead of per vertex though and everything that write depth receive shadows (making the Recieve shadow mode useless).
The good new is that it is significantly faster when you have a fair amount of shadowed objects in the scene.
I made a test case, that is the worst case scenario for PSSM. Lot of objects, very close to one another, 4 splits and 1024 (1024 could be worst but nvm) filtering is PCF4.
1 new object is added every second, from 0 to 300. I made some perf bench with the classic way of rendering shadows and the post filter one.
Here is a screenshot of the scene :
http://i.imgur.com/P2BZb.jpg
And here is a graph of how FPS vary with the 2 approaches while adding objects to the scenes.
here is a link to the google spread sheet
https://docs.google.com/spreadsheet/ccc?key=0AsE_ydpoOkOhdF9MRjh4cUo1T3gwby1kaU1lcDhIX1E&pli=1#gid=1
I put a logarithmic scale for the FPS so that the graph is readable.
As you can see the classic approach is faster until you have around 10 objects in the scene...then the post filtered one become faster.
In the end with 300 objects i have around 600 fps with the classic approach and around 90 with the post filtered approach.
The filter has some draw backs, but it would be a solid base to implement temporal reprojection.
Then I'd like to test how we could put the shadow calculation in the main render pass, i guess it would be a lot faster too.
Wow... this is incredibly cool! Did you mean you ended with 600 with classic? or the filter? The graphic looks opposite to that. I really don't think that not being able to disable receive shadows is such a bad thing. I always assumed it was a way of compromising to increase performance.... since my machine is so bad... I used it quite often!
@t0neg0d said:
Wow... this is incredibly cool! Did you mean you ended with 600 with classic? or the filter?
No that's a typo i meant 60 :p
I edited the post
You disable receive shadows on glowing things. For example I have some “lights” in my scene, the actual light from them is baked into the textures around them and then the light itself is just an unshaded material of the correct colour set to never receive shadows.
And considering most scenes have well more than 40 objects… those statics are really impressive. Most people would see a drastic performance increase from moment one.
@zarch said:
You disable receive shadows on glowing things. For example I have some "lights" in my scene, the actual light from them is baked into the textures around them and then the light itself is just an unshaded material of the correct colour set to never receive shadows.
Yes exactly.
@zarch said:
You disable receive shadows on glowing things. For example I have some "lights" in my scene, the actual light from them is baked into the textures around them and then the light itself is just an unshaded material of the correct colour set to never receive shadows.
Disabling depth write on those shouldn't effect them though, correct? Or do you need depth to create some kind of volume effect?
If I disable depth write on them then things behind them (for example the floor if looking down) will get drawn over them… and even if the floor were drawn first for some reason that means they would get shadowed as though they were at the floor position.
@t0neg0d:
I have a question…is your name:
“tone god”, “t one god”, “t zero neg zero d”
or something else entirely?
@zarch said:
If I disable depth write on them then things behind them (for example the floor if looking down) will get drawn over them... and even if the floor were drawn first for some reason that means they would get shadowed as though they were at the floor position.
There not in the opaque bucket, I take it?
@nehon
Not to be a pest... but can you run me through a quick overview of how the new process works?
The pre shadow pass still renders depth from the lights PoV, yes?
Is it still only passed those objects that are casting shadows?
You said "This filter reconstruct the fragment position". What's it reconstructing this from? The depth texture of the pre shadow pass? or?
@zarch said:
@t0neg0d:
I have a question...is your name:
"tone god", "t one god", "t zero neg zero d"
or something else entirely?
tone god... I guess goddess woulda been more appropriate... but that's way too much shit to type. It's referring to the amp I use. I play through a 1971 Marshall JMP Mark II 50 watt lead.... yuummmmm. Actually... goddess isn't really more appropriate... the amp isn't male or female.
tone amp. Ok
They are opaque. Why wouldn’t they be?
Because! Hah… I have no idea. Are they light “cones”? Like you see from street lights when it foggy outside? Semi-transparent? If so… I wanna see a screen shot. I’ve been trying to figure out a good way of rendering these.
wow… foggy is a word >.< It really shouldn’t be.
Foggy is a word - of course it should be
No, they are lights as in the actual light bulb glowing bit that emits light.
@nehon said:
So i made some experimentation with this and the results are very interesting.
All of what's coming is not committed (and may never be) and is still in a WIP stage.
So i made some changes in the PSSMShadowProcessor to have the post shadow pass as a post filter. The ShadowProcessor initialize a Filter that is then passed to the FilterPostProcessor.
This filter reconstruct the fragment position in worldspace (not view space in the end) and the shadow computation are done according to this position.
Computing the shadowTexcoord in now done per pixel instead of per vertex though and everything that write depth receive shadows (making the Recieve shadow mode useless).
The good new is that it is significantly faster when you have a fair amount of shadowed objects in the scene.
I made a test case, that is the worst case scenario for PSSM. Lot of objects, very close to one another, 4 splits and 1024 (1024 could be worst but nvm) filtering is PCF4.
1 new object is added every second, from 0 to 300. I made some perf bench with the classic way of rendering shadows and the post filter one.
Here is a screenshot of the scene :
http://i.imgur.com/P2BZb.jpg
And here is a graph of how FPS vary with the 2 approaches while adding objects to the scenes.
here is a link to the google spread sheet
https://docs.google.com/spreadsheet/ccc?key=0AsE_ydpoOkOhdF9MRjh4cUo1T3gwby1kaU1lcDhIX1E&pli=1#gid=1
I put a logarithmic scale for the FPS so that the graph is readable.
As you can see the classic approach is faster until you have around 10 objects in the scene...then the post filtered one becomes faster.
In the end with 300 objects i have around 60 fps with the classic approach and around 90 with the post filtered approach.
The filter has some draw backs, but it would be a solid base to implement temporal reprojection.
Then I'd like to test how we could put the shadow calculation in the main render pass, i guess it would be a lot faster too.
What happens with the objects hidden in viewpace? (Behind some other objects) Do they simply no cast shadows (which would cause lot's of artifacts in real game scenes) or have you found a way to keep track of them?
@t0neg0d said:
The pre shadow pass still renders depth from the lights PoV, yes?
Is it still only passed those objects that are casting shadows?
You said "This filter reconstruct the fragment position". What's it reconstructing this from? The depth texture of the pre shadow pass? or?
The pre shadow pass is exactly the same, casting objects are rendered to the shadow map from the light point of view.
The difference is only in the post pass
For the classic way, a full geometry pass is done on shadow recieving objects, by forcing the post shadow technique. The shadows are blended over the existing render (modulate mode, which basically means the color is multiplied by the shadow value).
For the post filter shadows, the post pass is a full screen pass, so basically the only geometry sent to the gpu is a full screen quad.
I use the depth buffer of the scene to reconstruct the world position in world space : you have non linear depth, that can be easily transformed to z in projection space, then you have the texture coordinates of the quad that can be transformed to x,y coords of the fragment in projection space.
once you have x,y,z in projection space you multiply by the inverse view projection matrix and you end up with position of the fragment in world space.
From this you can compute the projected texture coordinates (biasmat*lightViewMatrix*worldpos), then you just have to make regular shadow compares.
@zzuegg said:
What happens with the objects hidden in viewpace? (Behind some other objects) Do they simply no cast shadows (which would cause lot's of artifacts in real game scenes) or have you found a way to keep track of them?
No, this is only the recieve pass. If an object is entirely occluded by another object there are no shadow to be drawn on it.
The pre pass is still the same
@nehon said:
The pre shadow pass is exactly the same, casting objects are rendered to the shadow map from the light point of view.
The difference is only in the post pass
For the classic way, a full geometry pass is done one shadow recieving objects, by forcing the post shadow technique. The shadows are blended over the existing render (modulate mode, which basically means the color is multiplied by the shadow value).
For the post filter shadows, the post pass is a full screen pass, so basically the only geometry sent to the gpu is a full screen quad.
I use the depth buffer of the scene to reconstruct the world position in world space : you have non linear depth, that can be easily transformed to z in projection space, then you have the texture coordinates of the quad that can be transformed to x,y coords of the fragment in projection space.
once you have x,y,z in projection space you multiply by the inverse view projection matrix and you end up with position of the fragment in world space.
From this you can compute the projected texture coordinates (biasmat*lightViewMatrix*worldpos), then you just have to make regular shadow compares.
Ninja'ed and even respont to my answer without knowing the questions. Ninja++