diff --git a/src/osgShadow/ViewDependentShadowMap.cpp b/src/osgShadow/ViewDependentShadowMap.cpp index 531841ce7..8c96a6de8 100644 --- a/src/osgShadow/ViewDependentShadowMap.cpp +++ b/src/osgShadow/ViewDependentShadowMap.cpp @@ -34,6 +34,74 @@ static const char fragmentShaderSource_withBaseTexture[] = " gl_FragColor = color; \n" "} \n"; + +template +class RenderLeafTraverser : public T +{ +public: + + RenderLeafTraverser() + { + } + + void traverse(const osgUtil::RenderStage* rs) + { + traverse(static_cast(rs)); + } + + void traverse(const osgUtil::RenderBin* renderBin) + { + const osgUtil::RenderBin::RenderBinList& rbl = renderBin->getRenderBinList(); + for(osgUtil::RenderBin::RenderBinList::const_iterator itr = rbl.begin(); + itr != rbl.end(); + ++itr) + { + traverse(itr->second.get()); + } + + const osgUtil::RenderBin::RenderLeafList& rll = renderBin->getRenderLeafList(); + for(osgUtil::RenderBin::RenderLeafList::const_iterator itr = rll.begin(); + itr != rll.end(); + ++itr) + { + handle(*itr); + } + + const osgUtil::RenderBin::StateGraphList& rgl = renderBin->getStateGraphList(); + for(osgUtil::RenderBin::StateGraphList::const_iterator itr = rgl.begin(); + itr != rgl.end(); + ++itr) + { + traverse(*itr); + } + + } + + void traverse(const osgUtil::StateGraph* stateGraph) + { + const osgUtil::StateGraph::ChildList& cl = stateGraph->_children; + for(osgUtil::StateGraph::ChildList::const_iterator itr = cl.begin(); + itr != cl.end(); + ++itr) + { + traverse(itr->second.get()); + } + + const osgUtil::StateGraph::LeafList& ll = stateGraph->_leaves; + for(osgUtil::StateGraph::LeafList::const_iterator itr = ll.begin(); + itr != ll.end(); + ++itr) + { + handle(itr->get()); + } + } + + inline void handle(const osgUtil::RenderLeaf* renderLeaf) + { + this->operator()(renderLeaf); + } +}; + /////////////////////////////////////////////////////////////////////////////////////////////// // // VDSMCameraCullCallback @@ -489,6 +557,10 @@ void ViewDependentShadowMap::cull(osgUtil::CullVisitor& cv) OSG_INFO<<"cv->getProjectionMatrix()="<<*cv.getProjectionMatrix()<setAttribute( new osg::CullFace( osg::CullFace::FRONT ), - osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE ); + _shadowCastingStateSet->setAttribute( new osg::CullFace( osg::CullFace::FRONT ), + osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE ); - // make sure GL_CULL_FACE is off by default - // we assume that if object has cull face attribute set to back - // it will also set cull face mode ON so no need for override - _shadowCastingStateSet->setMode( GL_CULL_FACE, osg::StateAttribute::OFF ); -#endif + // make sure GL_CULL_FACE is off by default + // we assume that if object has cull face attribute set to back + // it will also set cull face mode ON so no need for override + _shadowCastingStateSet->setMode( GL_CULL_FACE, osg::StateAttribute::OFF ); + } #if 1 float factor = 1.1; @@ -1026,43 +1102,306 @@ bool ViewDependentShadowMap::perspectiveShadowMapCameraSettings(Frustum& frustum return adjustPerspectiveShadowMapCameraSettings(0, frustum, positionedLight, camera); } -struct RenderLeafIterator +struct ConvexHull { - RenderLeafIterator() + typedef std::vector Vertices; + typedef std::pair< osg::Vec3d, osg::Vec3d > Edge; + typedef std::list< Edge > Edges; + + Edges _edges; + + void setToFrustum(ViewDependentShadowMap::Frustum& frustum) { + _edges.push_back( Edge(frustum.corners[0],frustum.corners[1]) ); + _edges.push_back( Edge(frustum.corners[1],frustum.corners[2]) ); + _edges.push_back( Edge(frustum.corners[2],frustum.corners[3]) ); + _edges.push_back( Edge(frustum.corners[3],frustum.corners[0]) ); + + _edges.push_back( Edge(frustum.corners[4],frustum.corners[5]) ); + _edges.push_back( Edge(frustum.corners[5],frustum.corners[6]) ); + _edges.push_back( Edge(frustum.corners[6],frustum.corners[7]) ); + _edges.push_back( Edge(frustum.corners[7],frustum.corners[4]) ); + + _edges.push_back( Edge(frustum.corners[0],frustum.corners[4]) ); + _edges.push_back( Edge(frustum.corners[1],frustum.corners[5]) ); + _edges.push_back( Edge(frustum.corners[2],frustum.corners[6]) ); + _edges.push_back( Edge(frustum.corners[3],frustum.corners[7]) ); + } + + void transform(const osg::Matrixd& m) + { + for(Edges::iterator itr = _edges.begin(); + itr != _edges.end(); + ++itr) + { + itr->first = itr->first * m; + itr->second = itr->second * m; + } + } + + void clip(const osg::Plane& plane) + { + // OSG_NOTICE<<"clip("<=0.0 && d1>=0.0) + { + // OSG_NOTICE<<" Edge completely inside"<first; + osg::Vec3d& v1 = itr->second; + osg::Vec3d intersection = v0 - (v1-v0)*(d0/(d1-d0)); + // OSG_NOTICE<<" Edge across clip plane, v0="<m) m = ratio; + + delta = edge.second-eye; + ratio = delta[index]/delta[1]; + if (ratio>m) m = ratio; + } + return m; } - void handle(osgUtil::RenderLeaf* renderLeaf) + void output(std::ostream& out) { - OSG_NOTICE<<"handle("<_modelview.get()!=previous_modelview) + { + previous_modelview = renderLeaf->_modelview.get(); + light_mvp.mult(*renderLeaf->_modelview, light_vp); + //OSG_NOTICE<<"Computing new light_mvp "<_drawable->getBound(); + if (bb.valid()) + { + handle(osg::Vec3d(bb.xMin(),bb.yMin(),bb.zMin())); + handle(osg::Vec3d(bb.xMax(),bb.yMin(),bb.zMin())); + handle(osg::Vec3d(bb.xMin(),bb.yMax(),bb.zMin())); + handle(osg::Vec3d(bb.xMax(),bb.yMax(),bb.zMin())); + handle(osg::Vec3d(bb.xMin(),bb.yMin(),bb.zMax())); + handle(osg::Vec3d(bb.xMax(),bb.yMin(),bb.zMax())); + handle(osg::Vec3d(bb.xMin(),bb.yMax(),bb.zMax())); + handle(osg::Vec3d(bb.xMax(),bb.yMax(),bb.zMax())); + } + else + { + //OSG_NOTICE<<"bb invalid"<n) + { + x_ratio = delta.x()/delta.y(); + z_ratio = delta.z()/delta.y(); + } + else + { + x_ratio = delta.x()/n; + z_ratio = delta.z()/n; + } + + if (x_ratiomax_x_ratio) max_x_ratio = x_ratio; + if (z_ratiomax_z_ratio) max_z_ratio = z_ratio; + + // clip to the light space + if (ls.x()clip_max_x) ls.x()=clip_max_x; + if (ls.y()clip_max_y) ls.y()=clip_max_y; + if (ls.z()clip_max_z) ls.z()=clip_max_z; + + // compute the xyz range. + if (ls.x()max_x) max_x=ls.x(); + if (ls.y()max_y) max_y=ls.y(); + if (ls.z()max_z) max_z=ls.z(); + } + + osg::Matrixd light_vp; + osg::Vec3d eye_ls; + double n; + + osg::Matrixd light_mvp; + osg::RefMatrix* previous_modelview; + unsigned int numLeaves; + + double clip_min_x, clip_max_x; + double clip_min_y, clip_max_y; + double clip_min_z, clip_max_z; + + double clip_min_x_ratio, clip_max_x_ratio; + double clip_min_z_ratio, clip_max_z_ratio; + + double min_x_ratio, max_x_ratio; + double min_z_ratio, max_z_ratio; + double min_x, max_x; + double min_y, max_y; + double min_z, max_z; +}; + bool ViewDependentShadowMap::adjustPerspectiveShadowMapCameraSettings(osgUtil::RenderStage* renderStage, Frustum& frustum, LightData& positionedLight, osg::Camera* camera) { - if (renderStage) - { - RenderLeafIterator rli; - //rli.traverse(renderStage); - } - //frustum.projectionMatrix; //frustum.modelViewMatrix; @@ -1074,6 +1413,65 @@ bool ViewDependentShadowMap::adjustPerspectiveShadowMapCameraSettings(osgUtil::R //OSG_NOTICE<<"light_v="<setProjectionMatrix(light_p); + //return true; + } + + osg::Vec3d eye_v = frustum.eye * light_v; osg::Vec3d centerNearPlane_v = frustum.centerNearPlane * light_v; osg::Vec3d center_v = frustum.center * light_v; @@ -1084,7 +1482,7 @@ bool ViewDependentShadowMap::adjustPerspectiveShadowMapCameraSettings(osgUtil::R double standardShadowMapToleranceAngle = 2.0; if (gamma_vosg::DegreesToRadians(180-standardShadowMapToleranceAngle)) { - OSG_NOTICE<<"Light and view vectors near parrallel - use standard shadow map."<max_y) max_y = c_ls.y(); - // OSG_NOTICE<<" corner light space "<