void ParallelSplitShadowMap::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();

#ifdef SHADOW_TEXTURE_GLSL
    PSSMShadowSplitTextureMap::iterator it=_PSSMShadowSplitTextureMap.begin();
#else
    // do traversal of shadow receiving scene which does need to be decorated by the shadow map
    for (PSSMShadowSplitTextureMap::iterator it=_PSSMShadowSplitTextureMap.begin();it!=_PSSMShadowSplitTextureMap.end();it++)
#endif
    {
        PSSMShadowSplitTexture pssmShadowSplitTexture = it->second;
        cv.pushStateSet(pssmShadowSplitTexture._stateset.get());

        //////////////////////////////////////////////////////////////////////////
        // DEBUG
        if ( _displayTexturesGroupingNode ) {
            cv.pushStateSet(pssmShadowSplitTexture._debug_stateset.get());
        }
        //////////////////////////////////////////////////////////////////////////

        _shadowedScene->osg::Group::traverse(cv);

        cv.popStateSet();

    }

    // need to compute view frustum for RTT camera.
    // get the bounds of the model.
    osg::ComputeBoundsVisitor cbbv(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN);
    cbbv.setTraversalMask(getShadowedScene()->getCastsShadowTraversalMask());
    _shadowedScene->osg::Group::traverse(cbbv);

    //////////////////////////////////////////////////////////////////////////
    const osg::Light* selectLight = 0;

    /// light pos and light direction
    osg::Vec4 lightpos;
    osg::Vec3 lightDirection;

    if ( ! _userLight ) {
        // try to find a light in the scene
        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)
            {
                osg::RefMatrix* matrix = itr->second.get();
                if (matrix) lightpos = light->getPosition() * (*matrix);
                else lightpos = light->getPosition();
                if (matrix) lightDirection = light->getDirection() * (*matrix);
                else lightDirection = light->getDirection();

                selectLight = light;
            }
        }

        osg::Matrix eyeToWorld;
        eyeToWorld.invert(*cv.getModelViewMatrix());

        lightpos = lightpos * eyeToWorld;
        lightDirection = lightDirection * eyeToWorld;
    }else{
        // take the user light as light source
        lightpos = _userLight->getPosition();
        lightDirection = _userLight->getDirection();
        selectLight = _userLight.get();
    }

    if (selectLight)
    {

        // do traversal of shadow receiving scene which does need to be decorated by the shadow map
        //unsigned int iMaxSplit = _PSSMShadowSplitTextureMap.size();

        for (PSSMShadowSplitTextureMap::iterator it=_PSSMShadowSplitTextureMap.begin();it!=_PSSMShadowSplitTextureMap.end();it++)
        {
            PSSMShadowSplitTexture pssmShadowSplitTexture = it->second;


            //////////////////////////////////////////////////////////////////////////
            // SETUP pssmShadowSplitTexture for rendering
            //
            lightDirection.normalize();
            pssmShadowSplitTexture._lightDirection = lightDirection;
            pssmShadowSplitTexture._cameraView    = cv.getRenderInfo().getView()->getCamera()->getViewMatrix();
            pssmShadowSplitTexture._cameraProj    = cv.getRenderInfo().getView()->getCamera()->getProjectionMatrix();

            //////////////////////////////////////////////////////////////////////////
            // CALCULATE



            // Calculate corner points of frustum split
            //
            // To avoid edge problems, scale the frustum so
            // that it's at least a few pixels larger
            //
            osg::Vec3d pCorners[8];
            calculateFrustumCorners(pssmShadowSplitTexture,pCorners);

            // Init Light (Directional Light)
            //
            calculateLightInitialPosition(pssmShadowSplitTexture,pCorners);

            // Calculate near and far for light view
            //
            calculateLightNearFarFormFrustum(pssmShadowSplitTexture,pCorners);

            // Calculate view and projection matrices
            //
            calculateLightViewProjectionFormFrustum(pssmShadowSplitTexture,pCorners);

            //////////////////////////////////////////////////////////////////////////
            // set up shadow rendering camera
            pssmShadowSplitTexture._camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);

            //////////////////////////////////////////////////////////////////////////
            // DEBUG
            if ( _displayTexturesGroupingNode ) {
                pssmShadowSplitTexture._debug_camera->setViewMatrix(pssmShadowSplitTexture._camera->getViewMatrix());
                pssmShadowSplitTexture._debug_camera->setProjectionMatrix(pssmShadowSplitTexture._camera->getProjectionMatrix());
                pssmShadowSplitTexture._debug_camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
            }

            //////////////////////////////////////////////////////////////////////////
            // compute the matrix which takes a vertex from local coords into tex coords
            // will use this later to specify osg::TexGen..

            osg::Matrix MVPT = pssmShadowSplitTexture._camera->getViewMatrix() *
                pssmShadowSplitTexture._camera->getProjectionMatrix() *
                osg::Matrix::translate(1.0,1.0,1.0) *
                osg::Matrix::scale(0.5,0.5,0.5);

            pssmShadowSplitTexture._texgen->setMode(osg::TexGen::EYE_LINEAR);
            pssmShadowSplitTexture._texgen->setPlanesFromMatrix(MVPT);
            //////////////////////////////////////////////////////////////////////////


            //////////////////////////////////////////////////////////////////////////
            cv.setTraversalMask( traversalMask & getShadowedScene()->getCastsShadowTraversalMask() );

            // do RTT camera traversal
            pssmShadowSplitTexture._camera->accept(cv);

            //////////////////////////////////////////////////////////////////////////
            // DEBUG
            if ( _displayTexturesGroupingNode ) {
                pssmShadowSplitTexture._debug_camera->accept(cv);
            }


            orig_rs->getPositionalStateContainer()->addPositionedTextureAttribute(pssmShadowSplitTexture._textureUnit, cv.getModelViewMatrix(), pssmShadowSplitTexture._texgen.get());


        }
    } // if light



    // reapply the original traversal mask
    cv.setTraversalMask( traversalMask );
}
Example #2
0
void SoftShadowMap::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 receiving 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;

    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)
        {
            osg::RefMatrix* matrix = itr->second.get();
            if (matrix) lightpos = light->getPosition() * (*matrix);
            else lightpos = light->getPosition();

            selectLight = light;
        }
    }

    osg::Matrix eyeToWorld;
    eyeToWorld.invert(*cv.getModelViewMatrix());

    lightpos = lightpos * eyeToWorld;

    if (selectLight)
    {
        // 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();


        osg::Vec3 position;

        if (lightpos[3]!=0.0)
        {
            position.set(lightpos.x(), lightpos.y(), lightpos.z());
        }
        else
        {
            // make an orthographic projection
            osg::Vec3 lightDir(lightpos.x(), lightpos.y(), lightpos.z());
            lightDir.normalize();

            // set the position far away along the light direction
            position = lightDir * bb.radius()  * 20;
        }

        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->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
        _camera->setProjectionMatrixAsOrtho(-right, right, -top, top, znear, zfar);
        _camera->setViewMatrixAsLookAt(position, bb.center(), osg::Vec3(0.0f,1.0f,0.0f));

        // 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.5,0.5,0.5+_bias);

        _texgen->setMode(osg::TexGen::EYE_LINEAR);
        _texgen->setPlanesFromMatrix(MVPT);

        cv.setTraversalMask( traversalMask &
                             getShadowedScene()->getCastsShadowTraversalMask() );

        // do RTT camera traversal
        _camera->accept(cv);

        orig_rs->getPositionalStateContainer()->addPositionedTextureAttribute(_textureUnit, cv.getModelViewMatrix(), _texgen.get());
    }


    // reapply the original traversal mask
    cv.setTraversalMask( traversalMask );
}
Example #3
0
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 receiving 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,computeOrthogonalVector(lightDir));
        }
        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(),computeOrthogonalVector(bb.center()-position));
            }
            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(),computeOrthogonalVector(lightDir));
            }


        }

        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 );
}
Example #4
0
void ShadowVolume::cull( osgUtil::CullVisitor& cv )
{
   //notify(NOTICE)<<"CULL BEGIN"<<std::endl;
    // if no light, render scene default way
    if( !_light ) {
        _shadowedScene->Group::traverse( cv );
        return;
    }

    // pass 4: add light using stencil
    // The pass is culled in the first place as it is always culled (in contrary to pass 1).
    // Its traversed lights are used in following getLightPositionalState.
    // Note: traversing order of passes 1 to 4 does not matter. Rendering order is given
    //       by RenderBin's setRenderBinDetails().
    cv.pushStateSet( _ss4 );
    _shadowedScene->Group::traverse( cv );
    cv.popStateSet();

    // clear stencil buffer - bin number 1 schedules it before 2nd and 3rd pass
    if( _clearStencil)
       //_clearDrawable->setBufferMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
       cv.addDrawable( _clearDrawable, cv.getModelViewMatrix() );

    // pass 1: ambient pass
    if(!_ambientPassDisabled)
    {
       cv.pushStateSet( _ss1 );
       _shadowedScene->Group::traverse( cv );
       cv.popStateSet();
    }

    // get light positional state,
    // if no light, return
    Vec4 lightPos;
    Vec3 lightDir;
    if( !getLightPositionalState( cv, _light, lightPos, lightDir ) )
        return;

    /******************PASS 2,3/: Shadow geometry into stencil buffer*********************/
    
    if(   _mode == ShadowVolumeGeometryGenerator::CPU_FIND_GPU_EXTRUDE
       || _mode == ShadowVolumeGeometryGenerator::GPU_RAW
       || _mode == ShadowVolumeGeometryGenerator::GPU_SILHOUETTE)
    {    
       //notify(NOTICE)<<"LIGHTPOS: "<<lightPos.x()<<" "<<lightPos.y()<<" "<<lightPos.z()<<" "<<std::endl;
       _lightPosUniform->set(lightPos);
    }

    if(_updateStrategy == UPDATE_EACH_FRAME)
      _svgg.dirty();

   if(_svgg.isDirty()){
          //_svgg.clearGeometry();
          _svgg.setup(lightPos);
          _shadowedScene->Group::traverse( _svgg );
   }

   if(_mode == ShadowVolumeGeometryGenerator::SILHOUETTES_ONLY){
      cv.pushStateSet(_ssd);
      ref_ptr< Drawable > d = _svgg.createGeometry();
      d->setUseDisplayList( false );
      ref_ptr< Geode > geode = new Geode;
      geode->addDrawable( d );
      geode->accept( cv );
      cv.popStateSet();
      return;
   }

   bool twoSidedStencil = _stencilImplementation == STENCIL_TWO_SIDED;
   if( _stencilImplementation == STENCIL_AUTO )
   {
      GraphicsContext *gc = cv.getState()->getGraphicsContext();
      if( gc->isGLExtensionSupported( 2.0, "GL20_separate_stencil" ) ||
          gc->isGLExtensionSupported( "GL_EXT_stencil_two_side" ) ||
          gc->isGLExtensionSupported( "GL_ATI_separate_stencil" ) )
      {
         twoSidedStencil = true;
      }
   }

   if(twoSidedStencil){
      cv.pushStateSet( _ss23 );

      ref_ptr< Drawable > d = _svgg.createGeometry();
      d->setUseDisplayList( false );
      ref_ptr< Geode > geode = new Geode;
      geode->addDrawable( d );
      geode->accept( cv );

      cv.popStateSet();

      if(_svgg.getMethod() == ShadowVolumeGeometryGenerator::ZFAIL){
         if(   _svgg.getMode() == ShadowVolumeGeometryGenerator::CPU_RAW 
             || _svgg.getMode() == ShadowVolumeGeometryGenerator::CPU_SILHOUETTE)
          {
            ref_ptr< Drawable > caps;
            caps = _svgg.getCapsGeometry();
            caps->setUseDisplayList( false );
            ref_ptr< Geode > geode_caps = new Geode;
            geode_caps->addDrawable( caps );

            cv.pushStateSet( _ss23_caps );
            geode_caps->accept( cv );
            cv.popStateSet();
         }
         else if(   _svgg.getMode() == ShadowVolumeGeometryGenerator::GPU_RAW 
                 || _svgg.getMode() == ShadowVolumeGeometryGenerator::GPU_SILHOUETTE)
         {
            cv.pushStateSet( _ss23_caps );
            geode->accept( cv );
            cv.popStateSet();
         }
      }
   }
   else{
       ref_ptr< Drawable > d = _svgg.createGeometry();
       d->setUseDisplayList( false );
       ref_ptr< Geode > geode = new Geode;
       geode->addDrawable( d );

       cv.pushStateSet( _ss2 );               
       geode->accept( cv );
       cv.popStateSet();

       // pass 3
       cv.pushStateSet( _ss3 );
       geode->accept( cv );
       cv.popStateSet();
   
       if(_svgg.getMethod() == ShadowVolumeGeometryGenerator::ZFAIL){          
          if(   _svgg.getMode() == ShadowVolumeGeometryGenerator::CPU_RAW 
             || _svgg.getMode() == ShadowVolumeGeometryGenerator::CPU_SILHOUETTE)
          {
             ref_ptr< Drawable > caps;
             ref_ptr< Geode > geode_caps = new Geode;
             caps = _svgg.getCapsGeometry();
             caps->setUseDisplayList( false );
             geode_caps->addDrawable( caps );

             cv.pushStateSet( _ss2_caps );               
             geode_caps->accept( cv );
             cv.popStateSet();

             cv.pushStateSet( _ss3_caps );               
             geode_caps->accept( cv );
             cv.popStateSet();
          }
          else if(   _svgg.getMode() == ShadowVolumeGeometryGenerator::GPU_RAW 
                  || _svgg.getMode() == ShadowVolumeGeometryGenerator::GPU_SILHOUETTE)
          {
             //_just_caps->set(1);
             cv.pushStateSet( _ss2_caps );
             geode->accept( cv );
             cv.popStateSet();

             cv.pushStateSet( _ss3_caps );
             geode->accept( cv );
             cv.popStateSet();
             //_just_caps->set(0);
          }
       }
               
   }

    //notify(NOTICE)<<"CULL END!!!"<<std::endl;
}