As you suspect, this is not a bug. PSSM is not a performance optimization, but rather a quality improvement.
That being said, there's things that could be added to Ogre to improve the situation.
This post explains how PSSM
Ogre 1.x used LiPSM
on top of PSSM. I got rid of it in Ogre 2.0 because:
- Our implementation was glitchy. It was showing errors the original demo just did not exhibit
- LiPSM has terrible quality degradation on its edge cases, which happens to be the same edge cases as PSSM (i.e. it didn't improve PSSM where it mattered the most)
But as you said, there are things that can be done to improve performance of the shadow maps. One is very simple but I never put thought into it:
1. Roll the shadow map camera. The shadow map camera's orientation is set in CompositorShadowNode::_update:
Code: Select all
if( light->getType() != Light::LT_POINT )
texCamera->setOrientation( light->getParentNode()->_getDerivedOrientation() );
texCamera->setOrientation( Quaternion::IDENTITY );
However there is no reason for directional lights to keep the roll of the rotation to improve things. The frustum of the camera from the light's perspective should look approx like this:
Red is first split, blue is second split (I'm simplifying it to two splits, but applies to any number of splits)
It is no wonder the last split contains the whole thing, because the square must be enlarged enough, and that includes a lot of wasted space.
This could be improved if we simply rolled the camera:
and then we simply scale it:
I haven't put much thought on how to figure out the required roll for directional lights, but if you're willing to try, do some math and ultimately your code would boilt to:
Code: Select all
shadowCamera->setOrientation( shadowCamera->getOrientation() * rollQuat ):
shadowCamera->setOrthoWindow( tighter_bounds_than_before );
This solution requires no projection matrix fiddling, improves quality; but as a disadvantage shadow quality may swim/flicker as you rotate the camera (because the shadow map camera keeps changing its roll instead of staying stationary)
2. Alternatively, you could use enableCustomNearClipPlane. This was thought for planar reflections but it should work here as well.
Going back to the original example, there is a custom clipping plane, and objects behind that plane should not be rendered (in yellow):
Use enableCustomNearClipPlane for that yellow plane, and if all things work correctly, objects behind it will not be rendered and performance should go up.
Basically this is your idea of "making the projection oblique".
Advantages: Should be stable regardless of camera rotation (unlike previous method)
Disadvantages: Quality does not improve as the waste will still be there, custom near clip plane sacrifices depth buffer precision so there could be more shadow acne and stuff like that.
My time is limited so I haven't had the time to fight with neither of these techniques. Anyone is welcome to try them and tell us the results!