Imorovements to the new perspective/lispsm style shadow implementation.

This commit is contained in:
Robert Osfield
2011-08-24 12:32:03 +00:00
parent 3db0557ed5
commit 622cfb524c

View File

@@ -34,6 +34,74 @@ static const char fragmentShaderSource_withBaseTexture[] =
" gl_FragColor = color; \n"
"} \n";
template<class T>
class RenderLeafTraverser : public T
{
public:
RenderLeafTraverser()
{
}
void traverse(const osgUtil::RenderStage* rs)
{
traverse(static_cast<const osgUtil::RenderBin*>(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()<<std::endl;
osg::CullSettings::ComputeNearFarMode cachedNearFarMode = cv.getComputeNearFarMode();
#if 1
cv.setComputeNearFarMode(osg::CullSettings::COMPUTE_NEAR_FAR_USING_PRIMITIVES);
#endif
// 1. Traverse main scene graph
cv.pushStateSet( _shadowRecievingPlaceholderStateSet.get() );
@@ -502,7 +574,10 @@ void ViewDependentShadowMap::cull(osgUtil::CullVisitor& cv)
// are all done correctly.
cv.computeNearPlane();
// return compute near far mode back to it's original settings
cv.setComputeNearFarMode(cachedNearFarMode);
// 2. select active light sources
// create a list of light sources + their matrices to place them
selectActiveLights(&cv, vdd);
@@ -691,23 +766,24 @@ void ViewDependentShadowMap::createShaders()
_shadowCastingStateSet = new osg::StateSet;
#if 1
// note soft (attribute only no mode override) setting. When this works ?
// 1. for objects prepared for backface culling
// because they usually also set CullFace and CullMode on in their state
// For them we override CullFace but CullMode remains set by them
// 2. For one faced, trees, and similar objects which cannot use
// backface nor front face so they usually use CullMode off set here.
// In this case we will draw them in their entirety.
if (!_debugDraw)
{
// note soft (attribute only no mode override) setting. When this works ?
// 1. for objects prepared for backface culling
// because they usually also set CullFace and CullMode on in their state
// For them we override CullFace but CullMode remains set by them
// 2. For one faced, trees, and similar objects which cannot use
// backface nor front face so they usually use CullMode off set here.
// In this case we will draw them in their entirety.
_shadowCastingStateSet->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<osg::Vec3d> 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("<<plane<<") edges.size()="<<_edges.size()<<std::endl;
for(Edges::iterator itr = _edges.begin();
itr != _edges.end();
)
{
double d0 = plane.distance(itr->first);
double d1 = plane.distance(itr->second);
if (d0<0.0 && d1<0.0)
{
// OSG_NOTICE<<" Edge completely outside, removing"<<std::endl;
Edges::iterator to_delete_itr = itr;
++itr;
_edges.erase(to_delete_itr);
}
else if (d0>=0.0 && d1>=0.0)
{
// OSG_NOTICE<<" Edge completely inside"<<std::endl;
++itr;
}
else
{
osg::Vec3d& v0 = itr->first;
osg::Vec3d& v1 = itr->second;
osg::Vec3d intersection = v0 - (v1-v0)*(d0/(d1-d0));
// OSG_NOTICE<<" Edge across clip plane, v0="<<v0<<", v1="<<v1<<", intersection= "<<intersection<<std::endl;
if (d0<0.0)
{
// move first vertex on edge
v0 = intersection;
}
else
{
// move second vertex on edge
v1 = intersection;
}
++itr;
}
}
// OSG_NOTICE<<" after clip("<<plane<<") edges.size()="<<_edges.size()<<std::endl;
}
void clip(const osg::Polytope& polytope)
{
const osg::Polytope::PlaneList& planes = polytope.getPlaneList();
for(osg::Polytope::PlaneList::const_iterator itr = planes.begin();
itr != planes.end();
++itr)
{
clip(*itr);
}
}
void traverse(osgUtil::RenderStage* rs)
double min(unsigned int index) const
{
traverse(static_cast<osgUtil::RenderBin*>(rs));
double m = DBL_MAX;
for(Edges::const_iterator itr = _edges.begin();
itr != _edges.end();
++itr)
{
const Edge& edge = *itr;
if (edge.first[index]<m) m = edge.first[index];
if (edge.second[index]<m) m = edge.second[index];
}
return m;
}
double max(unsigned int index) const
{
double m = -DBL_MAX;
for(Edges::const_iterator itr = _edges.begin();
itr != _edges.end();
++itr)
{
const Edge& edge = *itr;
if (edge.first[index]>m) m = edge.first[index];
if (edge.second[index]>m) m = edge.second[index];
}
return m;
}
void traverse(osgUtil::RenderBin* renderBin)
double minRatio(const osg::Vec3d& eye, unsigned int index) const
{
OSG_NOTICE<<"traverse(RenderBin="<<renderBin<<")"<<std::endl;
double m = DBL_MAX;
osg::Vec3d delta;
double ratio;
for(Edges::const_iterator itr = _edges.begin();
itr != _edges.end();
++itr)
{
const Edge& edge = *itr;
delta = edge.first-eye;
ratio = delta[index]/delta[1];
if (ratio<m) m = ratio;
delta = edge.second-eye;
ratio = delta[index]/delta[1];
if (ratio<m) m = ratio;
}
return m;
}
void traverse(osgUtil::StateGraph* stateGraph)
double maxRatio(const osg::Vec3d& eye, unsigned int index) const
{
OSG_NOTICE<<"traverse(StateGraph="<<stateGraph<<")"<<std::endl;
double m = -DBL_MAX;
osg::Vec3d delta;
double ratio;
for(Edges::const_iterator itr = _edges.begin();
itr != _edges.end();
++itr)
{
const Edge& edge = *itr;
delta = edge.first-eye;
ratio = delta[index]/delta[1];
if (ratio>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("<<renderLeaf<<")"<<std::endl;
}
out<<"ConvexHull"<<std::endl;
for(Edges::const_iterator itr = _edges.begin();
itr != _edges.end();
++itr)
{
const Edge& edge = *itr;
out<<" edge ("<<edge.first<<") ("<<edge.second<<")"<<std::endl;
}
}
};
struct RenderLeafBounds
{
RenderLeafBounds():
n(0.0),
previous_modelview(0),
clip_min_x(-1.0), clip_max_x(1.0),
clip_min_y(-1.0), clip_max_y(1.0),
clip_min_z(-1.0), clip_max_z(1.0),
clip_min_x_ratio(-DBL_MAX), clip_max_x_ratio(DBL_MAX),
clip_min_z_ratio(-DBL_MAX), clip_max_z_ratio(DBL_MAX),
min_x_ratio(DBL_MAX), max_x_ratio(-DBL_MAX),
min_z_ratio(DBL_MAX), max_z_ratio(-DBL_MAX),
min_x(1.0), max_x(-1.0),
min_y(1.0), max_y(-1.0),
min_z(1.0), max_z(-1.0)
{
//OSG_NOTICE<<std::endl<<"RenderLeafBounds"<<std::endl;
}
void set(const osg::Matrixd& vp, osg::Vec3d& e_ls, double nr)
{
light_vp = vp;
eye_ls = e_ls;
n = nr;
}
void operator() (const osgUtil::RenderLeaf* renderLeaf)
{
if (renderLeaf->_modelview.get()!=previous_modelview)
{
previous_modelview = renderLeaf->_modelview.get();
light_mvp.mult(*renderLeaf->_modelview, light_vp);
//OSG_NOTICE<<"Computing new light_mvp "<<light_mvp<<std::endl;
}
else
{
//OSG_NOTICE<<"Reusing light_mvp "<<light_mvp<<std::endl;
}
const osg::BoundingBox& bb = renderLeaf->_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"<<std::endl;
}
}
void handle(const osg::Vec3d& v)
{
osg::Vec3d ls = v * light_mvp;
osg::Vec3d delta = ls-eye_ls;
double x_ratio, z_ratio;
if (delta.y()>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_ratio<min_x_ratio) min_x_ratio = x_ratio;
if (x_ratio>max_x_ratio) max_x_ratio = x_ratio;
if (z_ratio<min_z_ratio) min_z_ratio = z_ratio;
if (z_ratio>max_z_ratio) max_z_ratio = z_ratio;
// clip to the light space
if (ls.x()<clip_min_x) ls.x()=clip_min_x;
if (ls.x()>clip_max_x) ls.x()=clip_max_x;
if (ls.y()<clip_min_y) ls.y()=clip_min_y;
if (ls.y()>clip_max_y) ls.y()=clip_max_y;
if (ls.z()<clip_min_z) ls.z()=clip_min_z;
if (ls.z()>clip_max_z) ls.z()=clip_max_z;
// compute the xyz range.
if (ls.x()<min_x) min_x=ls.x();
if (ls.x()>max_x) max_x=ls.x();
if (ls.y()<min_y) min_y=ls.y();
if (ls.y()>max_y) max_y=ls.y();
if (ls.z()<min_z) min_z=ls.z();
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="<<light_v<<std::endl;
//OSG_NOTICE<<"light_p="<<light_p<<std::endl;
ConvexHull convexHull;
convexHull.setToFrustum(frustum);
#if 0
OSG_NOTICE<<"ws ConvexHull xMin="<<convexHull.min(0)<<", xMax="<<convexHull.max(0)<<std::endl;
OSG_NOTICE<<"ws ConvexHull yMin="<<convexHull.min(1)<<", yMax="<<convexHull.max(1)<<std::endl;
OSG_NOTICE<<"ws ConvexHull zMin="<<convexHull.min(2)<<", zMax="<<convexHull.max(2)<<std::endl;
convexHull.output(osg::notify(osg::NOTICE));
#endif
convexHull.transform(light_vp);
#if 0
convexHull.output(osg::notify(osg::NOTICE));
OSG_NOTICE<<"ls ConvexHull xMin="<<convexHull.min(0)<<", xMax="<<convexHull.max(0)<<std::endl;
OSG_NOTICE<<"ls ConvexHull yMin="<<convexHull.min(1)<<", yMax="<<convexHull.max(1)<<std::endl;
OSG_NOTICE<<"ls ConvexHull zMin="<<convexHull.min(2)<<", zMax="<<convexHull.max(2)<<std::endl;
#endif
convexHull.clip(osg::Plane(0.0,0.0,1,1.0)); // clip by near plane of light space.
convexHull.clip(osg::Plane(0.0,0.0,-1,1.0)); // clip by far plane of light space.
#if 0
convexHull.output(osg::notify(osg::NOTICE));
OSG_NOTICE<<"clipped ls ConvexHull xMin="<<convexHull.min(0)<<", xMax="<<convexHull.max(0)<<std::endl;
OSG_NOTICE<<"clipped ls ConvexHull yMin="<<convexHull.min(1)<<", yMax="<<convexHull.max(1)<<std::endl;
OSG_NOTICE<<"clipped ls ConvexHull zMin="<<convexHull.min(2)<<", zMax="<<convexHull.max(2)<<std::endl;
#endif
if (convexHull.min(0)!=-1.0 || convexHull.min(1)!=-1.0 || convexHull.min(2)!=-1.0 ||
convexHull.max(0)!=1.0 || convexHull.max(1)!=1.0 || convexHull.max(2)!=1.0)
{
double zMin = -1.0;
osg::Matrix m;
m.makeTranslate(osg::Vec3d(-0.5*(convexHull.max(0)+convexHull.min(0)),
-0.5*(convexHull.max(1)+convexHull.min(1)),
-0.5*(convexHull.max(2)+zMin)));
m.postMultScale(osg::Vec3d(2.0/(convexHull.max(0)-convexHull.min(0)),
2.0/(convexHull.max(1)-convexHull.min(1)),
2.0/(convexHull.max(2)-zMin)));
convexHull.transform(m);
light_p.postMult(m);
light_vp = light_v * light_p;
#if 0
OSG_NOTICE<<"Adjusting projection matrix "<<m<<std::endl;
convexHull.output(osg::notify(osg::NOTICE));
#endif
camera->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_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;
}
@@ -1092,112 +1490,76 @@ bool ViewDependentShadowMap::adjustPerspectiveShadowMapCameraSettings(osgUtil::R
//OSG_NOTICE<<"viewdir_v="<<viewdir_v<<std::endl;
osg::Vec3d eye_ls = frustum.eye * light_vp;
#if 0
if (eye_ls.y()>-1.0)
{
OSG_NOTICE<<"Eye point within light space - use standard shadow map."<<std::endl;
return true;
}
#endif
osg::Vec3d centerNearPlane_ls = frustum.centerNearPlane * light_vp;
osg::Vec3d centerFarPlane_ls = frustum.centerFarPlane * light_vp;
osg::Vec3d center_ls = frustum.center * light_vp;
osg::Vec3d viewdir_ls = center_ls-eye_ls; viewdir_ls.normalize();
double sinGamma = sin(gamma_v);
osg::Vec3d side = lightdir ^ viewdir_ls; side.normalize();
osg::Vec3d up = side ^ lightdir;
// double nearDist = (centerNearPlane_ls - eye_ls).length();
double nearDist = (centerNearPlane_ls - eye_ls).y();
double farDist = (centerFarPlane_ls - eye_ls).y();
double nearFarRatio = nearDist/(farDist-nearDist);
double d = 2.0;
double min_y = DBL_MAX;
double max_y = -DBL_MAX;
for(unsigned int i=0;i<8;++i)
double alpha = osg::DegreesToRadians(30.0);
double n = tan(alpha)*tan(osg::PI_2-gamma_v)*tan(osg::PI_2-gamma_v);
//double n = tan(alpha)*tan(osg::PI_2-gamma_v);
double min_n = osg::maximum(-1.0-eye_ls.y(), 0.01);
if (n<min_n)
{
osg::Vec3d c_ls = frustum.corners[i] * light_vp;
if (c_ls.y()<min_y) min_y = c_ls.y();
if (c_ls.y()>max_y) max_y = c_ls.y();
// OSG_NOTICE<<" corner light space "<<c_ls<<std::endl;
// OSG_NOTICE<<"Clamping n to eye point"<<std::endl;
n=min_n;
}
double d = (max_y-min_y);
//OSG_NOTICE<<"nearDist before = "<<nearDist<<", nearFarRatio = "<<nearFarRatio<<std::endl;
//double factor = 1.0/sinGamma;
//double z_n = factor*nearDist;
double z_n = d * nearFarRatio;
//perspective transform depth light space y extents
double z_f = z_n + d;
double n = (z_n+sqrt(z_f*z_n))/sinGamma;
double min_n = 0.0;
if (n<min_n) n = min_n;
//n = z_n;
double f = n+d;
double a = (f+n)/(f-n);
double b = -2.0*f*n/(f-n);
double shift = n - (min_y - eye_ls.y());
osg::Vec3d virtual_eye = eye_ls - up*shift;
osg::Vec3d virtual_eye(0.0,-1.0-n, eye_ls.z());
osg::Matrixd lightView;
lightView.makeLookAt(virtual_eye, virtual_eye+lightdir, up);
#if 0
OSG_NOTICE<<"Eye world "<<frustum.eye<<std::endl;
OSG_NOTICE<<"Eye light space "<<eye_ls<<std::endl;
OSG_NOTICE<<"Center light space "<<center_ls<<std::endl;
OSG_NOTICE<<"Viewdir light space "<<viewdir_ls<<std::endl;
OSG_NOTICE<<"gamma_v "<<osg::RadiansToDegrees(gamma_v)<<std::endl;
OSG_NOTICE<<"side "<<side<<std::endl;
OSG_NOTICE<<"up "<<up<<std::endl;
OSG_NOTICE<<"min_y = "<<min_y<<std::endl;
OSG_NOTICE<<"max_y = "<<max_y<<std::endl;
OSG_NOTICE<<"d = "<<d<<std::endl;
OSG_NOTICE<<"n = "<<n<<std::endl;
OSG_NOTICE<<"z_n = "<<z_n<<std::endl;
OSG_NOTICE<<"z_f = "<<z_f<<std::endl;
OSG_NOTICE<<"nearDist = "<<nearDist<<std::endl;
OSG_NOTICE<<"shift = "<<shift<<std::endl;
#endif
double min_x = -1.0 - virtual_eye.x();
double max_x = 1.0 - virtual_eye.x();
double min_z = -1.0 - virtual_eye.z();
double max_z = 1.0 - virtual_eye.z();
#if 0
OSG_NOTICE<<"min_x = "<<min_x<<std::endl;
OSG_NOTICE<<"max_x = "<<max_x<<std::endl;
OSG_NOTICE<<"min_z = "<<min_z<<std::endl;
OSG_NOTICE<<"max_z = "<<max_z<<std::endl;
#endif
double min_x_ratio = 0.0;
double max_x_ratio = 0.0;
double min_z_ratio = FLT_MAX;
double max_z_ratio = -FLT_MAX;
for(unsigned int i=0;i<8;++i)
min_x_ratio = convexHull.minRatio(virtual_eye,0);
min_z_ratio = convexHull.minRatio(virtual_eye,2);
max_x_ratio = convexHull.maxRatio(virtual_eye,0);
max_z_ratio = convexHull.maxRatio(virtual_eye,2);
if (renderStage)
{
osg::Vec3d c_ve = frustum.corners[i] * light_vp - virtual_eye;
osg::ElapsedTime timer;
RenderLeafTraverser<RenderLeafBounds> rli;
rli.set(osg::Matrix::inverse(frustum.modelViewMatrix) * light_vp, virtual_eye, n);
rli.traverse(renderStage);
#if 0
OSG_NOTICE<<"Time for RenderLeafTraverser "<<timer.elapsedTime_m()<<"ms"<<std::endl;
OSG_NOTICE<<"scene bounds min_x="<<rli.min_x<<", max_x="<<rli.max_x<<std::endl;
OSG_NOTICE<<"scene bounds min_y="<<rli.min_y<<", max_y="<<rli.max_y<<std::endl;
OSG_NOTICE<<"scene bounds min_z="<<rli.min_z<<", max_z="<<rli.max_z<<std::endl;
OSG_NOTICE<<"min_x_ratio="<<rli.min_x_ratio<<", max_x_ratio="<<rli.max_x_ratio<<std::endl;
OSG_NOTICE<<"min_z_ratio="<<rli.min_z_ratio<<", max_z_ratio="<<rli.max_z_ratio<<std::endl;
#endif
if (rli.max_z_ratio>max_z_ratio) max_z_ratio = rli.max_z_ratio;
if (rli.min_z_ratio<min_z_ratio) min_z_ratio = rli.min_z_ratio;
double x = c_ve.x();
if (x<min_x) x=min_x;
if (x>max_x) x=max_x;
double x_ratio = x/c_ve.y();
if (x_ratio<min_x_ratio) min_x_ratio = x_ratio;
if (x_ratio>max_x_ratio) max_x_ratio = x_ratio;
double z = c_ve.z();
if (z<min_z) z=min_z;
if (z>max_z) z=max_z;
double z_ratio = c_ve.z()/c_ve.y();
if (z_ratio<min_z_ratio) min_z_ratio = z_ratio;
if (z_ratio>max_z_ratio) max_z_ratio = z_ratio;
//if (rli.min_y>min_y) min_y = rli.min_y;
//if (rli.max_y<max_y) max_y = rli.max_y;
}
double best_x_ratio = osg::maximum(fabs(min_x_ratio),fabs(max_x_ratio));
@@ -1211,7 +1573,7 @@ bool ViewDependentShadowMap::adjustPerspectiveShadowMapCameraSettings(osgUtil::R
OSG_NOTICE<<"max_z_ratio = "<<max_z_ratio<<std::endl;
OSG_NOTICE<<"best_z_ratio = "<<best_z_ratio<<std::endl;
#endif
#if 0
osg::Matrixd lightPerspective( 1.0, 0.0, 0.0, 0.0,
0.0, a, 0.0, 1.0,