Ran dos2unix on new shadow implemenations
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,368 +1,368 @@
|
||||
/* -*-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.
|
||||
*
|
||||
* ViewDependentShadow codes Copyright (C) 2008 Wojciech Lewandowski
|
||||
* Thanks to to my company http://www.ai.com.pl for allowing me free this work.
|
||||
*/
|
||||
|
||||
|
||||
#include <osgShadow/MinimalCullBoundsShadowMap>
|
||||
#include <osgUtil/RenderLeaf>
|
||||
#include <string.h>
|
||||
|
||||
#define IGNORE_OBJECTS_LARGER_THAN_HEIGHT 0
|
||||
|
||||
using namespace osgShadow;
|
||||
|
||||
MinimalCullBoundsShadowMap::MinimalCullBoundsShadowMap(): BaseClass()
|
||||
{
|
||||
}
|
||||
|
||||
MinimalCullBoundsShadowMap::MinimalCullBoundsShadowMap
|
||||
(const MinimalCullBoundsShadowMap& copy, const osg::CopyOp& copyop) :
|
||||
BaseClass(copy,copyop)
|
||||
{
|
||||
}
|
||||
|
||||
MinimalCullBoundsShadowMap::~MinimalCullBoundsShadowMap()
|
||||
{
|
||||
}
|
||||
|
||||
void MinimalCullBoundsShadowMap::ViewData::init
|
||||
( ThisClass *st, osgUtil::CullVisitor *cv )
|
||||
{
|
||||
BaseClass::ViewData::init( st, cv );
|
||||
}
|
||||
|
||||
void MinimalCullBoundsShadowMap::ViewData::aimShadowCastingCamera
|
||||
( const osg::Light *light,
|
||||
const osg::Vec4 &lightPos,
|
||||
const osg::Vec3 &lightDir,
|
||||
const osg::Vec3 &lightUp )
|
||||
{
|
||||
MinimalShadowMap::ViewData::aimShadowCastingCamera
|
||||
( light, lightPos, lightDir, lightUp );
|
||||
|
||||
frameShadowCastingCamera
|
||||
( _cv->getCurrentRenderBin()->getStage()->getCamera(), _camera.get() );
|
||||
}
|
||||
|
||||
void MinimalCullBoundsShadowMap::ViewData::cullShadowReceivingScene( )
|
||||
{
|
||||
RenderLeafList rllOld, rllNew;
|
||||
|
||||
GetRenderLeaves( _cv->getRenderStage(), rllOld );
|
||||
|
||||
MinimalShadowMap::ViewData::cullShadowReceivingScene( );
|
||||
|
||||
GetRenderLeaves( _cv->getRenderStage(), rllNew );
|
||||
|
||||
RemoveOldRenderLeaves( rllNew, rllOld );
|
||||
RemoveIgnoredRenderLeaves( rllNew );
|
||||
|
||||
osg::Matrix projectionToModelSpace =
|
||||
osg::Matrix::inverse( *_modellingSpaceToWorldPtr *
|
||||
*_cv->getModelViewMatrix() * *_cv->getProjectionMatrix() );
|
||||
|
||||
osg::BoundingBox bb;
|
||||
if( *_cv->getProjectionMatrix() != _clampedProjection ) {
|
||||
|
||||
osg::Polytope polytope;
|
||||
#if 1
|
||||
polytope.setToUnitFrustum();
|
||||
#else
|
||||
polytope.add( osg::Plane( 0.0,0.0,-1.0,1.0 ) ); // only far plane
|
||||
#endif
|
||||
polytope.transformProvidingInverse( *_modellingSpaceToWorldPtr *
|
||||
*_cv->getModelViewMatrix() * _clampedProjection );
|
||||
|
||||
bb = ComputeRenderLeavesBounds( rllNew, projectionToModelSpace, polytope );
|
||||
} else {
|
||||
bb = ComputeRenderLeavesBounds( rllNew, projectionToModelSpace );
|
||||
}
|
||||
|
||||
cutScenePolytope( *_modellingSpaceToWorldPtr,
|
||||
osg::Matrix::inverse( *_modellingSpaceToWorldPtr ), bb );
|
||||
}
|
||||
|
||||
void MinimalCullBoundsShadowMap::ViewData::GetRenderLeaves
|
||||
( osgUtil::RenderBin *rb, RenderLeafList & rll )
|
||||
{
|
||||
osgUtil::RenderBin::RenderBinList& bins = rb->getRenderBinList();
|
||||
osgUtil::RenderBin::RenderBinList::const_iterator rbitr;
|
||||
|
||||
// scan pre render bins
|
||||
for(rbitr = bins.begin(); rbitr!=bins.end() && rbitr->first<0; ++rbitr )
|
||||
GetRenderLeaves( rbitr->second.get(), rll );
|
||||
|
||||
// scan fine grained ordering.
|
||||
osgUtil::RenderBin::RenderLeafList& renderLeafList = rb->getRenderLeafList();
|
||||
osgUtil::RenderBin::RenderLeafList::const_iterator rlitr;
|
||||
for( rlitr= renderLeafList.begin(); rlitr!= renderLeafList.end(); ++rlitr )
|
||||
{
|
||||
rll.push_back( *rlitr );
|
||||
}
|
||||
|
||||
// scan coarse grained ordering.
|
||||
osgUtil::RenderBin::StateGraphList& stateGraphList = rb->getStateGraphList();
|
||||
osgUtil::RenderBin::StateGraphList::const_iterator oitr;
|
||||
for( oitr= stateGraphList.begin(); oitr!= stateGraphList.end(); ++oitr )
|
||||
{
|
||||
for( osgUtil::StateGraph::LeafList::const_iterator dw_itr =
|
||||
(*oitr)->_leaves.begin(); dw_itr != (*oitr)->_leaves.end(); ++dw_itr)
|
||||
{
|
||||
rll.push_back( dw_itr->get() );
|
||||
}
|
||||
}
|
||||
|
||||
// scan post render bins
|
||||
for(; rbitr!=bins.end(); ++rbitr )
|
||||
GetRenderLeaves( rbitr->second.get(), rll );
|
||||
}
|
||||
|
||||
class CompareRenderLeavesByMatrices {
|
||||
public:
|
||||
bool operator()( const osgUtil::RenderLeaf *a, const osgUtil::RenderLeaf *b )
|
||||
{
|
||||
if ( !a ) return false; // NULL render leaf goes last
|
||||
return !b ||
|
||||
a->_projection < b->_projection ||
|
||||
a->_projection == b->_projection && a->_modelview < b->_modelview;
|
||||
}
|
||||
};
|
||||
|
||||
inline bool CheckAndMultiplyBoxIfWithinPolytope
|
||||
( osg::BoundingBox & bb, osg::Matrix & m, osg::Polytope &p )
|
||||
{
|
||||
if( !bb.valid() ) return false;
|
||||
|
||||
osg::Vec3 o = bb._min * m, s[3];
|
||||
|
||||
for( int i = 0; i < 3; i ++ )
|
||||
s[i] = osg::Vec3( m(i,0), m(i,1), m(i,2) ) * ( bb._max[i] - bb._min[i] );
|
||||
|
||||
for( osg::Polytope::PlaneList::iterator it = p.getPlaneList().begin();
|
||||
it != p.getPlaneList().end();
|
||||
++it )
|
||||
{
|
||||
float dist = it->distance( o ), dist_min = dist, dist_max = dist;
|
||||
|
||||
for( int i = 0; i < 3; i ++ ) {
|
||||
dist = it->dotProductNormal( s[i] );
|
||||
if( dist < 0 ) dist_min += dist; else dist_max += dist;
|
||||
}
|
||||
|
||||
if( dist_max < 0 )
|
||||
return false;
|
||||
}
|
||||
|
||||
bb._max = bb._min = o;
|
||||
#if 1
|
||||
for( int i = 0; i < 3; i ++ )
|
||||
for( int j = 0; j < 3; j ++ )
|
||||
if( s[i][j] < 0 ) bb._min[j] += s[i][j]; else bb._max[j] += s[i][j];
|
||||
#else
|
||||
b.expandBy( o + s[0] );
|
||||
b.expandBy( o + s[1] );
|
||||
b.expandBy( o + s[2] );
|
||||
b.expandBy( o + s[0] + s[1] );
|
||||
b.expandBy( o + s[0] + s[2] );
|
||||
b.expandBy( o + s[1] + s[2] );
|
||||
b.expandBy( o + s[0] + s[1] + s[2] );
|
||||
#endif
|
||||
|
||||
#if ( IGNORE_OBJECTS_LARGER_THAN_HEIGHT > 0 )
|
||||
if( bb._max[2] - bb._min[2] > IGNORE_OBJECTS_LARGER_THAN_HEIGHT ) // ignore huge objects
|
||||
return false;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned MinimalCullBoundsShadowMap::ViewData::RemoveOldRenderLeaves
|
||||
( RenderLeafList &rllNew, RenderLeafList &rllOld )
|
||||
{
|
||||
unsigned count = 0;
|
||||
|
||||
std::sort( rllOld.begin(), rllOld.end() );
|
||||
RenderLeafList::iterator itNew, itOld;
|
||||
for( itNew = rllNew.begin(); itNew != rllNew.end() && rllOld.size(); ++itNew )
|
||||
{
|
||||
itOld = std::lower_bound( rllOld.begin(), rllOld.end(), *itNew );
|
||||
|
||||
if( itOld == rllOld.end() || *itOld != *itNew ) continue;
|
||||
// found !
|
||||
rllOld.erase( itOld ); //remove it from old range to speed up search
|
||||
*itNew = NULL; //its not new = invalidate it among new render leaves
|
||||
count ++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
unsigned MinimalCullBoundsShadowMap::ViewData::RemoveIgnoredRenderLeaves
|
||||
( RenderLeafList &rll )
|
||||
{
|
||||
unsigned count = 0;
|
||||
|
||||
for( RenderLeafList::iterator it = rll.begin(); it != rll.end(); ++it )
|
||||
{
|
||||
if( !*it ) continue;
|
||||
|
||||
const char * name = (*it)->_drawable->className();
|
||||
|
||||
// Its a dirty but quick test (not very future proof)
|
||||
if( !name || name[0] != 'L' ) continue;
|
||||
|
||||
if( !strcmp( name, "LightPointDrawable" ) ||
|
||||
!strcmp( name, "LightPointSpriteDrawable" ) )
|
||||
{
|
||||
*it = NULL; //ignored = invalidate this in new render leaves list
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
osg::BoundingBox MinimalCullBoundsShadowMap::ViewData::ComputeRenderLeavesBounds
|
||||
( RenderLeafList &rll, osg::Matrix & projectionToWorld )
|
||||
{
|
||||
osg::BoundingBox bbResult;
|
||||
|
||||
if( rll.size() == 0 ) return bbResult;
|
||||
|
||||
std::sort( rll.begin(), rll.end(), CompareRenderLeavesByMatrices() );
|
||||
|
||||
osg::ref_ptr< osg::RefMatrix > modelview;
|
||||
osg::ref_ptr< osg::RefMatrix > projection;
|
||||
osg::Matrix viewToWorld, modelToWorld, *ptrProjection = NULL,
|
||||
*ptrViewToWorld = &projectionToWorld, *ptrModelToWorld;
|
||||
|
||||
osg::BoundingBox bb;
|
||||
|
||||
// compute bounding boxes but skip old ones (placed at the end as NULLs)
|
||||
for( RenderLeafList::iterator it = rll.begin(); ; ++it ) {
|
||||
// we actually allow to pass one element behind end to flush bb queue
|
||||
osgUtil::RenderLeaf *rl = ( it != rll.end() ? *it : NULL );
|
||||
|
||||
// Don't trust already computed bounds for cull generated drawables
|
||||
// LightPointDrawable & LightPointSpriteDrawable are such examples
|
||||
// they store wrong recorded bounds from very first pass
|
||||
if( rl && rl->_modelview == NULL )
|
||||
rl->_drawable->dirtyBound();
|
||||
|
||||
// Stay as long as possible in model space to minimize matrix ops
|
||||
if( rl && rl->_modelview == modelview && rl->_projection == projection ){
|
||||
bb.expandBy( rl->_drawable->getBound() );
|
||||
} else {
|
||||
if( bb.valid() ) {
|
||||
// Conditions to avoid matrix multiplications
|
||||
if( projection.valid() )
|
||||
{
|
||||
if( projection.get() != ptrProjection )
|
||||
{
|
||||
ptrProjection = projection.get();
|
||||
viewToWorld = *ptrProjection * projectionToWorld;
|
||||
}
|
||||
ptrViewToWorld = &viewToWorld;
|
||||
} else {
|
||||
ptrViewToWorld = &projectionToWorld;
|
||||
}
|
||||
|
||||
if( modelview.valid() )
|
||||
{
|
||||
modelToWorld = *modelview.get() * *ptrViewToWorld;
|
||||
ptrModelToWorld = &modelToWorld;
|
||||
} else {
|
||||
ptrModelToWorld = ptrViewToWorld;
|
||||
}
|
||||
|
||||
for( int i = 0; i < 8; i++ )
|
||||
bbResult.expandBy( bb.corner( i ) * *ptrModelToWorld );
|
||||
}
|
||||
if( !rl ) break;
|
||||
bb = rl->_drawable->getBound();
|
||||
modelview = rl->_modelview;
|
||||
projection = rl->_projection;
|
||||
}
|
||||
}
|
||||
|
||||
rll.clear();
|
||||
|
||||
return bbResult;
|
||||
}
|
||||
|
||||
osg::BoundingBox MinimalCullBoundsShadowMap::ViewData::ComputeRenderLeavesBounds
|
||||
( RenderLeafList &rll, osg::Matrix & projectionToWorld, osg::Polytope & p )
|
||||
{
|
||||
osg::BoundingBox bbResult, bb;
|
||||
|
||||
if( rll.size() == 0 ) return bbResult;
|
||||
|
||||
std::sort( rll.begin(), rll.end(), CompareRenderLeavesByMatrices() );
|
||||
|
||||
osg::ref_ptr< osg::RefMatrix > modelview;
|
||||
osg::ref_ptr< osg::RefMatrix > projection;
|
||||
osg::Matrix viewToWorld, modelToWorld, *ptrProjection = NULL,
|
||||
*ptrViewToWorld = &projectionToWorld, *ptrModelToWorld;
|
||||
|
||||
// compute bounding boxes but skip old ones (placed at the end as NULLs)
|
||||
for( RenderLeafList::iterator it = rll.begin(); it != rll.end(); ++it ) {
|
||||
// we actually allow to pass one element behind end to flush bb queue
|
||||
osgUtil::RenderLeaf *rl = *it;
|
||||
if( !rl ) break;
|
||||
|
||||
// Don't trust already computed bounds for cull generated drawables
|
||||
// LightPointDrawable & LightPointSpriteDrawable are such examples
|
||||
// they store wrong recorded bounds from very first pass
|
||||
if( rl && rl->_modelview == NULL )
|
||||
rl->_drawable->dirtyBound();
|
||||
|
||||
bb = rl->_drawable->getBound();
|
||||
if( !bb.valid() ) continue;
|
||||
|
||||
// Stay as long as possible in model space to minimize matrix ops
|
||||
if( rl->_modelview != modelview || rl->_projection != projection ) {
|
||||
|
||||
projection = rl->_projection;
|
||||
if( projection.valid() )
|
||||
{
|
||||
if( projection.get() != ptrProjection )
|
||||
{
|
||||
ptrProjection = projection.get();
|
||||
viewToWorld = *ptrProjection * projectionToWorld;
|
||||
}
|
||||
ptrViewToWorld = &viewToWorld;
|
||||
} else {
|
||||
ptrViewToWorld = &projectionToWorld;
|
||||
}
|
||||
|
||||
modelview = rl->_modelview;
|
||||
if( modelview.valid() )
|
||||
{
|
||||
modelToWorld = *modelview.get() * *ptrViewToWorld;
|
||||
ptrModelToWorld = &modelToWorld;
|
||||
} else {
|
||||
ptrModelToWorld = ptrViewToWorld;
|
||||
}
|
||||
}
|
||||
|
||||
if( CheckAndMultiplyBoxIfWithinPolytope( bb, *ptrModelToWorld, p ) )
|
||||
bbResult.expandBy( bb );
|
||||
}
|
||||
|
||||
rll.clear();
|
||||
|
||||
return bbResult;
|
||||
}
|
||||
|
||||
/* -*-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.
|
||||
*
|
||||
* ViewDependentShadow codes Copyright (C) 2008 Wojciech Lewandowski
|
||||
* Thanks to to my company http://www.ai.com.pl for allowing me free this work.
|
||||
*/
|
||||
|
||||
|
||||
#include <osgShadow/MinimalCullBoundsShadowMap>
|
||||
#include <osgUtil/RenderLeaf>
|
||||
#include <string.h>
|
||||
|
||||
#define IGNORE_OBJECTS_LARGER_THAN_HEIGHT 0
|
||||
|
||||
using namespace osgShadow;
|
||||
|
||||
MinimalCullBoundsShadowMap::MinimalCullBoundsShadowMap(): BaseClass()
|
||||
{
|
||||
}
|
||||
|
||||
MinimalCullBoundsShadowMap::MinimalCullBoundsShadowMap
|
||||
(const MinimalCullBoundsShadowMap& copy, const osg::CopyOp& copyop) :
|
||||
BaseClass(copy,copyop)
|
||||
{
|
||||
}
|
||||
|
||||
MinimalCullBoundsShadowMap::~MinimalCullBoundsShadowMap()
|
||||
{
|
||||
}
|
||||
|
||||
void MinimalCullBoundsShadowMap::ViewData::init
|
||||
( ThisClass *st, osgUtil::CullVisitor *cv )
|
||||
{
|
||||
BaseClass::ViewData::init( st, cv );
|
||||
}
|
||||
|
||||
void MinimalCullBoundsShadowMap::ViewData::aimShadowCastingCamera
|
||||
( const osg::Light *light,
|
||||
const osg::Vec4 &lightPos,
|
||||
const osg::Vec3 &lightDir,
|
||||
const osg::Vec3 &lightUp )
|
||||
{
|
||||
MinimalShadowMap::ViewData::aimShadowCastingCamera
|
||||
( light, lightPos, lightDir, lightUp );
|
||||
|
||||
frameShadowCastingCamera
|
||||
( _cv->getCurrentRenderBin()->getStage()->getCamera(), _camera.get() );
|
||||
}
|
||||
|
||||
void MinimalCullBoundsShadowMap::ViewData::cullShadowReceivingScene( )
|
||||
{
|
||||
RenderLeafList rllOld, rllNew;
|
||||
|
||||
GetRenderLeaves( _cv->getRenderStage(), rllOld );
|
||||
|
||||
MinimalShadowMap::ViewData::cullShadowReceivingScene( );
|
||||
|
||||
GetRenderLeaves( _cv->getRenderStage(), rllNew );
|
||||
|
||||
RemoveOldRenderLeaves( rllNew, rllOld );
|
||||
RemoveIgnoredRenderLeaves( rllNew );
|
||||
|
||||
osg::Matrix projectionToModelSpace =
|
||||
osg::Matrix::inverse( *_modellingSpaceToWorldPtr *
|
||||
*_cv->getModelViewMatrix() * *_cv->getProjectionMatrix() );
|
||||
|
||||
osg::BoundingBox bb;
|
||||
if( *_cv->getProjectionMatrix() != _clampedProjection ) {
|
||||
|
||||
osg::Polytope polytope;
|
||||
#if 1
|
||||
polytope.setToUnitFrustum();
|
||||
#else
|
||||
polytope.add( osg::Plane( 0.0,0.0,-1.0,1.0 ) ); // only far plane
|
||||
#endif
|
||||
polytope.transformProvidingInverse( *_modellingSpaceToWorldPtr *
|
||||
*_cv->getModelViewMatrix() * _clampedProjection );
|
||||
|
||||
bb = ComputeRenderLeavesBounds( rllNew, projectionToModelSpace, polytope );
|
||||
} else {
|
||||
bb = ComputeRenderLeavesBounds( rllNew, projectionToModelSpace );
|
||||
}
|
||||
|
||||
cutScenePolytope( *_modellingSpaceToWorldPtr,
|
||||
osg::Matrix::inverse( *_modellingSpaceToWorldPtr ), bb );
|
||||
}
|
||||
|
||||
void MinimalCullBoundsShadowMap::ViewData::GetRenderLeaves
|
||||
( osgUtil::RenderBin *rb, RenderLeafList & rll )
|
||||
{
|
||||
osgUtil::RenderBin::RenderBinList& bins = rb->getRenderBinList();
|
||||
osgUtil::RenderBin::RenderBinList::const_iterator rbitr;
|
||||
|
||||
// scan pre render bins
|
||||
for(rbitr = bins.begin(); rbitr!=bins.end() && rbitr->first<0; ++rbitr )
|
||||
GetRenderLeaves( rbitr->second.get(), rll );
|
||||
|
||||
// scan fine grained ordering.
|
||||
osgUtil::RenderBin::RenderLeafList& renderLeafList = rb->getRenderLeafList();
|
||||
osgUtil::RenderBin::RenderLeafList::const_iterator rlitr;
|
||||
for( rlitr= renderLeafList.begin(); rlitr!= renderLeafList.end(); ++rlitr )
|
||||
{
|
||||
rll.push_back( *rlitr );
|
||||
}
|
||||
|
||||
// scan coarse grained ordering.
|
||||
osgUtil::RenderBin::StateGraphList& stateGraphList = rb->getStateGraphList();
|
||||
osgUtil::RenderBin::StateGraphList::const_iterator oitr;
|
||||
for( oitr= stateGraphList.begin(); oitr!= stateGraphList.end(); ++oitr )
|
||||
{
|
||||
for( osgUtil::StateGraph::LeafList::const_iterator dw_itr =
|
||||
(*oitr)->_leaves.begin(); dw_itr != (*oitr)->_leaves.end(); ++dw_itr)
|
||||
{
|
||||
rll.push_back( dw_itr->get() );
|
||||
}
|
||||
}
|
||||
|
||||
// scan post render bins
|
||||
for(; rbitr!=bins.end(); ++rbitr )
|
||||
GetRenderLeaves( rbitr->second.get(), rll );
|
||||
}
|
||||
|
||||
class CompareRenderLeavesByMatrices {
|
||||
public:
|
||||
bool operator()( const osgUtil::RenderLeaf *a, const osgUtil::RenderLeaf *b )
|
||||
{
|
||||
if ( !a ) return false; // NULL render leaf goes last
|
||||
return !b ||
|
||||
a->_projection < b->_projection ||
|
||||
a->_projection == b->_projection && a->_modelview < b->_modelview;
|
||||
}
|
||||
};
|
||||
|
||||
inline bool CheckAndMultiplyBoxIfWithinPolytope
|
||||
( osg::BoundingBox & bb, osg::Matrix & m, osg::Polytope &p )
|
||||
{
|
||||
if( !bb.valid() ) return false;
|
||||
|
||||
osg::Vec3 o = bb._min * m, s[3];
|
||||
|
||||
for( int i = 0; i < 3; i ++ )
|
||||
s[i] = osg::Vec3( m(i,0), m(i,1), m(i,2) ) * ( bb._max[i] - bb._min[i] );
|
||||
|
||||
for( osg::Polytope::PlaneList::iterator it = p.getPlaneList().begin();
|
||||
it != p.getPlaneList().end();
|
||||
++it )
|
||||
{
|
||||
float dist = it->distance( o ), dist_min = dist, dist_max = dist;
|
||||
|
||||
for( int i = 0; i < 3; i ++ ) {
|
||||
dist = it->dotProductNormal( s[i] );
|
||||
if( dist < 0 ) dist_min += dist; else dist_max += dist;
|
||||
}
|
||||
|
||||
if( dist_max < 0 )
|
||||
return false;
|
||||
}
|
||||
|
||||
bb._max = bb._min = o;
|
||||
#if 1
|
||||
for( int i = 0; i < 3; i ++ )
|
||||
for( int j = 0; j < 3; j ++ )
|
||||
if( s[i][j] < 0 ) bb._min[j] += s[i][j]; else bb._max[j] += s[i][j];
|
||||
#else
|
||||
b.expandBy( o + s[0] );
|
||||
b.expandBy( o + s[1] );
|
||||
b.expandBy( o + s[2] );
|
||||
b.expandBy( o + s[0] + s[1] );
|
||||
b.expandBy( o + s[0] + s[2] );
|
||||
b.expandBy( o + s[1] + s[2] );
|
||||
b.expandBy( o + s[0] + s[1] + s[2] );
|
||||
#endif
|
||||
|
||||
#if ( IGNORE_OBJECTS_LARGER_THAN_HEIGHT > 0 )
|
||||
if( bb._max[2] - bb._min[2] > IGNORE_OBJECTS_LARGER_THAN_HEIGHT ) // ignore huge objects
|
||||
return false;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned MinimalCullBoundsShadowMap::ViewData::RemoveOldRenderLeaves
|
||||
( RenderLeafList &rllNew, RenderLeafList &rllOld )
|
||||
{
|
||||
unsigned count = 0;
|
||||
|
||||
std::sort( rllOld.begin(), rllOld.end() );
|
||||
RenderLeafList::iterator itNew, itOld;
|
||||
for( itNew = rllNew.begin(); itNew != rllNew.end() && rllOld.size(); ++itNew )
|
||||
{
|
||||
itOld = std::lower_bound( rllOld.begin(), rllOld.end(), *itNew );
|
||||
|
||||
if( itOld == rllOld.end() || *itOld != *itNew ) continue;
|
||||
// found !
|
||||
rllOld.erase( itOld ); //remove it from old range to speed up search
|
||||
*itNew = NULL; //its not new = invalidate it among new render leaves
|
||||
count ++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
unsigned MinimalCullBoundsShadowMap::ViewData::RemoveIgnoredRenderLeaves
|
||||
( RenderLeafList &rll )
|
||||
{
|
||||
unsigned count = 0;
|
||||
|
||||
for( RenderLeafList::iterator it = rll.begin(); it != rll.end(); ++it )
|
||||
{
|
||||
if( !*it ) continue;
|
||||
|
||||
const char * name = (*it)->_drawable->className();
|
||||
|
||||
// Its a dirty but quick test (not very future proof)
|
||||
if( !name || name[0] != 'L' ) continue;
|
||||
|
||||
if( !strcmp( name, "LightPointDrawable" ) ||
|
||||
!strcmp( name, "LightPointSpriteDrawable" ) )
|
||||
{
|
||||
*it = NULL; //ignored = invalidate this in new render leaves list
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
osg::BoundingBox MinimalCullBoundsShadowMap::ViewData::ComputeRenderLeavesBounds
|
||||
( RenderLeafList &rll, osg::Matrix & projectionToWorld )
|
||||
{
|
||||
osg::BoundingBox bbResult;
|
||||
|
||||
if( rll.size() == 0 ) return bbResult;
|
||||
|
||||
std::sort( rll.begin(), rll.end(), CompareRenderLeavesByMatrices() );
|
||||
|
||||
osg::ref_ptr< osg::RefMatrix > modelview;
|
||||
osg::ref_ptr< osg::RefMatrix > projection;
|
||||
osg::Matrix viewToWorld, modelToWorld, *ptrProjection = NULL,
|
||||
*ptrViewToWorld = &projectionToWorld, *ptrModelToWorld;
|
||||
|
||||
osg::BoundingBox bb;
|
||||
|
||||
// compute bounding boxes but skip old ones (placed at the end as NULLs)
|
||||
for( RenderLeafList::iterator it = rll.begin(); ; ++it ) {
|
||||
// we actually allow to pass one element behind end to flush bb queue
|
||||
osgUtil::RenderLeaf *rl = ( it != rll.end() ? *it : NULL );
|
||||
|
||||
// Don't trust already computed bounds for cull generated drawables
|
||||
// LightPointDrawable & LightPointSpriteDrawable are such examples
|
||||
// they store wrong recorded bounds from very first pass
|
||||
if( rl && rl->_modelview == NULL )
|
||||
rl->_drawable->dirtyBound();
|
||||
|
||||
// Stay as long as possible in model space to minimize matrix ops
|
||||
if( rl && rl->_modelview == modelview && rl->_projection == projection ){
|
||||
bb.expandBy( rl->_drawable->getBound() );
|
||||
} else {
|
||||
if( bb.valid() ) {
|
||||
// Conditions to avoid matrix multiplications
|
||||
if( projection.valid() )
|
||||
{
|
||||
if( projection.get() != ptrProjection )
|
||||
{
|
||||
ptrProjection = projection.get();
|
||||
viewToWorld = *ptrProjection * projectionToWorld;
|
||||
}
|
||||
ptrViewToWorld = &viewToWorld;
|
||||
} else {
|
||||
ptrViewToWorld = &projectionToWorld;
|
||||
}
|
||||
|
||||
if( modelview.valid() )
|
||||
{
|
||||
modelToWorld = *modelview.get() * *ptrViewToWorld;
|
||||
ptrModelToWorld = &modelToWorld;
|
||||
} else {
|
||||
ptrModelToWorld = ptrViewToWorld;
|
||||
}
|
||||
|
||||
for( int i = 0; i < 8; i++ )
|
||||
bbResult.expandBy( bb.corner( i ) * *ptrModelToWorld );
|
||||
}
|
||||
if( !rl ) break;
|
||||
bb = rl->_drawable->getBound();
|
||||
modelview = rl->_modelview;
|
||||
projection = rl->_projection;
|
||||
}
|
||||
}
|
||||
|
||||
rll.clear();
|
||||
|
||||
return bbResult;
|
||||
}
|
||||
|
||||
osg::BoundingBox MinimalCullBoundsShadowMap::ViewData::ComputeRenderLeavesBounds
|
||||
( RenderLeafList &rll, osg::Matrix & projectionToWorld, osg::Polytope & p )
|
||||
{
|
||||
osg::BoundingBox bbResult, bb;
|
||||
|
||||
if( rll.size() == 0 ) return bbResult;
|
||||
|
||||
std::sort( rll.begin(), rll.end(), CompareRenderLeavesByMatrices() );
|
||||
|
||||
osg::ref_ptr< osg::RefMatrix > modelview;
|
||||
osg::ref_ptr< osg::RefMatrix > projection;
|
||||
osg::Matrix viewToWorld, modelToWorld, *ptrProjection = NULL,
|
||||
*ptrViewToWorld = &projectionToWorld, *ptrModelToWorld;
|
||||
|
||||
// compute bounding boxes but skip old ones (placed at the end as NULLs)
|
||||
for( RenderLeafList::iterator it = rll.begin(); it != rll.end(); ++it ) {
|
||||
// we actually allow to pass one element behind end to flush bb queue
|
||||
osgUtil::RenderLeaf *rl = *it;
|
||||
if( !rl ) break;
|
||||
|
||||
// Don't trust already computed bounds for cull generated drawables
|
||||
// LightPointDrawable & LightPointSpriteDrawable are such examples
|
||||
// they store wrong recorded bounds from very first pass
|
||||
if( rl && rl->_modelview == NULL )
|
||||
rl->_drawable->dirtyBound();
|
||||
|
||||
bb = rl->_drawable->getBound();
|
||||
if( !bb.valid() ) continue;
|
||||
|
||||
// Stay as long as possible in model space to minimize matrix ops
|
||||
if( rl->_modelview != modelview || rl->_projection != projection ) {
|
||||
|
||||
projection = rl->_projection;
|
||||
if( projection.valid() )
|
||||
{
|
||||
if( projection.get() != ptrProjection )
|
||||
{
|
||||
ptrProjection = projection.get();
|
||||
viewToWorld = *ptrProjection * projectionToWorld;
|
||||
}
|
||||
ptrViewToWorld = &viewToWorld;
|
||||
} else {
|
||||
ptrViewToWorld = &projectionToWorld;
|
||||
}
|
||||
|
||||
modelview = rl->_modelview;
|
||||
if( modelview.valid() )
|
||||
{
|
||||
modelToWorld = *modelview.get() * *ptrViewToWorld;
|
||||
ptrModelToWorld = &modelToWorld;
|
||||
} else {
|
||||
ptrModelToWorld = ptrViewToWorld;
|
||||
}
|
||||
}
|
||||
|
||||
if( CheckAndMultiplyBoxIfWithinPolytope( bb, *ptrModelToWorld, p ) )
|
||||
bbResult.expandBy( bb );
|
||||
}
|
||||
|
||||
rll.clear();
|
||||
|
||||
return bbResult;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,406 +1,406 @@
|
||||
/* -*-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.
|
||||
*
|
||||
* ViewDependentShadow codes Copyright (C) 2008 Wojciech Lewandowski
|
||||
* Thanks to to my company http://www.ai.com.pl for allowing me free this work.
|
||||
*/
|
||||
|
||||
#include <osgShadow/MinimalDrawBoundsShadowMap>
|
||||
#include <osgShadow/ConvexPolyhedron>
|
||||
#include <osg/PolygonOffset>
|
||||
#include <osgUtil/RenderLeaf>
|
||||
#include <osgShadow/ShadowedScene>
|
||||
#include <osg/FrameBufferObject>
|
||||
#include <osg/BlendEquation>
|
||||
#include <osg/Depth>
|
||||
#include <osg/AlphaFunc>
|
||||
#include <osg/Image>
|
||||
#include <iostream>
|
||||
#include <string.h>
|
||||
|
||||
#define ANALYSIS_DEPTH 1
|
||||
#define USE_FLOAT_IMAGE 1
|
||||
|
||||
using namespace osgShadow;
|
||||
|
||||
MinimalDrawBoundsShadowMap::MinimalDrawBoundsShadowMap(): BaseClass()
|
||||
{
|
||||
}
|
||||
|
||||
MinimalDrawBoundsShadowMap::MinimalDrawBoundsShadowMap
|
||||
(const MinimalDrawBoundsShadowMap& copy, const osg::CopyOp& copyop) :
|
||||
BaseClass(copy,copyop)
|
||||
{
|
||||
}
|
||||
|
||||
MinimalDrawBoundsShadowMap::~MinimalDrawBoundsShadowMap()
|
||||
{
|
||||
}
|
||||
|
||||
void MinimalDrawBoundsShadowMap::ViewData::cullShadowReceivingScene( )
|
||||
{
|
||||
BaseClass::ViewData::cullShadowReceivingScene( );
|
||||
ThisClass::ViewData::cullBoundAnalysisScene( );
|
||||
}
|
||||
|
||||
void MinimalDrawBoundsShadowMap::ViewData::cullBoundAnalysisScene( )
|
||||
{
|
||||
_boundAnalysisCamera->setReferenceFrame( osg::Camera::ABSOLUTE_RF );
|
||||
_boundAnalysisCamera->setViewMatrix( *_cv->getModelViewMatrix() );
|
||||
_boundAnalysisCamera->setProjectionMatrix( _clampedProjection );
|
||||
|
||||
osg::Matrix::value_type l,r,b,t,n,f;
|
||||
_boundAnalysisCamera->getProjectionMatrixAsFrustum( l,r,b,t,n,f );
|
||||
|
||||
_mainCamera = _cv->getRenderStage()->getCamera();
|
||||
|
||||
extendProjection( _boundAnalysisCamera->getProjectionMatrix(),
|
||||
_boundAnalysisCamera->getViewport(), osg::Vec2( 2,2 ) );
|
||||
|
||||
// record the traversal mask on entry so we can reapply it later.
|
||||
unsigned int traversalMask = _cv->getTraversalMask();
|
||||
|
||||
_cv->setTraversalMask( traversalMask &
|
||||
_st->getShadowedScene()->getReceivesShadowTraversalMask() );
|
||||
|
||||
// do RTT camera traversal
|
||||
_boundAnalysisCamera->accept(*_cv);
|
||||
|
||||
// reapply the original traversal mask
|
||||
_cv->setTraversalMask( traversalMask );
|
||||
}
|
||||
|
||||
|
||||
void MinimalDrawBoundsShadowMap::ViewData::createDebugHUD( )
|
||||
{
|
||||
// _hudSize[0] *= 2;
|
||||
_viewportSize[0] *= 2;
|
||||
_orthoSize[0] *= 2;
|
||||
|
||||
MinimalShadowMap::ViewData::createDebugHUD( );
|
||||
|
||||
osg::Camera * camera = _cameraDebugHUD.get();
|
||||
|
||||
osg::Geode* geode = new osg::Geode;
|
||||
camera->addChild( geode );
|
||||
|
||||
osg::Geometry* geometry = osg::createTexturedQuadGeometry
|
||||
( osg::Vec3(_hudOrigin[0]+_hudSize[0],_hudOrigin[1],0),
|
||||
osg::Vec3(_hudSize[0],0,0),
|
||||
osg::Vec3(0,_hudSize[1],0) );
|
||||
|
||||
geode->addDrawable(geometry);
|
||||
|
||||
osg::StateSet* stateset = geometry->getOrCreateStateSet();
|
||||
stateset->setTextureAttributeAndModes
|
||||
(0, _boundAnalysisTexture.get(),osg::StateAttribute::ON );
|
||||
|
||||
#if ANALYSIS_DEPTH
|
||||
osg::Program* program = new osg::Program;
|
||||
program->addShader( _depthColorFragmentShader.get() );
|
||||
stateset->setAttribute( program );
|
||||
stateset->addUniform( new osg::Uniform( "texture" , 0 ) );
|
||||
#else
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
osg::BoundingBox MinimalDrawBoundsShadowMap::ViewData::scanImage
|
||||
( const osg::Image * image, osg::Matrix m )
|
||||
{
|
||||
osg::BoundingBox bb, bbProj;
|
||||
|
||||
int components = osg::Image::computeNumComponents( image->getPixelFormat() );
|
||||
|
||||
if( image->getDataType() == GL_FLOAT ) {
|
||||
float scale = 255.f / 254.f;
|
||||
float * pf = (float *)image->data();
|
||||
for( int y = 0; y < image->t(); y++ ) {
|
||||
float fY = ( 0.5f + y ) / image->t();
|
||||
for( int x = 0; x < image->s(); x++ ) {
|
||||
float fX = ( 0.5f + x ) / image->s();
|
||||
|
||||
if( pf[0] < 1.0 ) {
|
||||
float fMinZ = pf[0] * scale;
|
||||
bbProj.expandBy( osg::Vec3( fX, fY, fMinZ ) );
|
||||
bb.expandBy( osg::Vec3( fX, fY, fMinZ ) * m );
|
||||
|
||||
if( components > 1 ) {
|
||||
float fMaxZ = scale * ( 1.f - pf[1] );
|
||||
bbProj.expandBy( osg::Vec3( fX, fY, fMaxZ ) );
|
||||
bb.expandBy( osg::Vec3( fX, fY, fMaxZ ) * m );
|
||||
}
|
||||
}
|
||||
|
||||
pf += components;
|
||||
}
|
||||
}
|
||||
} else if( image->getDataType() == GL_UNSIGNED_BYTE ) {
|
||||
|
||||
unsigned char * pb = (unsigned char *)image->data();
|
||||
|
||||
float scale = 1.f / 254, bias = 0.5f;
|
||||
for( int y = 0; y < image->t(); y++ ) {
|
||||
float fY = ( 0.5f + y ) / image->t();
|
||||
for( int x = 0; x < image->s(); x++ ) {
|
||||
float fX = ( 0.5f + x ) / image->s();
|
||||
|
||||
if( pb[0] < 255 ) {
|
||||
float fMinZ = scale * (pb[0] - 0.5f);
|
||||
fMinZ = osg::clampTo( fMinZ, 0.f, 1.f );
|
||||
|
||||
bbProj.expandBy( osg::Vec3( fX, fY, fMinZ ) );
|
||||
bb.expandBy( osg::Vec3( fX, fY, fMinZ ) * m );
|
||||
|
||||
if( components > 1 ) {
|
||||
float fMaxZ = scale * (255 - pb[1] + 0.5f);
|
||||
fMaxZ = osg::clampTo( fMaxZ, 0.f, 1.f );
|
||||
|
||||
bbProj.expandBy( osg::Vec3( fX, fY, fMaxZ ) );
|
||||
bb.expandBy( osg::Vec3( fX, fY, fMaxZ ) * m );
|
||||
}
|
||||
}
|
||||
|
||||
pb += components;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bb;
|
||||
}
|
||||
|
||||
void MinimalDrawBoundsShadowMap::ViewData::performBoundAnalysis( const osg::Camera& camera )
|
||||
{
|
||||
if( !_projection.valid() )
|
||||
return;
|
||||
|
||||
osg::Camera::BufferAttachmentMap & bam
|
||||
= const_cast<osg::Camera&>( camera ).getBufferAttachmentMap();
|
||||
#if ANALYSIS_DEPTH
|
||||
osg::Camera::Attachment & attachment = bam[ osg::Camera::DEPTH_BUFFER ];
|
||||
#else
|
||||
osg::Camera::Attachment & attachment = bam[ osg::Camera::COLOR_BUFFER ];
|
||||
#endif
|
||||
|
||||
const osg::ref_ptr< osg::Image > image = attachment._image.get();
|
||||
if( !image.valid() )
|
||||
return;
|
||||
|
||||
osg::Matrix m;
|
||||
m.invert( *_modellingSpaceToWorldPtr *
|
||||
camera.getViewMatrix() *
|
||||
camera.getProjectionMatrix() );
|
||||
|
||||
m.preMult( osg::Matrix::scale( osg::Vec3( 2.f, 2.f, 2.f ) ) *
|
||||
osg::Matrix::translate( osg::Vec3( -1.f, -1.f, -1.f ) ) );
|
||||
|
||||
osg::BoundingBox bb = scanImage( image.get(), m );
|
||||
|
||||
if( getDebugDraw() ) {
|
||||
ConvexPolyhedron p;
|
||||
p.setToBoundingBox( bb );
|
||||
p.transform( *_modellingSpaceToWorldPtr,
|
||||
osg::Matrix::inverse( *_modellingSpaceToWorldPtr ) );
|
||||
|
||||
setDebugPolytope( "scan", p,
|
||||
osg::Vec4( 0,0,0,1 ), osg::Vec4( 0,0,0,0.1 ) );
|
||||
}
|
||||
|
||||
cutScenePolytope( *_modellingSpaceToWorldPtr,
|
||||
osg::Matrix::inverse( *_modellingSpaceToWorldPtr ), bb );
|
||||
|
||||
frameShadowCastingCamera( _mainCamera.get(), _camera.get() );
|
||||
|
||||
_projection->set( _camera->getProjectionMatrix( ) );
|
||||
|
||||
BaseClass::ViewData::_texgen->setPlanesFromMatrix(
|
||||
_camera->getProjectionMatrix() *
|
||||
osg::Matrix::translate(1.0,1.0,1.0) *
|
||||
osg::Matrix::scale(0.5,0.5,0.5) );
|
||||
|
||||
updateDebugGeometry( _mainCamera.get(), _camera.get() );
|
||||
}
|
||||
|
||||
void MinimalDrawBoundsShadowMap::ViewData::recordShadowMapParams( )
|
||||
{
|
||||
const osgUtil::RenderStage * rs = _cv->getCurrentRenderBin()->getStage();
|
||||
|
||||
setShadowCameraProjectionMatrixPtr( _cv->getProjectionMatrix() );
|
||||
|
||||
if( !rs->getRenderBinList().empty() || rs->getBinNum() != 0 )
|
||||
{
|
||||
|
||||
}
|
||||
#if 0
|
||||
MinimalShadowMap::RenderLeafList rll;
|
||||
|
||||
static unsigned pass = 0, c = 0;
|
||||
|
||||
pass++;
|
||||
|
||||
std::set< osg::ref_ptr< osg::RefMatrix > > projections;
|
||||
|
||||
MinimalShadowMap::GetRenderLeaves( , rll );
|
||||
for( unsigned i =0; i < rll.size(); i++ ) {
|
||||
if( rll[i]->_projection.get() != _projection.get() ) {
|
||||
osg::RefMatrix * projection = rll[i]->_projection.get();
|
||||
projections.insert( rll[i]->_projection );
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
if( projections.size() > 0 )
|
||||
_projection = (*projections.begin()).get();
|
||||
|
||||
|
||||
c = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void MinimalDrawBoundsShadowMap::ViewData::init
|
||||
( ThisClass *st, osgUtil::CullVisitor *cv )
|
||||
{
|
||||
BaseClass::ViewData::init( st, cv );
|
||||
|
||||
_camera->setCullCallback
|
||||
( new CameraCullCallback( this, _camera->getCullCallback() ) );
|
||||
|
||||
_boundAnalysisTexture = new osg::Texture2D;
|
||||
_boundAnalysisTexture->setTextureSize
|
||||
( _boundAnalysisSize[0], _boundAnalysisSize[1] );
|
||||
|
||||
_boundAnalysisImage = new osg::Image;
|
||||
|
||||
|
||||
#if ANALYSIS_DEPTH
|
||||
_boundAnalysisImage->allocateImage( _boundAnalysisSize[0],
|
||||
_boundAnalysisSize[1], 1,
|
||||
GL_DEPTH_COMPONENT, GL_FLOAT );
|
||||
|
||||
_boundAnalysisTexture->setInternalFormat(GL_DEPTH_COMPONENT);
|
||||
// _boundAnalysisTexture->setShadowComparison(true);
|
||||
_boundAnalysisTexture->setShadowTextureMode(osg::Texture2D::LUMINANCE);
|
||||
|
||||
|
||||
_boundAnalysisImage->setInternalTextureFormat( GL_DEPTH_COMPONENT );
|
||||
_boundAnalysisTexture->setInternalFormat( GL_DEPTH_COMPONENT );
|
||||
#else
|
||||
|
||||
#if USE_FLOAT_IMAGE
|
||||
_boundAnalysisImage->allocateImage( _boundAnalysisSize[0],
|
||||
_boundAnalysisSize[1], 1,
|
||||
GL_RGBA, GL_FLOAT );
|
||||
|
||||
_boundAnalysisImage->setInternalTextureFormat( GL_RGBA16F_ARB );
|
||||
_boundAnalysisTexture->setInternalFormat(GL_RGBA16F_ARB);
|
||||
#else
|
||||
_boundAnalysisImage->allocateImage( _boundAnalysisSize[0],
|
||||
_boundAnalysisSize[1], 1,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE );
|
||||
|
||||
_boundAnalysisImage->setInternalTextureFormat( GL_RGBA );
|
||||
_boundAnalysisTexture->setInternalFormat( GL_RGBA );
|
||||
#endif
|
||||
|
||||
#endif
|
||||
memset( _boundAnalysisImage->data(), 0, _boundAnalysisImage->getImageSizeInBytes() );
|
||||
|
||||
if( getDebugDraw() )
|
||||
_boundAnalysisTexture->setImage(0, _boundAnalysisImage.get() );
|
||||
|
||||
_boundAnalysisTexture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::NEAREST);
|
||||
_boundAnalysisTexture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::NEAREST);
|
||||
|
||||
// the shadow comparison should fail if object is outside the texture
|
||||
_boundAnalysisTexture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::REPEAT);
|
||||
_boundAnalysisTexture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::REPEAT);
|
||||
|
||||
// set up the render to texture camera.
|
||||
// create the camera
|
||||
_boundAnalysisCamera = new osg::Camera;
|
||||
_boundAnalysisCamera->setName( "AnalysisCamera" );
|
||||
|
||||
_boundAnalysisCamera->setCullCallback( new BaseClass::CameraCullCallback(st) );
|
||||
// _boundAnalysisCamera->setPreDrawCallback( _camera->getPreDrawCallback() );
|
||||
_boundAnalysisCamera->setPostDrawCallback( new CameraPostDrawCallback(this) );
|
||||
|
||||
_boundAnalysisCamera->setClearColor( osg::Vec4(1,1,1,1) );
|
||||
_boundAnalysisCamera->setClearMask(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
|
||||
_boundAnalysisCamera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);
|
||||
|
||||
// set viewport
|
||||
_boundAnalysisCamera->setViewport
|
||||
( 0, 0, _boundAnalysisSize[0], _boundAnalysisSize[1] );
|
||||
|
||||
// set the camera to render before the main camera.
|
||||
_boundAnalysisCamera->setRenderOrder(osg::Camera::PRE_RENDER);
|
||||
|
||||
// tell the camera to use OpenGL frame buffer object where supported.
|
||||
_boundAnalysisCamera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
|
||||
//_boundAnalysisCamera->setRenderTargetImplementation(osg::Camera::SEPERATE_WINDOW);
|
||||
|
||||
const int OVERRIDE_ON = osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON;
|
||||
const int OVERRIDE_OFF = osg::StateAttribute::OVERRIDE | osg::StateAttribute::OFF;
|
||||
|
||||
osg::StateSet* stateset = _boundAnalysisCamera->getOrCreateStateSet();
|
||||
stateset->setAttributeAndModes
|
||||
( new osg::Depth( osg::Depth::LESS, 0.0, 254.f/255.f ), OVERRIDE_ON );
|
||||
|
||||
// stateset->setAttributeAndModes
|
||||
// ( new osg::AlphaFunc( osg::AlphaFunc::EQUAL, 1.f ), OVERRIDE_ON );
|
||||
|
||||
stateset->setRenderBinDetails( 0, "RenderBin",
|
||||
osg::StateSet::OVERRIDE_RENDERBIN_DETAILS );
|
||||
|
||||
osg::Program* program = new osg::Program;
|
||||
|
||||
program->addShader( new osg::Shader( osg::Shader::FRAGMENT,
|
||||
"uniform sampler2D texture; \n"
|
||||
"void main(void) \n"
|
||||
"{ \n"
|
||||
#if ANALYSIS_DEPTH
|
||||
" gl_FragColor = texture2D( texture, gl_TexCoord[0].xy ); \n"
|
||||
#else
|
||||
" gl_FragColor = vec4( gl_FragCoord.z, \n"
|
||||
" 1.-gl_FragCoord.z, \n"
|
||||
" 1., \n"
|
||||
" texture2D( texture, gl_TexCoord[0].xy ).a ); \n"
|
||||
#endif
|
||||
"} \n"
|
||||
) ); // program->addShader Fragment
|
||||
|
||||
program->addShader( new osg::Shader( osg::Shader::VERTEX,
|
||||
"void main(void) \n"
|
||||
"{ \n"
|
||||
" gl_Position = ftransform(); \n"
|
||||
" gl_TexCoord[0] = gl_MultiTexCoord0; \n"
|
||||
"} \n"
|
||||
) ); // program->addShader Vertex
|
||||
|
||||
stateset->setAttribute( program, OVERRIDE_ON );
|
||||
|
||||
// attach the texture and use it as the color buffer.
|
||||
#if ANALYSIS_DEPTH
|
||||
// _boundAnalysisCamera->attach(osg::Camera::DEPTH_BUFFER, _boundAnalysisTexture.get());
|
||||
_boundAnalysisCamera->attach(osg::Camera::DEPTH_BUFFER, _boundAnalysisImage.get());
|
||||
|
||||
stateset->setMode( GL_BLEND, OVERRIDE_OFF );
|
||||
#else
|
||||
// _boundAnalysisCamera->attach(osg::Camera::COLOR_BUFFER, _boundAnalysisTexture.get());
|
||||
_boundAnalysisCamera->attach(osg::Camera::COLOR_BUFFER, _boundAnalysisImage.get());
|
||||
|
||||
stateset->setAttributeAndModes
|
||||
( new osg::BlendEquation( osg::BlendEquation::RGBA_MIN ), OVERRIDE_ON );
|
||||
|
||||
stateset->setMode( GL_DEPTH_TEST, OVERRIDE_OFF );
|
||||
#endif
|
||||
}
|
||||
/* -*-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.
|
||||
*
|
||||
* ViewDependentShadow codes Copyright (C) 2008 Wojciech Lewandowski
|
||||
* Thanks to to my company http://www.ai.com.pl for allowing me free this work.
|
||||
*/
|
||||
|
||||
#include <osgShadow/MinimalDrawBoundsShadowMap>
|
||||
#include <osgShadow/ConvexPolyhedron>
|
||||
#include <osg/PolygonOffset>
|
||||
#include <osgUtil/RenderLeaf>
|
||||
#include <osgShadow/ShadowedScene>
|
||||
#include <osg/FrameBufferObject>
|
||||
#include <osg/BlendEquation>
|
||||
#include <osg/Depth>
|
||||
#include <osg/AlphaFunc>
|
||||
#include <osg/Image>
|
||||
#include <iostream>
|
||||
#include <string.h>
|
||||
|
||||
#define ANALYSIS_DEPTH 1
|
||||
#define USE_FLOAT_IMAGE 1
|
||||
|
||||
using namespace osgShadow;
|
||||
|
||||
MinimalDrawBoundsShadowMap::MinimalDrawBoundsShadowMap(): BaseClass()
|
||||
{
|
||||
}
|
||||
|
||||
MinimalDrawBoundsShadowMap::MinimalDrawBoundsShadowMap
|
||||
(const MinimalDrawBoundsShadowMap& copy, const osg::CopyOp& copyop) :
|
||||
BaseClass(copy,copyop)
|
||||
{
|
||||
}
|
||||
|
||||
MinimalDrawBoundsShadowMap::~MinimalDrawBoundsShadowMap()
|
||||
{
|
||||
}
|
||||
|
||||
void MinimalDrawBoundsShadowMap::ViewData::cullShadowReceivingScene( )
|
||||
{
|
||||
BaseClass::ViewData::cullShadowReceivingScene( );
|
||||
ThisClass::ViewData::cullBoundAnalysisScene( );
|
||||
}
|
||||
|
||||
void MinimalDrawBoundsShadowMap::ViewData::cullBoundAnalysisScene( )
|
||||
{
|
||||
_boundAnalysisCamera->setReferenceFrame( osg::Camera::ABSOLUTE_RF );
|
||||
_boundAnalysisCamera->setViewMatrix( *_cv->getModelViewMatrix() );
|
||||
_boundAnalysisCamera->setProjectionMatrix( _clampedProjection );
|
||||
|
||||
osg::Matrix::value_type l,r,b,t,n,f;
|
||||
_boundAnalysisCamera->getProjectionMatrixAsFrustum( l,r,b,t,n,f );
|
||||
|
||||
_mainCamera = _cv->getRenderStage()->getCamera();
|
||||
|
||||
extendProjection( _boundAnalysisCamera->getProjectionMatrix(),
|
||||
_boundAnalysisCamera->getViewport(), osg::Vec2( 2,2 ) );
|
||||
|
||||
// record the traversal mask on entry so we can reapply it later.
|
||||
unsigned int traversalMask = _cv->getTraversalMask();
|
||||
|
||||
_cv->setTraversalMask( traversalMask &
|
||||
_st->getShadowedScene()->getReceivesShadowTraversalMask() );
|
||||
|
||||
// do RTT camera traversal
|
||||
_boundAnalysisCamera->accept(*_cv);
|
||||
|
||||
// reapply the original traversal mask
|
||||
_cv->setTraversalMask( traversalMask );
|
||||
}
|
||||
|
||||
|
||||
void MinimalDrawBoundsShadowMap::ViewData::createDebugHUD( )
|
||||
{
|
||||
// _hudSize[0] *= 2;
|
||||
_viewportSize[0] *= 2;
|
||||
_orthoSize[0] *= 2;
|
||||
|
||||
MinimalShadowMap::ViewData::createDebugHUD( );
|
||||
|
||||
osg::Camera * camera = _cameraDebugHUD.get();
|
||||
|
||||
osg::Geode* geode = new osg::Geode;
|
||||
camera->addChild( geode );
|
||||
|
||||
osg::Geometry* geometry = osg::createTexturedQuadGeometry
|
||||
( osg::Vec3(_hudOrigin[0]+_hudSize[0],_hudOrigin[1],0),
|
||||
osg::Vec3(_hudSize[0],0,0),
|
||||
osg::Vec3(0,_hudSize[1],0) );
|
||||
|
||||
geode->addDrawable(geometry);
|
||||
|
||||
osg::StateSet* stateset = geometry->getOrCreateStateSet();
|
||||
stateset->setTextureAttributeAndModes
|
||||
(0, _boundAnalysisTexture.get(),osg::StateAttribute::ON );
|
||||
|
||||
#if ANALYSIS_DEPTH
|
||||
osg::Program* program = new osg::Program;
|
||||
program->addShader( _depthColorFragmentShader.get() );
|
||||
stateset->setAttribute( program );
|
||||
stateset->addUniform( new osg::Uniform( "texture" , 0 ) );
|
||||
#else
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
osg::BoundingBox MinimalDrawBoundsShadowMap::ViewData::scanImage
|
||||
( const osg::Image * image, osg::Matrix m )
|
||||
{
|
||||
osg::BoundingBox bb, bbProj;
|
||||
|
||||
int components = osg::Image::computeNumComponents( image->getPixelFormat() );
|
||||
|
||||
if( image->getDataType() == GL_FLOAT ) {
|
||||
float scale = 255.f / 254.f;
|
||||
float * pf = (float *)image->data();
|
||||
for( int y = 0; y < image->t(); y++ ) {
|
||||
float fY = ( 0.5f + y ) / image->t();
|
||||
for( int x = 0; x < image->s(); x++ ) {
|
||||
float fX = ( 0.5f + x ) / image->s();
|
||||
|
||||
if( pf[0] < 1.0 ) {
|
||||
float fMinZ = pf[0] * scale;
|
||||
bbProj.expandBy( osg::Vec3( fX, fY, fMinZ ) );
|
||||
bb.expandBy( osg::Vec3( fX, fY, fMinZ ) * m );
|
||||
|
||||
if( components > 1 ) {
|
||||
float fMaxZ = scale * ( 1.f - pf[1] );
|
||||
bbProj.expandBy( osg::Vec3( fX, fY, fMaxZ ) );
|
||||
bb.expandBy( osg::Vec3( fX, fY, fMaxZ ) * m );
|
||||
}
|
||||
}
|
||||
|
||||
pf += components;
|
||||
}
|
||||
}
|
||||
} else if( image->getDataType() == GL_UNSIGNED_BYTE ) {
|
||||
|
||||
unsigned char * pb = (unsigned char *)image->data();
|
||||
|
||||
float scale = 1.f / 254, bias = 0.5f;
|
||||
for( int y = 0; y < image->t(); y++ ) {
|
||||
float fY = ( 0.5f + y ) / image->t();
|
||||
for( int x = 0; x < image->s(); x++ ) {
|
||||
float fX = ( 0.5f + x ) / image->s();
|
||||
|
||||
if( pb[0] < 255 ) {
|
||||
float fMinZ = scale * (pb[0] - 0.5f);
|
||||
fMinZ = osg::clampTo( fMinZ, 0.f, 1.f );
|
||||
|
||||
bbProj.expandBy( osg::Vec3( fX, fY, fMinZ ) );
|
||||
bb.expandBy( osg::Vec3( fX, fY, fMinZ ) * m );
|
||||
|
||||
if( components > 1 ) {
|
||||
float fMaxZ = scale * (255 - pb[1] + 0.5f);
|
||||
fMaxZ = osg::clampTo( fMaxZ, 0.f, 1.f );
|
||||
|
||||
bbProj.expandBy( osg::Vec3( fX, fY, fMaxZ ) );
|
||||
bb.expandBy( osg::Vec3( fX, fY, fMaxZ ) * m );
|
||||
}
|
||||
}
|
||||
|
||||
pb += components;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bb;
|
||||
}
|
||||
|
||||
void MinimalDrawBoundsShadowMap::ViewData::performBoundAnalysis( const osg::Camera& camera )
|
||||
{
|
||||
if( !_projection.valid() )
|
||||
return;
|
||||
|
||||
osg::Camera::BufferAttachmentMap & bam
|
||||
= const_cast<osg::Camera&>( camera ).getBufferAttachmentMap();
|
||||
#if ANALYSIS_DEPTH
|
||||
osg::Camera::Attachment & attachment = bam[ osg::Camera::DEPTH_BUFFER ];
|
||||
#else
|
||||
osg::Camera::Attachment & attachment = bam[ osg::Camera::COLOR_BUFFER ];
|
||||
#endif
|
||||
|
||||
const osg::ref_ptr< osg::Image > image = attachment._image.get();
|
||||
if( !image.valid() )
|
||||
return;
|
||||
|
||||
osg::Matrix m;
|
||||
m.invert( *_modellingSpaceToWorldPtr *
|
||||
camera.getViewMatrix() *
|
||||
camera.getProjectionMatrix() );
|
||||
|
||||
m.preMult( osg::Matrix::scale( osg::Vec3( 2.f, 2.f, 2.f ) ) *
|
||||
osg::Matrix::translate( osg::Vec3( -1.f, -1.f, -1.f ) ) );
|
||||
|
||||
osg::BoundingBox bb = scanImage( image.get(), m );
|
||||
|
||||
if( getDebugDraw() ) {
|
||||
ConvexPolyhedron p;
|
||||
p.setToBoundingBox( bb );
|
||||
p.transform( *_modellingSpaceToWorldPtr,
|
||||
osg::Matrix::inverse( *_modellingSpaceToWorldPtr ) );
|
||||
|
||||
setDebugPolytope( "scan", p,
|
||||
osg::Vec4( 0,0,0,1 ), osg::Vec4( 0,0,0,0.1 ) );
|
||||
}
|
||||
|
||||
cutScenePolytope( *_modellingSpaceToWorldPtr,
|
||||
osg::Matrix::inverse( *_modellingSpaceToWorldPtr ), bb );
|
||||
|
||||
frameShadowCastingCamera( _mainCamera.get(), _camera.get() );
|
||||
|
||||
_projection->set( _camera->getProjectionMatrix( ) );
|
||||
|
||||
BaseClass::ViewData::_texgen->setPlanesFromMatrix(
|
||||
_camera->getProjectionMatrix() *
|
||||
osg::Matrix::translate(1.0,1.0,1.0) *
|
||||
osg::Matrix::scale(0.5,0.5,0.5) );
|
||||
|
||||
updateDebugGeometry( _mainCamera.get(), _camera.get() );
|
||||
}
|
||||
|
||||
void MinimalDrawBoundsShadowMap::ViewData::recordShadowMapParams( )
|
||||
{
|
||||
const osgUtil::RenderStage * rs = _cv->getCurrentRenderBin()->getStage();
|
||||
|
||||
setShadowCameraProjectionMatrixPtr( _cv->getProjectionMatrix() );
|
||||
|
||||
if( !rs->getRenderBinList().empty() || rs->getBinNum() != 0 )
|
||||
{
|
||||
|
||||
}
|
||||
#if 0
|
||||
MinimalShadowMap::RenderLeafList rll;
|
||||
|
||||
static unsigned pass = 0, c = 0;
|
||||
|
||||
pass++;
|
||||
|
||||
std::set< osg::ref_ptr< osg::RefMatrix > > projections;
|
||||
|
||||
MinimalShadowMap::GetRenderLeaves( , rll );
|
||||
for( unsigned i =0; i < rll.size(); i++ ) {
|
||||
if( rll[i]->_projection.get() != _projection.get() ) {
|
||||
osg::RefMatrix * projection = rll[i]->_projection.get();
|
||||
projections.insert( rll[i]->_projection );
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
if( projections.size() > 0 )
|
||||
_projection = (*projections.begin()).get();
|
||||
|
||||
|
||||
c = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void MinimalDrawBoundsShadowMap::ViewData::init
|
||||
( ThisClass *st, osgUtil::CullVisitor *cv )
|
||||
{
|
||||
BaseClass::ViewData::init( st, cv );
|
||||
|
||||
_camera->setCullCallback
|
||||
( new CameraCullCallback( this, _camera->getCullCallback() ) );
|
||||
|
||||
_boundAnalysisTexture = new osg::Texture2D;
|
||||
_boundAnalysisTexture->setTextureSize
|
||||
( _boundAnalysisSize[0], _boundAnalysisSize[1] );
|
||||
|
||||
_boundAnalysisImage = new osg::Image;
|
||||
|
||||
|
||||
#if ANALYSIS_DEPTH
|
||||
_boundAnalysisImage->allocateImage( _boundAnalysisSize[0],
|
||||
_boundAnalysisSize[1], 1,
|
||||
GL_DEPTH_COMPONENT, GL_FLOAT );
|
||||
|
||||
_boundAnalysisTexture->setInternalFormat(GL_DEPTH_COMPONENT);
|
||||
// _boundAnalysisTexture->setShadowComparison(true);
|
||||
_boundAnalysisTexture->setShadowTextureMode(osg::Texture2D::LUMINANCE);
|
||||
|
||||
|
||||
_boundAnalysisImage->setInternalTextureFormat( GL_DEPTH_COMPONENT );
|
||||
_boundAnalysisTexture->setInternalFormat( GL_DEPTH_COMPONENT );
|
||||
#else
|
||||
|
||||
#if USE_FLOAT_IMAGE
|
||||
_boundAnalysisImage->allocateImage( _boundAnalysisSize[0],
|
||||
_boundAnalysisSize[1], 1,
|
||||
GL_RGBA, GL_FLOAT );
|
||||
|
||||
_boundAnalysisImage->setInternalTextureFormat( GL_RGBA16F_ARB );
|
||||
_boundAnalysisTexture->setInternalFormat(GL_RGBA16F_ARB);
|
||||
#else
|
||||
_boundAnalysisImage->allocateImage( _boundAnalysisSize[0],
|
||||
_boundAnalysisSize[1], 1,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE );
|
||||
|
||||
_boundAnalysisImage->setInternalTextureFormat( GL_RGBA );
|
||||
_boundAnalysisTexture->setInternalFormat( GL_RGBA );
|
||||
#endif
|
||||
|
||||
#endif
|
||||
memset( _boundAnalysisImage->data(), 0, _boundAnalysisImage->getImageSizeInBytes() );
|
||||
|
||||
if( getDebugDraw() )
|
||||
_boundAnalysisTexture->setImage(0, _boundAnalysisImage.get() );
|
||||
|
||||
_boundAnalysisTexture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::NEAREST);
|
||||
_boundAnalysisTexture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::NEAREST);
|
||||
|
||||
// the shadow comparison should fail if object is outside the texture
|
||||
_boundAnalysisTexture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::REPEAT);
|
||||
_boundAnalysisTexture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::REPEAT);
|
||||
|
||||
// set up the render to texture camera.
|
||||
// create the camera
|
||||
_boundAnalysisCamera = new osg::Camera;
|
||||
_boundAnalysisCamera->setName( "AnalysisCamera" );
|
||||
|
||||
_boundAnalysisCamera->setCullCallback( new BaseClass::CameraCullCallback(st) );
|
||||
// _boundAnalysisCamera->setPreDrawCallback( _camera->getPreDrawCallback() );
|
||||
_boundAnalysisCamera->setPostDrawCallback( new CameraPostDrawCallback(this) );
|
||||
|
||||
_boundAnalysisCamera->setClearColor( osg::Vec4(1,1,1,1) );
|
||||
_boundAnalysisCamera->setClearMask(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
|
||||
_boundAnalysisCamera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);
|
||||
|
||||
// set viewport
|
||||
_boundAnalysisCamera->setViewport
|
||||
( 0, 0, _boundAnalysisSize[0], _boundAnalysisSize[1] );
|
||||
|
||||
// set the camera to render before the main camera.
|
||||
_boundAnalysisCamera->setRenderOrder(osg::Camera::PRE_RENDER);
|
||||
|
||||
// tell the camera to use OpenGL frame buffer object where supported.
|
||||
_boundAnalysisCamera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
|
||||
//_boundAnalysisCamera->setRenderTargetImplementation(osg::Camera::SEPERATE_WINDOW);
|
||||
|
||||
const int OVERRIDE_ON = osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON;
|
||||
const int OVERRIDE_OFF = osg::StateAttribute::OVERRIDE | osg::StateAttribute::OFF;
|
||||
|
||||
osg::StateSet* stateset = _boundAnalysisCamera->getOrCreateStateSet();
|
||||
stateset->setAttributeAndModes
|
||||
( new osg::Depth( osg::Depth::LESS, 0.0, 254.f/255.f ), OVERRIDE_ON );
|
||||
|
||||
// stateset->setAttributeAndModes
|
||||
// ( new osg::AlphaFunc( osg::AlphaFunc::EQUAL, 1.f ), OVERRIDE_ON );
|
||||
|
||||
stateset->setRenderBinDetails( 0, "RenderBin",
|
||||
osg::StateSet::OVERRIDE_RENDERBIN_DETAILS );
|
||||
|
||||
osg::Program* program = new osg::Program;
|
||||
|
||||
program->addShader( new osg::Shader( osg::Shader::FRAGMENT,
|
||||
"uniform sampler2D texture; \n"
|
||||
"void main(void) \n"
|
||||
"{ \n"
|
||||
#if ANALYSIS_DEPTH
|
||||
" gl_FragColor = texture2D( texture, gl_TexCoord[0].xy ); \n"
|
||||
#else
|
||||
" gl_FragColor = vec4( gl_FragCoord.z, \n"
|
||||
" 1.-gl_FragCoord.z, \n"
|
||||
" 1., \n"
|
||||
" texture2D( texture, gl_TexCoord[0].xy ).a ); \n"
|
||||
#endif
|
||||
"} \n"
|
||||
) ); // program->addShader Fragment
|
||||
|
||||
program->addShader( new osg::Shader( osg::Shader::VERTEX,
|
||||
"void main(void) \n"
|
||||
"{ \n"
|
||||
" gl_Position = ftransform(); \n"
|
||||
" gl_TexCoord[0] = gl_MultiTexCoord0; \n"
|
||||
"} \n"
|
||||
) ); // program->addShader Vertex
|
||||
|
||||
stateset->setAttribute( program, OVERRIDE_ON );
|
||||
|
||||
// attach the texture and use it as the color buffer.
|
||||
#if ANALYSIS_DEPTH
|
||||
// _boundAnalysisCamera->attach(osg::Camera::DEPTH_BUFFER, _boundAnalysisTexture.get());
|
||||
_boundAnalysisCamera->attach(osg::Camera::DEPTH_BUFFER, _boundAnalysisImage.get());
|
||||
|
||||
stateset->setMode( GL_BLEND, OVERRIDE_OFF );
|
||||
#else
|
||||
// _boundAnalysisCamera->attach(osg::Camera::COLOR_BUFFER, _boundAnalysisTexture.get());
|
||||
_boundAnalysisCamera->attach(osg::Camera::COLOR_BUFFER, _boundAnalysisImage.get());
|
||||
|
||||
stateset->setAttributeAndModes
|
||||
( new osg::BlendEquation( osg::BlendEquation::RGBA_MIN ), OVERRIDE_ON );
|
||||
|
||||
stateset->setMode( GL_DEPTH_TEST, OVERRIDE_OFF );
|
||||
#endif
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,127 +1,127 @@
|
||||
/* -*-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.
|
||||
*
|
||||
* ViewDependentShadow codes Copyright (C) 2008 Wojciech Lewandowski
|
||||
* Thanks to to my company http://www.ai.com.pl for allowing me free this work.
|
||||
*/
|
||||
|
||||
#include <osgShadow/ViewDependentShadowTechnique>
|
||||
#include <osgShadow/ShadowedScene>
|
||||
|
||||
using namespace osgShadow;
|
||||
|
||||
|
||||
ViewDependentShadowTechnique::ViewDependentShadowTechnique()
|
||||
{
|
||||
dirty();
|
||||
}
|
||||
|
||||
ViewDependentShadowTechnique::ViewDependentShadowTechnique
|
||||
(const ViewDependentShadowTechnique& copy, const osg::CopyOp& copyop):
|
||||
ShadowTechnique(copy,copyop)
|
||||
{
|
||||
dirty();
|
||||
}
|
||||
|
||||
ViewDependentShadowTechnique::~ViewDependentShadowTechnique(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ViewDependentShadowTechnique::traverse(osg::NodeVisitor& nv)
|
||||
{
|
||||
osgShadow::ShadowTechnique::traverse(nv);
|
||||
}
|
||||
|
||||
void ViewDependentShadowTechnique::dirty()
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_viewDataMapMutex);
|
||||
|
||||
osgShadow::ShadowTechnique::_dirty = true;
|
||||
|
||||
for( ViewDataMap::iterator mitr = _viewDataMap.begin();
|
||||
mitr != _viewDataMap.end();
|
||||
++mitr )
|
||||
{
|
||||
mitr->second->dirty( true );
|
||||
}
|
||||
}
|
||||
|
||||
void ViewDependentShadowTechnique::init()
|
||||
{
|
||||
//osgShadow::ShadowTechnique::init( );
|
||||
osgShadow::ShadowTechnique::_dirty = false;
|
||||
}
|
||||
|
||||
void ViewDependentShadowTechnique::update(osg::NodeVisitor& nv)
|
||||
{
|
||||
//osgShadow::ShadowTechnique::update( nv );
|
||||
osgShadow::ShadowTechnique::_shadowedScene->osg::Group::traverse(nv);
|
||||
}
|
||||
|
||||
void ViewDependentShadowTechnique::cull(osgUtil::CullVisitor& cv)
|
||||
{
|
||||
//osgShadow::ShadowTechnique::cull( cv );
|
||||
|
||||
ViewData * vd = getViewDependentData( &cv );
|
||||
|
||||
if ( !vd || vd->_dirty || vd->_cv != &cv || vd->_st != this ) {
|
||||
vd = initViewDependentData( &cv, vd );
|
||||
setViewDependentData( &cv, vd );
|
||||
}
|
||||
|
||||
if( vd ) {
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(vd->_mutex);
|
||||
vd->cull();
|
||||
} else {
|
||||
osgShadow::ShadowTechnique::_shadowedScene->osg::Group::traverse(cv);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewDependentShadowTechnique::cleanSceneGraph()
|
||||
{
|
||||
//osgShadow::ShadowTechnique::cleanSceneGraph( );
|
||||
}
|
||||
|
||||
ViewDependentShadowTechnique::ViewData *
|
||||
ViewDependentShadowTechnique::getViewDependentData( osgUtil::CullVisitor * cv )
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_viewDataMapMutex);
|
||||
return _viewDataMap[ cv ].get();
|
||||
}
|
||||
|
||||
void ViewDependentShadowTechnique::setViewDependentData
|
||||
( osgUtil::CullVisitor * cv, ViewData * data )
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_viewDataMapMutex);
|
||||
_viewDataMap[ cv ] = data;
|
||||
}
|
||||
|
||||
void ViewDependentShadowTechnique::ViewData::dirty( bool flag )
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
|
||||
_dirty = flag;
|
||||
}
|
||||
|
||||
void ViewDependentShadowTechnique::ViewData::init
|
||||
( ViewDependentShadowTechnique *st, osgUtil::CullVisitor * cv )
|
||||
{
|
||||
_cv = cv;
|
||||
_st = st;
|
||||
dirty( false );
|
||||
}
|
||||
|
||||
void ViewDependentShadowTechnique::ViewData::cull( void )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* -*-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.
|
||||
*
|
||||
* ViewDependentShadow codes Copyright (C) 2008 Wojciech Lewandowski
|
||||
* Thanks to to my company http://www.ai.com.pl for allowing me free this work.
|
||||
*/
|
||||
|
||||
#include <osgShadow/ViewDependentShadowTechnique>
|
||||
#include <osgShadow/ShadowedScene>
|
||||
|
||||
using namespace osgShadow;
|
||||
|
||||
|
||||
ViewDependentShadowTechnique::ViewDependentShadowTechnique()
|
||||
{
|
||||
dirty();
|
||||
}
|
||||
|
||||
ViewDependentShadowTechnique::ViewDependentShadowTechnique
|
||||
(const ViewDependentShadowTechnique& copy, const osg::CopyOp& copyop):
|
||||
ShadowTechnique(copy,copyop)
|
||||
{
|
||||
dirty();
|
||||
}
|
||||
|
||||
ViewDependentShadowTechnique::~ViewDependentShadowTechnique(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ViewDependentShadowTechnique::traverse(osg::NodeVisitor& nv)
|
||||
{
|
||||
osgShadow::ShadowTechnique::traverse(nv);
|
||||
}
|
||||
|
||||
void ViewDependentShadowTechnique::dirty()
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_viewDataMapMutex);
|
||||
|
||||
osgShadow::ShadowTechnique::_dirty = true;
|
||||
|
||||
for( ViewDataMap::iterator mitr = _viewDataMap.begin();
|
||||
mitr != _viewDataMap.end();
|
||||
++mitr )
|
||||
{
|
||||
mitr->second->dirty( true );
|
||||
}
|
||||
}
|
||||
|
||||
void ViewDependentShadowTechnique::init()
|
||||
{
|
||||
//osgShadow::ShadowTechnique::init( );
|
||||
osgShadow::ShadowTechnique::_dirty = false;
|
||||
}
|
||||
|
||||
void ViewDependentShadowTechnique::update(osg::NodeVisitor& nv)
|
||||
{
|
||||
//osgShadow::ShadowTechnique::update( nv );
|
||||
osgShadow::ShadowTechnique::_shadowedScene->osg::Group::traverse(nv);
|
||||
}
|
||||
|
||||
void ViewDependentShadowTechnique::cull(osgUtil::CullVisitor& cv)
|
||||
{
|
||||
//osgShadow::ShadowTechnique::cull( cv );
|
||||
|
||||
ViewData * vd = getViewDependentData( &cv );
|
||||
|
||||
if ( !vd || vd->_dirty || vd->_cv != &cv || vd->_st != this ) {
|
||||
vd = initViewDependentData( &cv, vd );
|
||||
setViewDependentData( &cv, vd );
|
||||
}
|
||||
|
||||
if( vd ) {
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(vd->_mutex);
|
||||
vd->cull();
|
||||
} else {
|
||||
osgShadow::ShadowTechnique::_shadowedScene->osg::Group::traverse(cv);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewDependentShadowTechnique::cleanSceneGraph()
|
||||
{
|
||||
//osgShadow::ShadowTechnique::cleanSceneGraph( );
|
||||
}
|
||||
|
||||
ViewDependentShadowTechnique::ViewData *
|
||||
ViewDependentShadowTechnique::getViewDependentData( osgUtil::CullVisitor * cv )
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_viewDataMapMutex);
|
||||
return _viewDataMap[ cv ].get();
|
||||
}
|
||||
|
||||
void ViewDependentShadowTechnique::setViewDependentData
|
||||
( osgUtil::CullVisitor * cv, ViewData * data )
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_viewDataMapMutex);
|
||||
_viewDataMap[ cv ] = data;
|
||||
}
|
||||
|
||||
void ViewDependentShadowTechnique::ViewData::dirty( bool flag )
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
|
||||
_dirty = flag;
|
||||
}
|
||||
|
||||
void ViewDependentShadowTechnique::ViewData::init
|
||||
( ViewDependentShadowTechnique *st, osgUtil::CullVisitor * cv )
|
||||
{
|
||||
_cv = cv;
|
||||
_st = st;
|
||||
dirty( false );
|
||||
}
|
||||
|
||||
void ViewDependentShadowTechnique::ViewData::cull( void )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user