Added s/getPerspectiveShadowMapCutOffAngle() and use of this when setting up light space to avoid sigularaties when

the light and view directions are co-incident.
This commit is contained in:
Robert Osfield 2011-09-06 10:12:45 +00:00
parent 15ad6eda63
commit f83722d62b
2 changed files with 36 additions and 14 deletions

View File

@ -177,6 +177,15 @@ class OSGSHADOW_EXPORT ViewDependentShadowMap : public ShadowTechnique
void setShadowMapProjectionHint(ShadowMapProjectionHint hint) { _shadowMapProjectionHint = hint; }
ShadowMapProjectionHint getShadowMapProjectionHint() const { return _shadowMapProjectionHint; }
/** Set the cut off angle, in degrees, between the light direction and the view direction
* that determines whether perspective shadow mapping is appropriate, or thar orthographic shadow
* map should be used instead. Default is 2 degrees so that for any angle greater than 2 degrees
* perspective shadow map will be used, and any angle less than 2 degrees orthographic shadow map
* will be used. Note, if ShadowMapProjectionHint is set to ORTHOGRAPHIC_SHADOW_MAP then an
* orthographic shadow map will always be used.*/
void setPerspectiveShadowMapCutOffAngle(double angle) { _perspectiveShadowMapCutOffAngle = angle; }
double getPerspectiveShadowMapCutOffAngle() const { return _perspectiveShadowMapCutOffAngle; }
enum ShaderHint
{
NO_SHADERS,
@ -233,6 +242,7 @@ protected:
double _minimumShadowMapNearFarRatio;
ShadowMapProjectionHint _shadowMapProjectionHint;
double _perspectiveShadowMapCutOffAngle;
ShaderHint _shaderHint;
bool _debugDraw;

View File

@ -526,6 +526,7 @@ ViewDependentShadowMap::ViewDependentShadowMap():
_textureSize(2048,2048),
_minimumShadowMapNearFarRatio(0.01),
_shadowMapProjectionHint(PERSPECTIVE_SHADOW_MAP),
_perspectiveShadowMapCutOffAngle(2.0),
_shaderHint(NO_SHADERS),
// _shaderHint(PROVIDE_FRAGMENT_SHADER),
_debugDraw(false)
@ -539,6 +540,7 @@ ViewDependentShadowMap::ViewDependentShadowMap(const ViewDependentShadowMap& vds
_textureSize(vdsm._textureSize),
_minimumShadowMapNearFarRatio(vdsm._minimumShadowMapNearFarRatio),
_shadowMapProjectionHint(vdsm._shadowMapProjectionHint),
_perspectiveShadowMapCutOffAngle(vdsm._perspectiveShadowMapCutOffAngle),
_shaderHint(vdsm._shaderHint),
_debugDraw(vdsm._debugDraw)
{
@ -1040,21 +1042,32 @@ bool ViewDependentShadowMap::computeShadowCameraSettings(Frustum& frustum, Light
{
OSG_INFO<<"standardShadowMapCameraSettings()"<<std::endl;
#if 0
// compute the basis vectors for the light coordinate frame
osg::Vec3d lightSide_y = positionedLight.lightDir ^ osg::Vec3d(0.0,1.0,0.0);
osg::Vec3d lightSide_z = positionedLight.lightDir ^ osg::Vec3d(0.0,0.0,1.0);
osg::Vec3d lightSide = (lightSide_y.length() > lightSide_z.length()) ? lightSide_y : lightSide_z;
lightSide.normalize();
#else
osg::Vec3d lightSide = positionedLight.lightDir ^ frustum.frustumCenterLine; lightSide.normalize();
#endif
osg::Vec3d lightSide;
double dotProduct_v = positionedLight.lightDir * frustum.frustumCenterLine;
double gamma_v = acos(dotProduct_v);
if (gamma_v<osg::DegreesToRadians(_perspectiveShadowMapCutOffAngle) || gamma_v>osg::DegreesToRadians(180.0-_perspectiveShadowMapCutOffAngle))
{
OSG_INFO<<"View direction and Light direction below tolerance"<<std::endl;
osg::Vec3d viewSide = osg::Matrixd::transform3x3(frustum.modelViewMatrix, osg::Vec3d(1.0,0.0,0.0));
lightSide = positionedLight.lightDir ^ (viewSide ^ positionedLight.lightDir);
lightSide.normalize();
}
else
{
lightSide = positionedLight.lightDir ^ frustum.frustumCenterLine;
lightSide.normalize();
}
osg::Vec3d lightUp = lightSide ^ positionedLight.lightDir;
OSG_INFO<<"positionedLight.lightDir="<<positionedLight.lightDir<<std::endl;
OSG_INFO<<"lightSide="<<lightSide<<std::endl;
OSG_INFO<<"lightUp="<<lightUp<<std::endl;
#if 0
OSG_NOTICE<<"positionedLight.lightDir="<<positionedLight.lightDir<<std::endl;
OSG_NOTICE<<"lightSide="<<lightSide<<std::endl;
OSG_NOTICE<<"lightUp="<<lightUp<<std::endl;
#endif
if (positionedLight.directionalLight)
{
double xMin=0.0, xMax=0.0;
@ -1586,8 +1599,7 @@ bool ViewDependentShadowMap::adjustPerspectiveShadowMapCameraSettings(osgUtil::R
double dotProduct_v = lightdir * viewdir_v;
double gamma_v = acos(dotProduct_v);
double standardShadowMapToleranceAngle = 2.0;
if (gamma_v<osg::DegreesToRadians(standardShadowMapToleranceAngle) || gamma_v>osg::DegreesToRadians(180-standardShadowMapToleranceAngle))
if (gamma_v<osg::DegreesToRadians(_perspectiveShadowMapCutOffAngle) || gamma_v>osg::DegreesToRadians(180-_perspectiveShadowMapCutOffAngle))
{
// OSG_NOTICE<<"Light and view vectors near parrallel - use standard shadow map."<<std::endl;
return true;