diff --git a/include/osgShadow/ViewDependentShadowMap b/include/osgShadow/ViewDependentShadowMap new file mode 100644 index 000000000..ff7402558 --- /dev/null +++ b/include/osgShadow/ViewDependentShadowMap @@ -0,0 +1,107 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + +#ifndef OSGSHADOW_VIEWDEPENDENTSHADOWMAP +#define OSGSHADOW_VIEWDEPENDENTSHADOWMAP 1 + +#include +#include +#include +#include + +#include + +namespace osgShadow { + +/** ViewDependentShadowMap provides an base implementation of view dependent shadow mapping techniques.*/ +class OSGSHADOW_EXPORT ViewDependentShadowMap : public ShadowTechnique +{ + public : + ViewDependentShadowMap(); + + ViewDependentShadowMap(const ViewDependentShadowMap& vdsm, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); + + META_Object(osgShadow, ViewDependentShadowMap); + + /** initialize the ShadowedScene and local cached data structures.*/ + virtual void init(); + + /** run the update traversal of the ShadowedScene and update any loca chached data structures.*/ + virtual void update(osg::NodeVisitor& nv); + + /** run the cull traversal of the ShadowedScene and set up the rendering for this ShadowTechnique.*/ + virtual void cull(osgUtil::CullVisitor& cv); + + /** Clean scene graph from any shadow technique specific nodes, state and drawables.*/ + virtual void cleanSceneGraph(); + + struct OSGSHADOW_EXPORT LightShadowData : public osg::Referenced + { + unsigned int _textureUnit; + osg::ref_ptr _texture; + osg::ref_ptr _texgen; + + osg::ref_ptr _light; + osg::ref_ptr _camera; + }; + + class OSGSHADOW_EXPORT ViewDependentData : public osg::Referenced + { + public: + ViewDependentData(ViewDependentShadowMap* vdsm, osgUtil::CullVisitor* cv); + + + + void cullShadowCastingScene(osgUtil::CullVisitor* cv); + + void cull(osgUtil::CullVisitor*); + + protected: + virtual ~ViewDependentData() {} + + osg::ref_ptr _stateset; + }; + + virtual ViewDependentData* createViewDependentData(osgUtil::CullVisitor* cv); + + ViewDependentData* getViewDependentData(osgUtil::CullVisitor* cv); + + + typedef std::pair< osg::ref_ptr, osg::ref_ptr > PositionedLight; + typedef std::list< PositionedLight > PositionedLightList; + + virtual bool selectActiveLights(osgUtil::CullVisitor* cv, PositionedLightList& pll) const; + + virtual osg::Polytope computeLightViewFrustumPolytope(osgUtil::CullVisitor* cv, PositionedLight& positionedLight); + + virtual bool computeShadowCameraSettings(PositionedLight& positionedLight, osg::Polytope& polytope, osg::Camera* camera); + + virtual bool assignTexGenSettings(osgUtil::CullVisitor* cv, osg::Camera* camera, unsigned int textureUnit, osg::TexGen* texgen); + + virtual void cullShadowReceivingScene(osgUtil::CullVisitor* cv, osg::StateSet* stateset) const; + + virtual void cullShadowCastingScene(osgUtil::CullVisitor* cv, osg::Camera* camera) const; + + +protected: + virtual ~ViewDependentShadowMap(); + + typedef std::map< osgUtil::CullVisitor*, osg::ref_ptr > ViewDependentDataMap; + OpenThreads::Mutex _viewDependentDataMapMutex; + ViewDependentDataMap _viewDependentDataMap; + +}; + +} + +#endif diff --git a/src/osgShadow/CMakeLists.txt b/src/osgShadow/CMakeLists.txt index a6458e181..40cee5de4 100644 --- a/src/osgShadow/CMakeLists.txt +++ b/src/osgShadow/CMakeLists.txt @@ -27,6 +27,7 @@ SET(TARGET_H ${HEADER_PATH}/ProjectionShadowMap ${HEADER_PATH}/StandardShadowMap ${HEADER_PATH}/ViewDependentShadowTechnique + ${HEADER_PATH}/ViewDependentShadowMap ) # FIXME: For OS X, need flag for Framework or dylib @@ -48,6 +49,7 @@ SET(TARGET_SRC MinimalShadowMap.cpp StandardShadowMap.cpp ViewDependentShadowTechnique.cpp + ViewDependentShadowMap.cpp ${OPENSCENEGRAPH_VERSIONINFO_RC} ) diff --git a/src/osgShadow/ViewDependentShadowMap.cpp b/src/osgShadow/ViewDependentShadowMap.cpp new file mode 100644 index 000000000..be95071ca --- /dev/null +++ b/src/osgShadow/ViewDependentShadowMap.cpp @@ -0,0 +1,476 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + +#include +#include +#include + +using namespace osgShadow; + +/////////////////////////////////////////////////////////////////////////////////////////////// +// +// ViewDependentShadowMap +// +ViewDependentShadowMap::ViewDependentShadowMap(): + ShadowTechnique() +{ +} + +ViewDependentShadowMap::ViewDependentShadowMap(const ViewDependentShadowMap& vdsm, const osg::CopyOp& copyop): + ShadowTechnique(vdsm,copyop) +{ +} + +ViewDependentShadowMap::~ViewDependentShadowMap() +{ +} + + +void ViewDependentShadowMap::init() +{ + if (!_shadowedScene) return; + + OSG_NOTICE<<"ViewDependentShadowMap::init()"< lock(_viewDependentDataMapMutex); + ViewDependentDataMap::iterator itr = _viewDependentDataMap.find(cv); + if (itr!=_viewDependentDataMap.end()) return itr->second.get(); + + osg::ref_ptr vdd = createViewDependentData(cv); + _viewDependentDataMap[cv] = vdd; + return vdd.release(); +} + +void ViewDependentShadowMap::update(osg::NodeVisitor& nv) +{ + OSG_NOTICE<<"ViewDependentShadowMap::update(osg::NodeVisitor& "<<&nv<<")"<osg::Group::traverse(nv); +} + +void ViewDependentShadowMap::cull(osgUtil::CullVisitor& cv) +{ + OSG_NOTICE<<"ViewDependentShadowMap::cull(osg::CullVisitor&"<<&cv<<")"<getRenderStage(); + + osgUtil::PositionalStateContainer::AttrMatrixList& aml = + rs->getPositionalStateContainer()->getAttrMatrixList(); + + for(osgUtil::PositionalStateContainer::AttrMatrixList::iterator itr = aml.begin(); + itr != aml.end(); + ++itr) + { + const osg::Light* light = dynamic_cast(itr->first.get()); + if (light) + { + pll.push_back(PositionedLight(itr->second, light)); + } + } + + return !pll.empty(); +} + +osg::Polytope ViewDependentShadowMap::computeLightViewFrustumPolytope(osgUtil::CullVisitor* cv, PositionedLight& positionedLight) +{ + OSG_NOTICE<<"computeLightViewFrustumPolytope()"<getProjectionMatrix()) ); + osg::Matrix modelViewMatrix( *(cv->getModelViewMatrix()) ); + + OSG_NOTICE<<"Projection matrix "<getCalculatedNearPlane(); + osgUtil::CullVisitor::value_type zFar = cv->getCalculatedFarPlane(); + + cv->clampProjectionMatrix(projectionMatrix,zNear,zFar); + + OSG_NOTICE<<"zNear = "< Vertices; + Vertices corners(8); + + corners[0].set(-1.0,-1.0,-1.0); + corners[1].set(1.0,-1.0,-1.0); + corners[2].set(1.0,-1.0,1.0); + corners[3].set(-1.0,-1.0,1.0); + corners[4].set(-1.0,1.0,-1.0); + corners[5].set(1.0,1.0,-1.0); + corners[6].set(1.0,1.0,1.0); + corners[7].set(-1.0,1.0,1.0); + + osg::Matrixd clipToWorld; + clipToWorld.invert(modelViewMatrix * projectionMatrix); + + osg::Vec3d center( osg::Vec3d(0.0,0.0,0.0) * clipToWorld ); + + for(Vertices::iterator itr = corners.begin(); + itr != corners.end(); + ++itr) + { + *itr = (*itr) * clipToWorld; + OSG_NOTICE<<" corner "<<*itr< Indices; + typedef std::vector Faces; + Faces faces(6); + + faces[0].push_back(0); + faces[0].push_back(3); + faces[0].push_back(7); + faces[0].push_back(4); + + faces[1].push_back(1); + faces[1].push_back(5); + faces[1].push_back(6); + faces[1].push_back(2); + + faces[2].push_back(0); + faces[2].push_back(1); + faces[2].push_back(2); + faces[2].push_back(3); + + faces[3].push_back(4); + faces[3].push_back(7); + faces[3].push_back(6); + faces[3].push_back(5); + + faces[4].push_back(0); + faces[4].push_back(4); + faces[4].push_back(5); + faces[4].push_back(1); + + faces[5].push_back(2); + faces[5].push_back(6); + faces[5].push_back(7); + faces[5].push_back(3); + + typedef std::vector Edges; + Edges edges(12); + edges[0].push_back(0); edges[0].push_back(1); // corner points on edge + edges[0].push_back(2); edges[0].push_back(4); // faces on edge + + edges[1].push_back(1); edges[1].push_back(2); // corner points on edge + edges[1].push_back(2); edges[1].push_back(1); // faces on edge + + edges[2].push_back(2); edges[2].push_back(3); // corner points on edge + edges[2].push_back(2); edges[2].push_back(5); // faces on edge + + edges[3].push_back(3); edges[3].push_back(0); // corner points on edge + edges[3].push_back(2); edges[3].push_back(0); // faces on edge + + + edges[4].push_back(0); edges[4].push_back(4); // corner points on edge + edges[4].push_back(0); edges[4].push_back(4); // faces on edge + + edges[5].push_back(1); edges[5].push_back(5); // corner points on edge + edges[5].push_back(4); edges[5].push_back(1); // faces on edge + + edges[6].push_back(2); edges[6].push_back(6); // corner points on edge + edges[6].push_back(1); edges[6].push_back(5); // faces on edge + + edges[7].push_back(3); edges[7].push_back(7); // corner points on edge + edges[7].push_back(5); edges[7].push_back(0); // faces on edge + + + edges[8].push_back(4); edges[8].push_back(5); // corner points on edge + edges[8].push_back(3); edges[8].push_back(4); // faces on edge + + edges[9].push_back(5); edges[9].push_back(6); // corner points on edge + edges[9].push_back(3); edges[9].push_back(1); // faces on edge + + edges[10].push_back(6);edges[10].push_back(7); // corner points on edge + edges[10].push_back(3);edges[10].push_back(5); // faces on edge + + edges[11].push_back(7); edges[11].push_back(4); // corner points on edge + edges[11].push_back(3); edges[11].push_back(0); // faces on edge + + + osg::Polytope polytope; + polytope.setToUnitFrustum(); + + polytope.transformProvidingInverse( projectionMatrix ); + polytope.transformProvidingInverse( modelViewMatrix ); + + osg::Polytope lightVolumePolytope; + + + osg::Vec4d lightPos = positionedLight.second->getPosition(); + osg::Vec3d lightPos3(lightPos.x(), lightPos.y(), lightPos.z()); + osg::Vec3d lightDir; + bool directionalLight = (lightPos.w()== 0.0); + if (directionalLight) + { + lightDir.set(-lightPos.x(), -lightPos.y(), -lightPos.z()); + lightDir.normalize(); + OSG_NOTICE<<" Directional light, lightPos="<getTraversalMask(); + + cv->setTraversalMask( traversalMask & _shadowedScene->getReceivesShadowTraversalMask() ); + + if (stateset) cv->pushStateSet( stateset ); + + _shadowedScene->osg::Group::traverse(*cv); + + if (stateset) cv->popStateSet(); + + cv->setTraversalMask( traversalMask ); + + return; +} + +void ViewDependentShadowMap::cullShadowCastingScene(osgUtil::CullVisitor* cv, osg::Camera* camera) const +{ + OSG_NOTICE<<"cullShadowCastingScene()"<getTraversalMask(); + + cv->setTraversalMask( traversalMask & _shadowedScene->getCastsShadowTraversalMask() ); + + if (camera) camera->accept(*cv); + + cv->setTraversalMask( traversalMask ); + + return; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////// +// +// ViewDependentData +// +ViewDependentShadowMap::ViewDependentData::ViewDependentData(ViewDependentShadowMap* vdsm, osgUtil::CullVisitor* cv) +{ + OSG_NOTICE<<"ViewDependentData::ViewDependentData("<