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; } void setShadowMapProjectionHint(ShadowMapProjectionHint hint) { _shadowMapProjectionHint = hint; }
ShadowMapProjectionHint getShadowMapProjectionHint() const { return _shadowMapProjectionHint; } 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 enum ShaderHint
{ {
NO_SHADERS, NO_SHADERS,
@ -233,6 +242,7 @@ protected:
double _minimumShadowMapNearFarRatio; double _minimumShadowMapNearFarRatio;
ShadowMapProjectionHint _shadowMapProjectionHint; ShadowMapProjectionHint _shadowMapProjectionHint;
double _perspectiveShadowMapCutOffAngle;
ShaderHint _shaderHint; ShaderHint _shaderHint;
bool _debugDraw; bool _debugDraw;

View File

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