bool ShadowVolume::getLightPositionalState( osgUtil::CullVisitor& cv, const Light* light, Vec4& lightPos, Vec3& lightDir ) { if( !light ) return false; // get positional state osgUtil::RenderStage* rs = cv.getRenderStage(); osgUtil::PositionalStateContainer::AttrMatrixList& aml = rs->getPositionalStateContainer()->getAttrMatrixList(); RefMatrix* matrix = NULL; bool found = false; // find the light and its matrix // note: it finds the last light occurence with its associated matrix for( osgUtil::PositionalStateContainer::AttrMatrixList::iterator itr = aml.begin(); itr != aml.end(); ++itr ) { const Light* l = dynamic_cast< const Light* >( itr->first.get() ); if( l && l == light ) { found = true; matrix = itr->second.get(); } } if( !found ) return false; // transform light to world space Matrix localToWorld = Matrix::inverse( *cv.getModelViewMatrix() ); if( matrix ) localToWorld.preMult( *matrix ); lightPos = light->getPosition(); if( lightPos[3] == 0 ) lightDir.set( -lightPos[0], -lightPos[1], -lightPos[2] ); else lightDir = light->getDirection(); lightPos = lightPos * localToWorld; lightDir = Matrix::transform3x3( lightDir, localToWorld ); lightDir.normalize(); return true; }
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 ); }
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 ); }
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 ); }
void ShadowVolume::cull(osgUtil::CullVisitor& cv) { osg::ref_ptr<osgUtil::RenderBin> original_bin = cv.getCurrentRenderBin(); osg::ref_ptr<osgUtil::RenderBin> new_bin = original_bin->find_or_insert(0,"RenderBin"); cv.setCurrentRenderBin(new_bin.get()); _shadowedScene->osg::Group::traverse(cv); cv.setCurrentRenderBin(original_bin.get()); osgUtil::RenderBin::RenderBinList::iterator itr = new_bin->getRenderBinList().find(1000); osg::ref_ptr<osgUtil::RenderBin> shadowVolumeBin; if (itr != new_bin->getRenderBinList().end()) { shadowVolumeBin = itr->second; if (shadowVolumeBin.valid()) { //OSG_NOTICE<<"Found shadow volume bin, now removing it"<<std::endl; new_bin->getRenderBinList().erase(itr); } } if (shadowVolumeBin.valid()) { original_bin->setStateSet(_ss1.get()); osgUtil::RenderStage* orig_rs = cv.getRenderStage(); osgUtil::RenderStage* new_rs = new osgUtil::RenderStage; orig_rs->addPostRenderStage(new_rs); new_rs->setViewport(orig_rs->getViewport()); new_rs->setClearColor(orig_rs->getClearColor()); new_rs->setClearMask(GL_STENCIL_BUFFER_BIT); new_rs->setDrawBuffer(orig_rs->getDrawBuffer(), orig_rs->getDrawBufferApplyMask()); new_rs->setReadBuffer(orig_rs->getReadBuffer(), orig_rs->getReadBufferApplyMask()); new_rs->setColorMask(orig_rs->getColorMask()); osg::Vec4 lightpos; osg::ref_ptr<osgUtil::PositionalStateContainer> ps = new osgUtil::PositionalStateContainer; new_rs->setPositionalStateContainer(ps.get()); const osg::Light* selectLight = 0; 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; } else { ps->addPositionedAttribute(itr->second.get(), itr->first.get()); } } _ambientLight->setPosition(lightpos); orig_rs->addPositionedAttribute(0,_ambientLight.get()); _diffuseLight->setPosition(lightpos); if (selectLight) { _ambientLight->setAmbient(selectLight->getAmbient()); _diffuseLight->setDiffuse(selectLight->getDiffuse()); _diffuseLight->setSpecular(selectLight->getSpecular()); _diffuseLight->setDirection(selectLight->getDirection()); _diffuseLight->setConstantAttenuation(selectLight->getConstantAttenuation()); _diffuseLight->setLinearAttenuation(selectLight->getLinearAttenuation()); _diffuseLight->setQuadraticAttenuation(selectLight->getQuadraticAttenuation()); _diffuseLight->setSpotExponent(selectLight->getSpotExponent()); _diffuseLight->setSpotCutoff(selectLight->getSpotCutoff()); } ps->addPositionedAttribute(0, _diffuseLight.get()); if (_lightpos != lightpos && _dynamicShadowVolumes) { _lightpos = lightpos; osg::Matrix eyeToWorld; eyeToWorld.invert(*cv.getModelViewMatrix()); _occluder->computeShadowVolumeGeometry(lightpos * eyeToWorld, *_shadowVolume); } if (shadowVolumeBin.valid()) { // new_rs->setStateSet(_mainShadowStateSet.get()); new_rs->getRenderBinList()[0] = shadowVolumeBin; shadowVolumeBin->setStateSet(_shadowVolumeStateSet.get()); osg::ref_ptr<osgUtil::RenderBin> nested_bin = new_rs->find_or_insert(1,"RenderBin"); nested_bin->getRenderBinList()[0] = new_bin; nested_bin->setStateSet(_shadowedSceneStateSet.get()); } } }