Hi Wojtek, I've gone for the solution of forward declaring this classes in the headers, this now checked into SVN.
On Fri, Jan 23, 2009 at 9:56 AM, Wojciech Lewandowski <[email protected]> wrote: > Hi Robert and Roger, > > I suppose good solution for this problem would be defining them as a > subclasses of DebugShadowMap and ShadowMap. This will correspond to actual > scope of their usage. > > Cheers, > Wojtek > > ----- Original Message ----- From: "Robert Osfield" > <[email protected]> > To: "OpenSceneGraph Submissions" <[email protected]> > Sent: Friday, January 23, 2009 10:28 AM > Subject: Re: [osg-submissions] A small fix in for osgShadow > > >> Hi Roger, >> >> Moving a class definition into a function implementation makes me >> nervous about the possibile consequence for older compilers handling >> this. I don't know whether it would be supported or not, but... given >> it's not a technique used in the rest the OSG I don't have a prior art >> to confirm that it's OK to roll out. >> >> Would enclosing the class in a local namespace be sufficient? >> >> Robert. >> >> On Thu, Jan 22, 2009 at 2:23 PM, Roger James >> <[email protected]> wrote: >>> >>> Robert, >>> >>> This fix moves a couple of debug callback functions that have the same >>> name >>> from the global context into the local function context where they are >>> used. >>> This avoids some obscure problems when they used in DLLs generated by MS >>> VC8.1. >>> >>> Roger >>> >>> /* -*-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/DebugShadowMap> >>> #include <osgShadow/ConvexPolyhedron> >>> #include <osgUtil/RenderLeaf> >>> #include <osg/Geometry> >>> #include <osg/PrimitiveSet> >>> #include <osg/MatrixTransform> >>> #include <osg/Depth> >>> #include <iostream> >>> #include <iomanip> >>> >>> using namespace osgShadow; >>> >>> >>> #define VECTOR_LENGTH( v ) ( sizeof(v)/sizeof(v[0]) ) >>> >>> #define DEFAULT_DEBUG_HUD_SIZE_X 256 >>> #define DEFAULT_DEBUG_HUD_SIZE_Y 256 >>> #define DEFAULT_DEBUG_HUD_ORIGIN_X 8 >>> #define DEFAULT_DEBUG_HUD_ORIGIN_Y 8 >>> >>> DebugShadowMap::DebugShadowMap(): >>> BaseClass(), >>> _hudSize( 2, 2 ), >>> _hudOrigin( -1, -1 ), >>> _viewportSize( DEFAULT_DEBUG_HUD_SIZE_X, DEFAULT_DEBUG_HUD_SIZE_Y ), >>> _viewportOrigin( DEFAULT_DEBUG_HUD_ORIGIN_X, DEFAULT_DEBUG_HUD_ORIGIN_Y >>> ), >>> _orthoSize( 2, 2 ), >>> _orthoOrigin( -1, -1 ), >>> _doDebugDraw( false ) >>> { >>> >>> // Why this fancy 24 bit depth to 24 bit rainbow colors shader ? >>> // >>> // Depth values cannot be easily cast on color component because they >>> are: >>> // a) 24 or 32 bit and we loose lots of precision when cast on 8 bit >>> // b) depth value distribution is non linear due to projection division >>> // when cast on componenent color there is usually very minor shade >>> variety >>> // and its often difficult to notice that there is anything in the >>> buffer >>> // >>> // Shader looks complex but it is used only for debug head-up rectangle >>> // so performance impact is not significant. >>> >>> _depthColorFragmentShader = new osg::Shader( osg::Shader::FRAGMENT, >>> #if 0 >>> "uniform sampler2D texture; >>> \n" >>> " >>> \n" >>> "void main(void) >>> \n" >>> "{ >>> \n" >>> " float f = texture2D( texture, vec3( gl_TexCoord[0].xy, 1.0).xy >>> ).r; \n" >>> " gl_FragColor = vec4( 0.0, 1.0 - f, 0.5 - f, 0.5 ); >>> \n" >>> "} >>> \n" >>> #else >>> "uniform sampler2D texture; >>> \n" >>> " >>> \n" >>> "void main(void) >>> \n" >>> "{ >>> \n" >>> " float f = texture2D( texture, vec3( gl_TexCoord[0].xy, 1.0).xy >>> ).r; \n" >>> " >>> \n" >>> " f = 256.0 * f; >>> \n" >>> " float fC = floor( f ) / 256.0; >>> \n" >>> " >>> \n" >>> " f = 256.0 * fract( f ); >>> \n" >>> " float fS = floor( f ) / 256.0; >>> \n" >>> " >>> \n" >>> " f = 256.0 * fract( f ); >>> \n" >>> " float fH = floor( f ) / 256.0; >>> \n" >>> " >>> \n" >>> " fS *= 0.5; >>> \n" >>> " fH = ( fH * 0.34 + 0.66 ) * ( 1.0 - fS ); >>> \n" >>> " >>> \n" >>> " vec3 rgb = vec3( ( fC > 0.5 ? ( 1.0 - fC ) : fC ), >>> \n" >>> " abs( fC - 0.333333 ), >>> \n" >>> " abs( fC - 0.666667 ) ); >>> \n" >>> " >>> \n" >>> " rgb = min( vec3( 1.0, 1.0, 1.0 ), 3.0 * rgb ); >>> \n" >>> " >>> \n" >>> " float fMax = max( max( rgb.r, rgb.g ), rgb.b ); >>> \n" >>> " fMax = 1.0 / fMax; >>> \n" >>> " >>> \n" >>> " vec3 color = fMax * rgb; >>> \n" >>> " >>> \n" >>> " gl_FragColor = vec4( fS + fH * color, 1 ) * gl_Color; >>> \n" >>> "} >>> \n" >>> #endif >>> ); // end _depthColorFragmentShader >>> } >>> >>> DebugShadowMap::DebugShadowMap >>> (const DebugShadowMap& copy, const osg::CopyOp& copyop) : >>> BaseClass(copy,copyop), >>> _hudSize( copy._hudSize ), >>> _hudOrigin( copy._hudOrigin ), >>> _viewportSize( copy._viewportSize ), >>> _viewportOrigin( copy._viewportOrigin ), >>> _orthoSize( copy._viewportOrigin ), >>> _orthoOrigin( copy._viewportOrigin ), >>> _doDebugDraw( copy._doDebugDraw ) >>> { >>> if( copy._depthColorFragmentShader.valid() ) >>> _depthColorFragmentShader = >>> dynamic_cast<osg::Shader*> >>> ( copy._depthColorFragmentShader->clone(copyop) ); >>> } >>> >>> DebugShadowMap::~DebugShadowMap() >>> { >>> } >>> >>> void DebugShadowMap::ViewData::cull( void ) >>> { >>> if( getDebugDraw() && !_cameraDebugHUD.valid() ) >>> createDebugHUD(); >>> >>> BaseClass::ViewData::cull( ); >>> >>> cullDebugGeometry( ); >>> } >>> >>> bool DebugShadowMap::ViewData::DebugBoundingBox >>> ( const osg::BoundingBox & bb, const char * name ) >>> { >>> bool result = false; >>> #if defined( _DEBUG ) || defined( DEBUG ) >>> if( !name ) name = ""; >>> >>> osg::BoundingBox & bb_prev = _boundingBoxMap[ std::string( name ) ]; >>> >>> result = bb.center() != bb_prev.center() || bb.radius() != >>> bb_prev.radius(); >>> if( result ) >>> std::cout << "Box<" << name << "> (" >>> << ( bb._max._v[0] + bb._min._v[0] ) * 0.5 << " " >>> << ( bb._max._v[1] + bb._min._v[1] ) * 0.5 << " " >>> << ( bb._max._v[2] + bb._min._v[2] ) * 0.5 << ") [" >>> << ( bb._max._v[0] - bb._min._v[0] ) << " " >>> << ( bb._max._v[1] - bb._min._v[1] ) << " " >>> << ( bb._max._v[2] - bb._min._v[2] ) << "] " >>> << std::endl; >>> >>> bb_prev = bb; >>> #endif >>> return result; >>> } >>> >>> bool DebugShadowMap::ViewData::DebugPolytope >>> ( const osg::Polytope & p, const char * name ) >>> { >>> bool result = false; >>> #if defined( _DEBUG ) || defined( DEBUG ) >>> if( !name ) name = ""; >>> >>> osg::Polytope & p_prev = _polytopeMap[ std::string( name ) ]; >>> >>> result = ( p.getPlaneList() != p_prev.getPlaneList() ); >>> >>> if( result ) { >>> std::cout << "Polytope<" << name >>> << "> size(" << p.getPlaneList().size() << ")" >>> << std::endl; >>> >>> if( p.getPlaneList().size() == p_prev.getPlaneList().size() ) { >>> for( unsigned i = 0; i < p.getPlaneList().size(); ++i ) >>> { >>> if( p.getPlaneList()[i] != p_prev.getPlaneList()[i] ) >>> { >>> std::cout << "Plane<" << i >>> << "> (" >>> << p.getPlaneList()[i].asVec4()[0] << ", " >>> << p.getPlaneList()[i].asVec4()[1] << ", " >>> << p.getPlaneList()[i].asVec4()[2] << ", " >>> << p.getPlaneList()[i].asVec4()[3] << ")" >>> << std::endl; >>> } >>> } >>> } >>> } >>> >>> p_prev = p; >>> #endif >>> return result; >>> } >>> >>> bool DebugShadowMap::ViewData::DebugMatrix >>> ( const osg::Matrix & m, const char * name ) >>> { >>> bool result = false; >>> #if defined( _DEBUG ) || defined( DEBUG ) >>> if( !name ) name = ""; >>> >>> osg::Matrix & m_prev = _matrixMap[ std::string( name ) ]; >>> >>> result = ( m != m_prev ); >>> >>> if( result ) >>> std::cout << "Matrix<" << name << "> " << std::endl >>> <<"[ " << m(0,0) << " " << m(0,1) << " " << m(0,2) << " " << >>> m(0,3) << " ] " << std::endl >>> <<"[ " << m(1,0) << " " << m(1,1) << " " << m(1,2) << " " << >>> m(1,3) << " ] " << std::endl >>> <<"[ " << m(2,0) << " " << m(2,1) << " " << m(2,2) << " " << >>> m(2,3) << " ] " << std::endl >>> <<"[ " << m(3,0) << " " << m(3,1) << " " << m(3,2) << " " << >>> m(3,3) << " ] " << std::endl; >>> >>> m_prev = m; >>> #endif >>> return result; >>> } >>> >>> void DebugShadowMap::ViewData::setDebugPolytope >>> ( const char * name, const ConvexPolyhedron & polytope, >>> osg::Vec4 colorOutline, osg::Vec4 colorInside ) >>> { >>> if( !getDebugDraw() ) return; >>> >>> if( &polytope == NULL ) { // delete >>> PolytopeGeometry & pg = _polytopeGeometryMap[ std::string( name ) >>> ]; >>> for( unsigned int i = 0; i < VECTOR_LENGTH( pg._geometry ) ; i++ ) >>> { >>> if( pg._geometry[i].valid() ) { >>> if( _geode[i].valid() && >>> _geode[i]->containsDrawable( pg._geometry[i].get() ) ) >>> _geode[i]->removeDrawable( pg._geometry[i].get() ); >>> >>> pg._geometry[i] = NULL; >>> } >>> } >>> _polytopeGeometryMap.erase( std::string( name ) ); >>> } else { // update >>> PolytopeGeometry & pg = _polytopeGeometryMap[ std::string( name ) >>> ]; >>> >>> pg._polytope = polytope; >>> if( colorOutline.a() > 0 ) >>> pg._colorOutline = colorOutline; >>> if( colorInside.a() > 0 ) >>> pg._colorInside = colorInside; >>> >>> for( unsigned int i = 0; i < VECTOR_LENGTH( pg._geometry ) ; i++ ) >>> { >>> if( !pg._geometry[i].valid() ) { >>> pg._geometry[i] = new osg::Geometry; >>> pg._geometry[i]->setDataVariance( osg::Object::DYNAMIC ); >>> pg._geometry[i]->setUseDisplayList( false ); >>> pg._geometry[i]->setSupportsDisplayList( false ); >>> } >>> >>> if( _geode[i].valid() && >>> !_geode[i]->containsDrawable( pg._geometry[i].get() ) ) { >>> osg::Geode::DrawableList & dl = >>> const_cast< osg::Geode::DrawableList &> >>> ( _geode[i]->getDrawableList() ); >>> dl.insert( dl.begin(), pg._geometry[i].get() ); >>> } >>> } >>> } >>> } >>> >>> void DebugShadowMap::ViewData::updateDebugGeometry >>> ( const osg::Camera * viewCam, const osg::Camera * shadowCam ) >>> { >>> if( !getDebugDraw() ) return; >>> if( _polytopeGeometryMap.empty() ) return; >>> >>> const int num = 2; // = VECTOR_LENGTH( PolytopeGeometry::_geometry ); >>> >>> osg::Matrix >>> transform[ num ] = >>> { viewCam->getViewMatrix() * >>> // use near far clamped projection ( precomputed in >>> cullDebugGeometry ) >>> ( viewCam == _viewCamera ? _viewProjection : >>> viewCam->getProjectionMatrix() ), >>> shadowCam->getViewMatrix() * shadowCam->getProjectionMatrix() >>> }, >>> inverse[ num ] = >>> { osg::Matrix::inverse( transform[0] ), >>> osg::Matrix::inverse( transform[1] ) }; >>> >>> #if 0 >>> ConvexPolyhedron frustum[ num ]; >>> for( int i = 0; i < num; i++ ) { >>> frustum[i].setToUnitFrustum( ); >>> #if 1 >>> frustum[i].transform( inverse[i], transform[i] ); >>> #else >>> frustum[i].transform >>> ( osg::Matrix::inverse( camera[i]->getProjectionMatrix() ), >>> camera[i]->getProjectionMatrix() ); >>> frustum[i].transform >>> ( osg::Matrix::inverse( camera[i]->getViewMatrix() ), >>> camera[i]->getViewMatrix() ); >>> #endif >>> }; >>> #else >>> osg::Polytope frustum[ num ]; >>> for( int i = 0; i < num; i++ ) { >>> frustum[i].setToUnitFrustum( ); >>> frustum[i].transformProvidingInverse( transform[i] ); >>> } >>> #endif >>> >>> transform[0] = viewCam->getViewMatrix(); >>> inverse[0] = viewCam->getInverseViewMatrix(); >>> >>> for( PolytopeGeometryMap::iterator itr = _polytopeGeometryMap.begin(); >>> itr != _polytopeGeometryMap.end(); >>> ++itr ) >>> { >>> PolytopeGeometry & pg = itr->second; >>> >>> for( int i = 0; i < num ; i++ ) >>> { >>> >>> ConvexPolyhedron cp( pg._polytope ); >>> cp.cut( frustum[i] ); >>> cp.transform( transform[i], inverse[i] ); >>> >>> pg._geometry[i] = cp.buildGeometry >>> ( pg._colorOutline, pg._colorInside, pg._geometry[i].get() >>> ); >>> } >>> } >>> } >>> >>> void DebugShadowMap::ViewData::cullDebugGeometry( ) >>> { >>> if( !getDebugDraw() ) return; >>> if( !_camera.valid() ) return; >>> >>> // View camera may use clamping projection matrix after traversal. >>> // Since we need to know exact matrix for drawing the frusta, >>> // we have to compute it here in exactly the same way as cull visitor >>> // will after cull traversal completes view camera subgraph. >>> { >>> _viewProjection = *_cv->getProjectionMatrix(); >>> _viewCamera = _cv->getRenderStage()->getCamera(); >>> >>> if( _cv->getComputeNearFarMode() ) { >>> >>> // Redo steps from CullVisitor::popProjectionMatrix() >>> // which clamps projection matrix when Camera & Projection >>> // completes traversal of their children >>> >>> // We have to do this now manually >>> // because we did not complete camera traversal yet but >>> // we need to know how this clamped projection matrix will be >>> >>> _cv->computeNearPlane(); >>> >>> osgUtil::CullVisitor::value_type n = >>> _cv->getCalculatedNearPlane(); >>> osgUtil::CullVisitor::value_type f = >>> _cv->getCalculatedFarPlane(); >>> >>> if( n < f ) >>> _cv->clampProjectionMatrix( _viewProjection, n, f ); >>> } >>> } >>> >>> updateDebugGeometry( _viewCamera, _camera.get() ); >>> >>> #if 1 // Add geometries of polytopes to main cam Render Stage >>> _transform[0]->accept( *_cv ); >>> #else >>> for( PolytopeGeometryMap::iterator itr = _polytopeGeometryMap.begin(); >>> itr != _polytopeGeometryMap.end(); >>> ++itr ) >>> { >>> PolytopeGeometry & pg = itr->second; >>> _cv->pushStateSet( _geode[0]->getStateSet() ); >>> _cv->addDrawableAndDepth( pg._geometry[0].get(), NULL, FLT_MAX ); >>> _cv->popStateSet( ); >>> } >>> #endif >>> >>> // Add geometries of polytopes to hud cam Render Stage >>> _cameraDebugHUD->accept( *_cv ); >>> } >>> >>> void DebugShadowMap::ViewData::init( ThisClass *st, osgUtil::CullVisitor >>> *cv >>> ) >>> { >>> BaseClass::ViewData::init( st, cv ); >>> >>> _doDebugDrawPtr = &st->_doDebugDraw; >>> >>> _hudSize = st->_hudSize; >>> _hudOrigin = st->_hudOrigin; >>> _viewportSize = st->_viewportSize; >>> _viewportOrigin = st->_viewportOrigin; >>> _orthoSize = st->_orthoSize; >>> _orthoOrigin = st->_orthoOrigin; >>> >>> _depthColorFragmentShader = st->_depthColorFragmentShader; >>> >>> // create placeholder geodeds for polytope geometries >>> // rest of their initialization will be performed during camera hud >>> init >>> _geode[0] = new osg::Geode; >>> _geode[1] = new osg::Geode; >>> >>> _cameraDebugHUD = NULL;//Force debug HUD rebuild ( if needed >>> ) >>> } >>> >>> void DebugShadowMap::ViewData::createDebugHUD( ) >>> { >>> // Callback used by debugging hud to display Shadow Map to color >>> buffer >>> // Had to do it this way because OSG does not allow to use >>> // the same GL Texture Id with different glTexParams. >>> // Callback simply turns compare mode off via GL while rendering >>> hud >>> and >>> // restores it before rendering the scene with shadows. >>> class DrawableDrawWithDepthShadowComparisonOffCallback: >>> public osg::Drawable::DrawCallback >>> { >>> public: >>> DrawableDrawWithDepthShadowComparisonOffCallback( >>> osg::Texture2D *pTex ) >>> : _pTexture( pTex ) >>> { >>> } >>> >>> virtual void drawImplementation >>> ( osg::RenderInfo & ri,const osg::Drawable* >>> drawable >>> ) const >>> { >>> ri.getState()->applyTextureAttribute( 0, >>> _pTexture.get() ); >>> >>> // Turn off depth comparison mode >>> glTexParameteri( GL_TEXTURE_2D, >>> GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE ); >>> >>> drawable->drawImplementation(ri); >>> >>> // Turn it back on >>> glTexParameteri( GL_TEXTURE_2D, >>> GL_TEXTURE_COMPARE_MODE_ARB, >>> GL_COMPARE_R_TO_TEXTURE_ARB ); >>> } >>> >>> osg::ref_ptr< osg::Texture2D > _pTexture; >>> }; >>> >>> _cameraDebugHUD = new osg::Camera; >>> >>> { // Make sure default HUD layout makes sense >>> if( _hudSize[0] <= 0 ) _hudSize[0] = DEFAULT_DEBUG_HUD_SIZE_X; >>> if( _hudSize[1] <= 0 ) _hudSize[1] = DEFAULT_DEBUG_HUD_SIZE_Y; >>> >>> if( _viewportSize[0] <= 0 ) _viewportSize[0] = _hudSize[0]; >>> if( _viewportSize[1] <= 0 ) _viewportSize[1] = _hudSize[1]; >>> >>> if( _orthoSize[0] <= 0 ) _orthoSize[0] = _viewportSize[0]; >>> if( _orthoSize[1] <= 0 ) _orthoSize[1] = _viewportSize[1]; >>> } >>> >>> { // Initialize hud camera >>> osg::Camera * camera = _cameraDebugHUD.get(); >>> >>> camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR); >>> camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF); >>> camera->setViewMatrix(osg::Matrix::identity()); >>> camera->setViewport( _viewportOrigin[0], _viewportOrigin[1], >>> _viewportSize[0], _viewportSize[1] ); >>> >>> camera->setProjectionMatrixAsOrtho( >>> _orthoOrigin[0], _orthoOrigin[0] + _orthoSize[0], >>> _orthoOrigin[1], _orthoOrigin[1] + _orthoSize[1], >>> -10, 10 ); >>> >>> camera->setClearMask(GL_DEPTH_BUFFER_BIT); >>> camera->setRenderOrder(osg::Camera::POST_RENDER); >>> } >>> >>> { // Add geode and drawable with BaseClass display >>> // create geode to contain hud drawables >>> osg::Geode* geode = new osg::Geode; >>> _cameraDebugHUD->addChild(geode); >>> >>> // finally create and attach hud geometry >>> osg::Geometry* geometry = osg::createTexturedQuadGeometry >>> ( osg::Vec3(_hudOrigin[0],_hudOrigin[1],0), >>> osg::Vec3(_hudSize[0],0,0), >>> osg::Vec3(0,_hudSize[1],0) ); >>> >>> osg::StateSet* stateset = _cameraDebugHUD->getOrCreateStateSet(); >>> >>> >>> >>> stateset->setTextureAttributeAndModes(0,_texture.get(),osg::StateAttribute::ON >>> ); >>> stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF); >>> // stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF); >>> stateset->setAttributeAndModes >>> ( new osg::Depth( osg::Depth::ALWAYS, 0, 1, false ) ); >>> stateset->setMode(GL_BLEND,osg::StateAttribute::ON); >>> >>> osg::Program* program = new osg::Program; >>> program->addShader( _depthColorFragmentShader.get() ); >>> stateset->setAttribute( program ); >>> stateset->addUniform( new osg::Uniform( "texture" , 0 ) ); >>> >>> geometry->setDrawCallback >>> ( new DrawableDrawWithDepthShadowComparisonOffCallback( >>> _texture.get() ) ); >>> >>> geode->addDrawable( geometry ); >>> } >>> >>> { // Create transforms and geodes to manage polytope drawing >>> osg::StateSet * stateset = new osg::StateSet; >>> stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF); >>> stateset->setTextureMode(0, GL_TEXTURE_2D, >>> osg::StateAttribute::OFF); >>> stateset->setTextureMode(1, GL_TEXTURE_2D, >>> osg::StateAttribute::OFF); >>> stateset->setMode(GL_BLEND, osg::StateAttribute::ON); >>> stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF); >>> stateset->setAttribute( new osg::Program() ); >>> stateset->setAttributeAndModes >>> ( new osg::Depth( osg::Depth::LEQUAL, 0, 1, false ) ); >>> >>> for( int i = 0; i < 2; i++ ) { >>> _geode[i]->setStateSet( stateset ); >>> _transform[i] = new osg::MatrixTransform; >>> _transform[i]->addChild( _geode[i].get() ); >>> _transform[i]->setMatrix( osg::Matrix::identity() ); >>> _transform[i]->setReferenceFrame( >>> osg::MatrixTransform::ABSOLUTE_RF ); >>> } >>> >>> _transform[1]->setMatrix >>> ( osg::Matrix::translate( 1, 1, 0 ) * >>> osg::Matrix::scale( 0.5, 0.5, 1 ) * >>> osg::Matrix::scale( _hudSize[0], _hudSize[1], 1 ) * >>> osg::Matrix::translate( _hudOrigin[0], _hudOrigin[1], 0 ) ); >>> >>> _cameraDebugHUD->addChild( _transform[1].get() ); >>> } >>> } >>> >>> osg::Vec3d DebugShadowMap::ViewData::computeShadowTexelToPixelError >>> ( const osg::Matrix & mvpwView, >>> const osg::Matrix & mvpwShadow, >>> const osg::Vec3d & vWorld, >>> const osg::Vec3d & vDelta ) >>> { >>> osg::Vec3d vS0 = mvpwShadow * vWorld; >>> osg::Vec3d vS1 = mvpwShadow * ( vWorld + vDelta ); >>> >>> osg::Vec3d vV0 = mvpwView * vWorld; >>> osg::Vec3d vV1 = mvpwView * ( vWorld + vDelta ); >>> >>> osg::Vec3d dV = vV1 - vV0; >>> osg::Vec3d dS = vS1 - vS0; >>> >>> return osg::Vec3( dS[0] / dV[0], dS[1] / dV[1], dS[2] / dV[2] ); >>> } >>> >>> void DebugShadowMap::ViewData::displayShadowTexelToPixelErrors >>> ( const osg::Camera* viewCamera, >>> const osg::Camera* shadowCamera, >>> const ConvexPolyhedron* hull ) >>> { >>> osg::Matrix mvpwMain = >>> viewCamera->getViewMatrix() * >>> viewCamera->getProjectionMatrix() * >>> viewCamera->getViewport()->computeWindowMatrix(); >>> >>> osg::Matrix mvpwShadow = >>> shadowCamera->getViewMatrix() * >>> shadowCamera->getProjectionMatrix() * >>> shadowCamera->getViewport()->computeWindowMatrix(); >>> >>> osg::BoundingBox bb = >>> hull->computeBoundingBox( viewCamera->getViewMatrix() ); >>> >>> osg::Matrix m = viewCamera->getInverseViewMatrix(); >>> >>> osg::Vec3d vn = osg::Vec3d( 0, 0, bb._max[2] ) * m; >>> osg::Vec3d vf = osg::Vec3d( 0, 0, bb._min[2] ) * m; >>> osg::Vec3d vm = osg::Vec3d( 0, 0, ( bb._max[2] + bb._min[2] ) * 0.5 ) * >>> m; >>> >>> osg::Vec3d vne = computeShadowTexelToPixelError( mvpwMain, mvpwShadow, >>> vn >>> ); >>> osg::Vec3d vfe = computeShadowTexelToPixelError( mvpwMain, mvpwShadow, >>> vf >>> ); >>> osg::Vec3d vme = computeShadowTexelToPixelError( mvpwMain, mvpwShadow, >>> vm >>> ); >>> >>> std::cout << std::setprecision( 3 ) << " " >>> << "ne=(" << vne[0] << "," << vne[1] << "," << vne[2] << ") " >>> << "fe=(" << vfe[0] << "," << vfe[1] << "," << vfe[2] << ") " >>> << "me=(" << vme[0] << "," << vme[1] << "," << vme[2] << ") " >>> << >>> >>> "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b" >>> << >>> >>> "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b" >>> << >>> >>> "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b" >>> << std::flush; >>> } >>> >>> >>> /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield >>> * >>> * This library is open source and may be redistributed and/or modified >>> under >>> * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or >>> * (at your option) any later version. The full license is in LICENSE >>> file >>> * included with this distribution, and on the openscenegraph.org >>> website. >>> * >>> * This library is distributed in the hope that it will be useful, >>> * but WITHOUT ANY WARRANTY; without even the implied warranty of >>> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >>> * OpenSceneGraph Public License for more details. >>> */ >>> >>> #include <osgShadow/ShadowMap> >>> #include <osgShadow/ShadowedScene> >>> #include <osg/Notify> >>> #include <osg/ComputeBoundsVisitor> >>> #include <osg/PolygonOffset> >>> #include <osg/CullFace> >>> #include <osg/io_utils> >>> >>> using namespace osgShadow; >>> >>> #include <iostream> >>> //for debug >>> #include <osg/LightSource> >>> #include <osg/PolygonMode> >>> #include <osg/Geometry> >>> #include <osgDB/ReadFile> >>> #include <osgText/Text> >>> >>> #define IMPROVE_TEXGEN_PRECISION 1 >>> >>> ////////////////////////////////////////////////////////////////// >>> // fragment shader >>> // >>> static const char fragmentShaderSource_noBaseTexture[] = >>> "uniform sampler2DShadow osgShadow_shadowTexture; \n" >>> "uniform vec2 osgShadow_ambientBias; \n" >>> "\n" >>> "void main(void) \n" >>> "{ \n" >>> " gl_FragColor = gl_Color * (osgShadow_ambientBias.x + shadow2DProj( >>> osgShadow_shadowTexture, gl_TexCoord[0] ) * osgShadow_ambientBias.y); \n" >>> "}\n"; >>> >>> ////////////////////////////////////////////////////////////////// >>> // fragment shader >>> // >>> static const char fragmentShaderSource_withBaseTexture[] = >>> "uniform sampler2D osgShadow_baseTexture; \n" >>> "uniform sampler2DShadow osgShadow_shadowTexture; \n" >>> "uniform vec2 osgShadow_ambientBias; \n" >>> "\n" >>> "void main(void) \n" >>> "{ \n" >>> " vec4 color = gl_Color * texture2D( osgShadow_baseTexture, >>> gl_TexCoord[0].xy ); \n" >>> " gl_FragColor = color * (osgShadow_ambientBias.x + shadow2DProj( >>> osgShadow_shadowTexture, gl_TexCoord[1] ) * osgShadow_ambientBias.y); \n" >>> "}\n"; >>> >>> ////////////////////////////////////////////////////////////////// >>> // fragment shader >>> // >>> static const char fragmentShaderSource_debugHUD_texcoord[] = >>> "uniform sampler2D osgShadow_shadowTexture; \n" >>> " \n" >>> "void main(void) \n" >>> "{ \n" >>> " vec4 texCoord = gl_TexCoord[1].xyzw; \n" >>> " float value = texCoord.z / texCoord.w; \n" >>> " gl_FragColor = vec4( value, value, value, 1.0 ); \n" >>> "} \n"; >>> >>> static const char fragmentShaderSource_debugHUD[] = >>> "uniform sampler2D osgShadow_shadowTexture; \n" >>> " \n" >>> "void main(void) \n" >>> "{ \n" >>> " vec4 texResult = texture2D(osgShadow_shadowTexture, >>> gl_TexCoord[0].st >>> ); \n" >>> " float value = texResult.r; \n" >>> " gl_FragColor = vec4( value, value, value, 0.8 ); \n" >>> "} \n"; >>> >>> ShadowMap::ShadowMap(): >>> _baseTextureUnit(0), >>> _shadowTextureUnit(1), >>> _polyOffset(1.0,1.0), >>> _ambientBias(0.5f,0.5f), >>> _textureSize(1024,1024) >>> { >>> } >>> >>> ShadowMap::ShadowMap(const ShadowMap& copy, const osg::CopyOp& copyop): >>> ShadowTechnique(copy,copyop), >>> _baseTextureUnit(copy._baseTextureUnit), >>> _shadowTextureUnit(copy._shadowTextureUnit), >>> _polyOffset(copy._polyOffset), >>> _ambientBias(copy._ambientBias), >>> _textureSize(copy._textureSize) >>> { >>> } >>> >>> void ShadowMap::setTextureUnit(unsigned int unit) >>> { >>> _shadowTextureUnit = unit; >>> } >>> >>> void ShadowMap::setPolygonOffset(const osg::Vec2& polyOffset) >>> { >>> _polyOffset = polyOffset; >>> } >>> >>> void ShadowMap::setAmbientBias(const osg::Vec2& ambientBias) >>> { >>> _ambientBias = ambientBias; >>> if (_ambientBiasUniform.valid()) >>> _ambientBiasUniform->set(_ambientBias); >>> } >>> >>> void ShadowMap::setTextureSize(const osg::Vec2s& textureSize) >>> { >>> _textureSize = textureSize; >>> dirty(); >>> } >>> >>> void ShadowMap::setLight(osg::Light* light) >>> { >>> _light = light; >>> } >>> >>> >>> void ShadowMap::setLight(osg::LightSource* ls) >>> { >>> _ls = ls; >>> _light = _ls->getLight(); >>> } >>> >>> void ShadowMap::createUniforms() >>> { >>> _uniformList.clear(); >>> >>> osg::Uniform* baseTextureSampler = new >>> osg::Uniform("osgShadow_baseTexture",(int)_baseTextureUnit); >>> _uniformList.push_back(baseTextureSampler); >>> >>> osg::Uniform* shadowTextureSampler = new >>> osg::Uniform("osgShadow_shadowTexture",(int)_shadowTextureUnit); >>> _uniformList.push_back(shadowTextureSampler); >>> >>> _ambientBiasUniform = new >>> osg::Uniform("osgShadow_ambientBias",_ambientBias); >>> _uniformList.push_back(_ambientBiasUniform.get()); >>> >>> } >>> >>> void ShadowMap::createShaders() >>> { >>> // if we are not given shaders, use the default >>> if( _shaderList.empty() ) >>> { >>> if (_shadowTextureUnit==0) >>> { >>> osg::Shader* fragment_shader = new >>> osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource_noBaseTexture); >>> _shaderList.push_back(fragment_shader); >>> } >>> else >>> { >>> osg::Shader* fragment_shader = new >>> osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource_withBaseTexture); >>> _shaderList.push_back(fragment_shader); >>> >>> } >>> } >>> } >>> >>> void ShadowMap::init() >>> { >>> if (!_shadowedScene) return; >>> >>> _texture = new osg::Texture2D; >>> _texture->setTextureSize(_textureSize.x(), _textureSize.y()); >>> _texture->setInternalFormat(GL_DEPTH_COMPONENT); >>> _texture->setShadowComparison(true); >>> _texture->setShadowTextureMode(osg::Texture2D::LUMINANCE); >>> >>> _texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR); >>> >>> _texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR); >>> >>> // the shadow comparison should fail if object is outside the texture >>> >>> >>> >>> _texture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_BORDER); >>> >>> >>> >>> _texture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_BORDER); >>> _texture->setBorderColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); >>> >>> // set up the render to texture camera. >>> { >>> // create the camera >>> _camera = new osg::Camera; >>> >>> >>> _camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF_INHERIT_VIEWPOINT); >>> >>> _camera->setCullCallback(new CameraCullCallback(this)); >>> >>> _camera->setClearMask(GL_DEPTH_BUFFER_BIT); >>> //_camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); >>> _camera->setClearColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); >>> >>> _camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR); >>> >>> // set viewport >>> _camera->setViewport(0,0,_textureSize.x(),_textureSize.y()); >>> >>> // set the camera to render before the main camera. >>> _camera->setRenderOrder(osg::Camera::PRE_RENDER); >>> >>> // tell the camera to use OpenGL frame buffer object where >>> supported. >>> >>> >>> _camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); >>> >>> //_camera->setRenderTargetImplementation(osg::Camera::SEPERATE_WINDOW); >>> >>> // attach the texture and use it as the color buffer. >>> _camera->attach(osg::Camera::DEPTH_BUFFER, _texture.get()); >>> >>> osg::StateSet* stateset = _camera->getOrCreateStateSet(); >>> >>> >>> #if 1 >>> // cull front faces so that only backfaces contribute to depth map >>> >>> >>> osg::ref_ptr<osg::CullFace> cull_face = new osg::CullFace; >>> cull_face->setMode(osg::CullFace::FRONT); >>> stateset->setAttribute(cull_face.get(), osg::StateAttribute::ON | >>> osg::StateAttribute::OVERRIDE); >>> stateset->setMode(GL_CULL_FACE, osg::StateAttribute::ON | >>> osg::StateAttribute::OVERRIDE); >>> >>> // negative polygonoffset - move the backface nearer to the eye >>> point >>> so that backfaces >>> // shadow themselves >>> float factor = -_polyOffset[0]; >>> float units = -_polyOffset[1]; >>> >>> osg::ref_ptr<osg::PolygonOffset> polygon_offset = new >>> osg::PolygonOffset; >>> polygon_offset->setFactor(factor); >>> polygon_offset->setUnits(units); >>> stateset->setAttribute(polygon_offset.get(), >>> osg::StateAttribute::ON >>> | osg::StateAttribute::OVERRIDE); >>> stateset->setMode(GL_POLYGON_OFFSET_FILL, osg::StateAttribute::ON | >>> osg::StateAttribute::OVERRIDE); >>> #else >>> // disabling cull faces so that only front and backfaces contribute >>> to depth map >>> stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF | >>> osg::StateAttribute::OVERRIDE); >>> >>> // negative polygonoffset - move the backface nearer to the eye >>> point >>> // so that front faces do not shadow themselves. >>> float factor = _polyOffset[0]; >>> float units = _polyOffset[1]; >>> >>> osg::ref_ptr<osg::PolygonOffset> polygon_offset = new >>> osg::PolygonOffset; >>> polygon_offset->setFactor(factor); >>> polygon_offset->setUnits(units); >>> stateset->setAttribute(polygon_offset.get(), >>> osg::StateAttribute::ON >>> | osg::StateAttribute::OVERRIDE); >>> stateset->setMode(GL_POLYGON_OFFSET_FILL, osg::StateAttribute::ON | >>> osg::StateAttribute::OVERRIDE); >>> #endif >>> } >>> >>> { >>> _stateset = new osg::StateSet; >>> >>> >>> >>> _stateset->setTextureAttributeAndModes(_shadowTextureUnit,_texture.get(),osg::StateAttribute::ON >>> | osg::StateAttribute::OVERRIDE); >>> >>> >>> >>> _stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_S,osg::StateAttribute::ON); >>> >>> >>> >>> _stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_T,osg::StateAttribute::ON); >>> >>> >>> >>> _stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_R,osg::StateAttribute::ON); >>> >>> >>> >>> _stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_Q,osg::StateAttribute::ON); >>> >>> _texgen = new osg::TexGen; >>> >>> // add Program, when empty of Shaders then we are using fixed >>> functionality >>> _program = new osg::Program; >>> _stateset->setAttribute(_program.get()); >>> >>> // create default shaders if needed >>> createShaders(); >>> >>> // add the shader list to the program >>> for(ShaderList::const_iterator itr=_shaderList.begin(); >>> itr!=_shaderList.end(); >>> ++itr) >>> { >>> _program->addShader(itr->get()); >>> } >>> >>> // create own uniforms >>> createUniforms(); >>> >>> // add the uniform list to the stateset >>> for(UniformList::const_iterator itr=_uniformList.begin(); >>> itr!=_uniformList.end(); >>> ++itr) >>> { >>> _stateset->addUniform(itr->get()); >>> } >>> >>> { >>> // fake texture for baseTexture, add a fake texture >>> // we support by default at least one texture layer >>> // without this fake texture we can not support >>> // textured and not textured scene >>> >>> // TODO: at the moment the PSSM supports just one texture layer >>> in the GLSL shader, multitexture are >>> // not yet supported ! >>> >>> osg::Image* image = new osg::Image; >>> // allocate the image data, noPixels x 1 x 1 with 4 rgba floats >>> - >>> equivilant to a Vec4! >>> int noPixels = 1; >>> image->allocateImage(noPixels,1,1,GL_RGBA,GL_FLOAT); >>> image->setInternalTextureFormat(GL_RGBA); >>> // fill in the image data. >>> osg::Vec4* dataPtr = (osg::Vec4*)image->data(); >>> osg::Vec4 color(1,1,1,1); >>> *dataPtr = color; >>> // make fake texture >>> osg::Texture2D* fakeTex = new osg::Texture2D; >>> >>> fakeTex->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_EDGE); >>> >>> fakeTex->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_EDGE); >>> >>> fakeTex->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR); >>> >>> fakeTex->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR); >>> fakeTex->setImage(image); >>> // add fake texture >>> >>> >>> >>> _stateset->setTextureAttribute(_baseTextureUnit,fakeTex,osg::StateAttribute::ON); >>> >>> >>> >>> _stateset->setTextureMode(_baseTextureUnit,GL_TEXTURE_1D,osg::StateAttribute::OFF); >>> >>> >>> >>> _stateset->setTextureMode(_baseTextureUnit,GL_TEXTURE_2D,osg::StateAttribute::ON); >>> >>> >>> >>> _stateset->setTextureMode(_baseTextureUnit,GL_TEXTURE_3D,osg::StateAttribute::OFF); >>> } >>> } >>> >>> _dirty = false; >>> } >>> >>> >>> void ShadowMap::update(osg::NodeVisitor& nv) >>> { >>> _shadowedScene->osg::Group::traverse(nv); >>> } >>> >>> void ShadowMap::cull(osgUtil::CullVisitor& cv) >>> { >>> // record the traversal mask on entry so we can reapply it later. >>> unsigned int traversalMask = cv.getTraversalMask(); >>> >>> osgUtil::RenderStage* orig_rs = cv.getRenderStage(); >>> >>> // do traversal of shadow recieving scene which does need to be >>> decorated >>> by the shadow map >>> { >>> cv.pushStateSet(_stateset.get()); >>> >>> _shadowedScene->osg::Group::traverse(cv); >>> >>> cv.popStateSet(); >>> >>> } >>> >>> // need to compute view frustum for RTT camera. >>> // 1) get the light position >>> // 2) get the center and extents of the view frustum >>> >>> const osg::Light* selectLight = 0; >>> osg::Vec4 lightpos; >>> osg::Vec3 lightDir; >>> >>> //MR testing giving a specific light >>> osgUtil::PositionalStateContainer::AttrMatrixList& aml = >>> orig_rs->getPositionalStateContainer()->getAttrMatrixList(); >>> for(osgUtil::PositionalStateContainer::AttrMatrixList::iterator itr = >>> aml.begin(); >>> itr != aml.end(); >>> ++itr) >>> { >>> const osg::Light* light = dynamic_cast<const >>> osg::Light*>(itr->first.get()); >>> if (light) >>> { >>> if( _light.valid()) { >>> if( _light.get() == light ) >>> selectLight = light; >>> else >>> continue; >>> } >>> else >>> selectLight = light; >>> >>> osg::RefMatrix* matrix = itr->second.get(); >>> if (matrix) >>> { >>> lightpos = light->getPosition() * (*matrix); >>> lightDir = osg::Matrix::transform3x3( >>> light->getDirection(), >>> *matrix ); >>> } >>> else >>> { >>> lightpos = light->getPosition(); >>> lightDir = light->getDirection(); >>> } >>> >>> } >>> } >>> >>> osg::Matrix eyeToWorld; >>> eyeToWorld.invert(*cv.getModelViewMatrix()); >>> >>> lightpos = lightpos * eyeToWorld; >>> lightDir = osg::Matrix::transform3x3( lightDir, eyeToWorld ); >>> lightDir.normalize(); >>> >>> if (selectLight) >>> { >>> >>> // set to ambient on light to black so that the ambient bias >>> uniform >>> can take it's affect >>> >>> >>> >>> const_cast<osg::Light*>(selectLight)->setAmbient(osg::Vec4(0.0f,0.0f,0.0f,1.0f)); >>> >>> //std::cout<<"----- VxOSG::ShadowMap selectLight spot cutoff >>> "<<selectLight->getSpotCutoff()<<std::endl; >>> >>> float fov = selectLight->getSpotCutoff() * 2; >>> if(fov < 180.0f) // spotlight, then we don't need the bounding >>> box >>> { >>> osg::Vec3 position(lightpos.x(), lightpos.y(), lightpos.z()); >>> _camera->setProjectionMatrixAsPerspective(fov, 1.0, 0.1, >>> 1000.0); >>> >>> >>> >>> _camera->setViewMatrixAsLookAt(position,position+lightDir,osg::Vec3(0.0f,1.0f,0.0f)); >>> } >>> else >>> { >>> // get the bounds of the model. >>> osg::ComputeBoundsVisitor >>> cbbv(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN); >>> >>> >>> cbbv.setTraversalMask(getShadowedScene()->getCastsShadowTraversalMask()); >>> >>> _shadowedScene->osg::Group::traverse(cbbv); >>> >>> osg::BoundingBox bb = cbbv.getBoundingBox(); >>> >>> if (lightpos[3]!=0.0) // point light >>> { >>> osg::Vec3 position(lightpos.x(), lightpos.y(), >>> lightpos.z()); >>> >>> float centerDistance = (position-bb.center()).length(); >>> >>> float znear = centerDistance-bb.radius(); >>> float zfar = centerDistance+bb.radius(); >>> float zNearRatio = 0.001f; >>> if (znear<zfar*zNearRatio) znear = zfar*zNearRatio; >>> >>> float top = (bb.radius()/centerDistance)*znear; >>> float right = top; >>> >>> >>> _camera->setProjectionMatrixAsFrustum(-right,right,-top,top,znear,zfar); >>> >>> >>> >>> _camera->setViewMatrixAsLookAt(position,bb.center(),osg::Vec3(0.0f,1.0f,0.0f)); >>> } >>> else // directional light >>> { >>> // make an orthographic projection >>> osg::Vec3 lightDir(lightpos.x(), lightpos.y(), >>> lightpos.z()); >>> lightDir.normalize(); >>> >>> // set the position far away along the light direction >>> osg::Vec3 position = bb.center() + lightDir * bb.radius() * >>> 2; >>> >>> float centerDistance = (position-bb.center()).length(); >>> >>> float znear = centerDistance-bb.radius(); >>> float zfar = centerDistance+bb.radius(); >>> float zNearRatio = 0.001f; >>> if (znear<zfar*zNearRatio) znear = zfar*zNearRatio; >>> >>> float top = bb.radius(); >>> float right = top; >>> >>> _camera->setProjectionMatrixAsOrtho(-right, right, -top, >>> top, >>> znear, zfar); >>> >>> >>> >>> _camera->setViewMatrixAsLookAt(position,bb.center(),osg::Vec3(0.0f,1.0f,0.0f)); >>> } >>> >>> >>> } >>> >>> cv.setTraversalMask( traversalMask & >>> getShadowedScene()->getCastsShadowTraversalMask() ); >>> >>> // do RTT camera traversal >>> _camera->accept(cv); >>> >>> _texgen->setMode(osg::TexGen::EYE_LINEAR); >>> >>> #if IMPROVE_TEXGEN_PRECISION >>> // compute the matrix which takes a vertex from local coords into >>> tex >>> coords >>> // We actually use two matrices one used to define texgen >>> // and second that will be used as modelview when appling to OpenGL >>> _texgen->setPlanesFromMatrix( _camera->getProjectionMatrix() * >>> osg::Matrix::translate(1.0,1.0,1.0) * >>> osg::Matrix::scale(0.5f,0.5f,0.5f) ); >>> >>> // Place texgen with modelview which removes big offsets (making it >>> float friendly) >>> osg::RefMatrix * refMatrix = new osg::RefMatrix >>> ( _camera->getInverseViewMatrix() * *cv.getModelViewMatrix() ); >>> >>> cv.getRenderStage()->getPositionalStateContainer()-> >>> addPositionedTextureAttribute( _shadowTextureUnit, refMatrix, >>> _texgen.get() ); >>> #else >>> // compute the matrix which takes a vertex from local coords into >>> tex >>> coords >>> // will use this later to specify osg::TexGen.. >>> osg::Matrix MVPT = _camera->getViewMatrix() * >>> _camera->getProjectionMatrix() * >>> osg::Matrix::translate(1.0,1.0,1.0) * >>> osg::Matrix::scale(0.5f,0.5f,0.5f); >>> >>> _texgen->setPlanesFromMatrix(MVPT); >>> >>> >>> >>> >>> orig_rs->getPositionalStateContainer()->addPositionedTextureAttribute(_shadowTextureUnit, >>> cv.getModelViewMatrix(), _texgen.get()); >>> #endif >>> } // if(selectLight) >>> >>> >>> // reapply the original traversal mask >>> cv.setTraversalMask( traversalMask ); >>> } >>> >>> void ShadowMap::cleanSceneGraph() >>> { >>> } >>> >>> ///////////////////// Debug Methods >>> >>> >>> //////////////////////////////////////////////////////////////////////////////// >>> osg::ref_ptr<osg::Camera> ShadowMap::makeDebugHUD() >>> { >>> >>> //////////////////////////////////////////////////////////////////////////////// >>> // Callback used by debugging hud to display Shadow Map in color buffer >>> // OSG does not allow to use the same GL Texture Id with different >>> glTexParams. >>> // Callback simply turns shadow compare mode off via GL while rendering >>> hud >>> and >>> // restores it afterwards. >>> >>> //////////////////////////////////////////////////////////////////////////////// >>> class DrawableDrawWithDepthShadowComparisonOffCallback: >>> public osg::Drawable::DrawCallback >>> { >>> public: >>> // >>> DrawableDrawWithDepthShadowComparisonOffCallback >>> ( osg::Texture2D * texture, unsigned stage = 0 ) >>> : _texture( texture ), _stage( stage ) >>> { >>> } >>> >>> virtual void drawImplementation >>> ( osg::RenderInfo & ri,const osg::Drawable* >>> drawable >>> ) const >>> { >>> if( _texture.valid() ) { >>> // make sure proper texture is currently >>> applied >>> ri.getState()->applyTextureAttribute( >>> _stage, >>> _texture.get() ); >>> >>> // Turn off depth comparison mode >>> glTexParameteri( GL_TEXTURE_2D, >>> GL_TEXTURE_COMPARE_MODE_ARB, >>> GL_NONE ); >>> } >>> >>> drawable->drawImplementation(ri); >>> >>> if( _texture.valid() ) { >>> // Turn it back on >>> glTexParameteri( GL_TEXTURE_2D, >>> GL_TEXTURE_COMPARE_MODE_ARB, >>> >>> GL_COMPARE_R_TO_TEXTURE_ARB ); >>> } >>> } >>> >>> osg::ref_ptr< osg::Texture2D > _texture; >>> unsigned _stage; >>> }; >>> >>> // Make sure we attach initialized texture to HUD >>> if( !_texture.valid() ) init(); >>> >>> osg::ref_ptr<osg::Camera> camera = new osg::Camera; >>> >>> osg::Vec2 size(1280, 1024); >>> // set the projection matrix >>> >>> camera->setProjectionMatrix(osg::Matrix::ortho2D(0,size.x(),0,size.y())); >>> >>> // set the view matrix >>> camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF); >>> camera->setViewMatrix(osg::Matrix::identity()); >>> >>> // only clear the depth buffer >>> camera->setClearMask(GL_DEPTH_BUFFER_BIT); >>> camera->setClearColor(osg::Vec4(0.2f, 0.3f, 0.5f, 0.2f)); >>> //camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); >>> >>> // draw subgraph after main camera view. >>> camera->setRenderOrder(osg::Camera::POST_RENDER); >>> >>> // we don't want the camera to grab event focus from the viewers main >>> camera(s). >>> camera->setAllowEventFocus(false); >>> >>> osg::Geode* geode = new osg::Geode; >>> >>> osg::Vec3 position(10.0f,size.y()-100.0f,0.0f); >>> osg::Vec3 delta(0.0f,-120.0f,0.0f); >>> float length = 300.0f; >>> >>> // turn the text off to avoid linking with osgText >>> #if 0 >>> std::string timesFont("fonts/arial.ttf"); >>> >>> { >>> osgText::Text* text = new osgText::Text; >>> geode->addDrawable( text ); >>> >>> text->setFont(timesFont); >>> text->setPosition(position); >>> text->setText("Shadow Map HUD"); >>> >>> position += delta; >>> } >>> #endif >>> >>> osg::Vec3 widthVec(length, 0.0f, 0.0f); >>> osg::Vec3 depthVec(0.0f,length, 0.0f); >>> osg::Vec3 centerBase( 10.0f + length/2, size.y()-length/2, 0.0f); >>> centerBase += delta; >>> >>> osg::Geometry *geometry = osg::createTexturedQuadGeometry >>> ( centerBase-widthVec*0.5f-depthVec*0.5f, widthVec, depthVec ); >>> >>> geode->addDrawable( geometry ); >>> >>> geometry->setDrawCallback >>> ( new DrawableDrawWithDepthShadowComparisonOffCallback( >>> _texture.get() ) ); >>> >>> osg::StateSet* stateset = geode->getOrCreateStateSet(); >>> >>> stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF); >>> stateset->setMode(GL_BLEND,osg::StateAttribute::ON); >>> stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); >>> >>> // test with regular texture >>> //stateset->setTextureAttributeAndModes(0, new >>> osg::Texture2D(osgDB::readImageFile("Images/lz.rgb"))); >>> >>> >>> >>> >>> stateset->setTextureAttributeAndModes(0,_texture.get(),osg::StateAttribute::ON); >>> >>> //test to check the texture coordinates generated during shadow pass >>> #if 0 >>> >>> >>> >>> stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_S,osg::StateAttribute::ON); >>> >>> >>> >>> stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_T,osg::StateAttribute::ON); >>> >>> >>> >>> stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_R,osg::StateAttribute::ON); >>> >>> >>> >>> stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_Q,osg::StateAttribute::ON); >>> >>> // create TexGen node >>> osg::ref_ptr<osg::TexGenNode> texGenNode = new osg::TexGenNode; >>> texGenNode->setTextureUnit(_shadowTextureUnit); >>> texGenNode->setTexGen(_texgen.get()); >>> camera->addChild(texGenNode.get()); >>> #endif >>> //shader for correct display >>> >>> osg::ref_ptr<osg::Program> program = new osg::Program; >>> stateset->setAttribute(program.get()); >>> >>> osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT, >>> fragmentShaderSource_debugHUD); >>> program->addShader(fragment_shader); >>> >>> camera->addChild(geode); >>> >>> return camera; >>> } >>> >>> //////////////////////// End Debug Section >>> >>> >>> _______________________________________________ >>> osg-submissions mailing list >>> [email protected] >>> >>> http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org >>> >>> >> _______________________________________________ >> osg-submissions mailing list >> [email protected] >> >> http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org > > _______________________________________________ > osg-submissions mailing list > [email protected] > http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org > _______________________________________________ osg-submissions mailing list [email protected] http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org
