diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index a59ba8c1a..920c7278c 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -202,8 +202,6 @@ namespace MWRender mSceneRoot = sceneRoot; sceneRoot->setStartLight(1); - osg::ref_ptr shadowedScene (new osgShadow::ShadowedScene); - int shadowCastingTraversalMask = Mask_Scene; if (Settings::Manager::getBool("actor shadows", "Shadows")) shadowCastingTraversalMask |= Mask_Actor; @@ -211,15 +209,11 @@ namespace MWRender shadowCastingTraversalMask |= Mask_Player; if (Settings::Manager::getBool("terrain shadows", "Shadows")) shadowCastingTraversalMask |= Mask_Terrain; - SceneUtil::ShadowManager::setupShadowSettings(shadowedScene->getShadowSettings(), shadowCastingTraversalMask); - SceneUtil::ShadowManager* tech = new SceneUtil::ShadowManager(); - shadowedScene->setShadowTechnique(tech); + mShadowManager.reset(new SceneUtil::ShadowManager(sceneRoot, mRootNode)); + mShadowManager->setupShadowSettings(shadowCastingTraversalMask); - shadowedScene->addChild(sceneRoot); - mRootNode->addChild(shadowedScene); - - Shader::ShaderManager::DefineMap shadowDefines = tech->getShadowDefines(); + Shader::ShaderManager::DefineMap shadowDefines = mShadowManager->getShadowDefines(); Shader::ShaderManager::DefineMap globalDefines = mResourceSystem->getSceneManager()->getShaderManager().getGlobalDefines(); for (auto itr = shadowDefines.begin(); itr != shadowDefines.end(); itr++) diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index f0087e43d..d322bfaf4 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -50,6 +50,7 @@ namespace Fallback namespace SceneUtil { + class ShadowManager; class WorkQueue; class UnrefQueue; } @@ -234,6 +235,7 @@ namespace MWRender TerrainStorage* mTerrainStorage; std::unique_ptr mSky; std::unique_ptr mEffectManager; + std::unique_ptr mShadowManager; osg::ref_ptr mPlayerAnimation; osg::ref_ptr mPlayerNode; std::unique_ptr mCamera; diff --git a/components/sceneutil/mwshadowtechnique.cpp b/components/sceneutil/mwshadowtechnique.cpp index 01e65bc36..123030b25 100644 --- a/components/sceneutil/mwshadowtechnique.cpp +++ b/components/sceneutil/mwshadowtechnique.cpp @@ -713,7 +713,9 @@ void MWShadowTechnique::ViewDependentData::releaseGLObjects(osg::State* state) c // MWShadowTechnique // MWShadowTechnique::MWShadowTechnique(): - ShadowTechnique() + ShadowTechnique(), + _enableShadows(false), + _debugHud(nullptr) { _shadowRecievingPlaceholderStateSet = new osg::StateSet; } @@ -750,7 +752,7 @@ void MWShadowTechnique::enableShadows() _enableShadows = true; } -void MWShadowTechnique::enableShadows() +void MWShadowTechnique::disableShadows() { _enableShadows = false; } @@ -2567,7 +2569,7 @@ void MWShadowTechnique::releaseGLObjects(osg::State* state) const _debugHud->releaseGLObjects(state); } -SceneUtil::MWShadowTechnique::DebugHUD::DebugHUD(int numberOfShadowMapsPerLight) +SceneUtil::MWShadowTechnique::DebugHUD::DebugHUD(int numberOfShadowMapsPerLight) : mDebugProgram(new osg::Program) { osg::ref_ptr vertexShader = new osg::Shader(osg::Shader::VERTEX, debugVertexShaderSource); mDebugProgram->addShader(vertexShader); diff --git a/components/sceneutil/mwshadowtechnique.hpp b/components/sceneutil/mwshadowtechnique.hpp index 797266287..41f1d7c32 100644 --- a/components/sceneutil/mwshadowtechnique.hpp +++ b/components/sceneutil/mwshadowtechnique.hpp @@ -32,7 +32,7 @@ namespace SceneUtil { /** ViewDependentShadowMap provides an base implementation of view dependent shadow mapping techniques.*/ - class OSGSHADOW_EXPORT MWShadowTechnique : public osgShadow::ShadowTechnique + class MWShadowTechnique : public osgShadow::ShadowTechnique { public: MWShadowTechnique(); @@ -95,7 +95,7 @@ namespace SceneUtil { osg::BoundingBox _bb; }; - struct OSGSHADOW_EXPORT Frustum + struct Frustum { Frustum(osgUtil::CullVisitor* cv, double minZNear, double maxZFar); @@ -122,7 +122,7 @@ namespace SceneUtil { // forward declare class ViewDependentData; - struct OSGSHADOW_EXPORT LightData : public osg::Referenced + struct LightData : public osg::Referenced { LightData(ViewDependentData* vdd); @@ -144,7 +144,7 @@ namespace SceneUtil { typedef std::list< osg::ref_ptr > LightDataList; - struct OSGSHADOW_EXPORT ShadowData : public osg::Referenced + struct ShadowData : public osg::Referenced { ShadowData(ViewDependentData* vdd); @@ -161,7 +161,7 @@ namespace SceneUtil { typedef std::list< osg::ref_ptr > ShadowDataList; - class OSGSHADOW_EXPORT ViewDependentData : public osg::Referenced + class ViewDependentData : public osg::Referenced { public: ViewDependentData(MWShadowTechnique* vdsm); @@ -245,7 +245,7 @@ namespace SceneUtil { protected: virtual void addAnotherShadowMap(); - static const int sDebugTextureUnit; + static const int sDebugTextureUnit = 0; std::vector> mDebugCameras; osg::ref_ptr mDebugProgram; diff --git a/components/sceneutil/shadow.cpp b/components/sceneutil/shadow.cpp index 8c729e3cc..8c58cb603 100644 --- a/components/sceneutil/shadow.cpp +++ b/components/sceneutil/shadow.cpp @@ -13,48 +13,17 @@ namespace SceneUtil { using namespace osgShadow; - std::string debugVertexShaderSource = "void main(void){gl_Position = gl_Vertex; gl_TexCoord[0]=gl_MultiTexCoord0;}"; - std::string debugFragmentShaderSource = - "uniform sampler2D texture; \n" - " \n" - "void main(void) \n" - "{ \n" -#if 1 - " float f = texture2D( texture, gl_TexCoord[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 ); \n" -#else - " gl_FragColor = texture2D(texture, gl_TexCoord[0].xy); \n" -#endif - "} \n"; - - void ShadowManager::setupShadowSettings(osg::ref_ptr settings, int castsShadowMask) + void ShadowManager::setupShadowSettings(int castsShadowMask) { if (!Settings::Manager::getBool("enable shadows", "Shadows")) + { + mShadowTechnique->disableShadows(); return; + } + else + mShadowTechnique->enableShadows(); + + osg::ref_ptr settings = mShadowedScene->getShadowSettings(); settings->setLightNum(0); settings->setCastsShadowTraversalMask(castsShadowMask); @@ -70,6 +39,11 @@ namespace SceneUtil int mapres = Settings::Manager::getInt("shadow map resolution", "Shadows"); settings->setTextureSize(osg::Vec2s(mapres, mapres)); + + if (Settings::Manager::getBool("enable debug hud", "Shadows")) + mShadowTechnique->enableDebugHUD(); + else + mShadowTechnique->disableDebugHUD(); } void ShadowManager::disableShadowsForStateSet(osg::ref_ptr stateset) @@ -87,768 +61,15 @@ namespace SceneUtil stateset->setTextureAttributeAndModes(i, fakeShadowMapTexture, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED); } - ShadowManager::ShadowManager() : enableShadows(Settings::Manager::getBool("enable shadows", "Shadows")), + ShadowManager::ShadowManager(osg::ref_ptr sceneRoot, osg::ref_ptr rootNode) : enableShadows(Settings::Manager::getBool("enable shadows", "Shadows")), numberOfShadowMapsPerLight(Settings::Manager::getInt("number of shadow maps", "Shadows")), baseShadowTextureUnit(8 - numberOfShadowMapsPerLight), - debugHud(Settings::Manager::getBool("enable debug hud", "Shadows")), - debugProgram(new osg::Program), debugTextureUnit(0) + mShadowedScene(new osgShadow::ShadowedScene), + mShadowTechnique(new MWShadowTechnique) { - if (debugHud) - { - osg::ref_ptr vertexShader = new osg::Shader(osg::Shader::VERTEX, debugVertexShaderSource); - debugProgram->addShader(vertexShader); - osg::ref_ptr fragmentShader = new osg::Shader(osg::Shader::FRAGMENT, debugFragmentShaderSource); - debugProgram->addShader(fragmentShader); - - for (int i = 0; i < numberOfShadowMapsPerLight; ++i) - { - std::cout << i << std::endl; - - debugCameras.push_back(new osg::Camera); - debugCameras[i]->setViewport(200 * i, 0, 200, 200); - debugCameras[i]->setRenderOrder(osg::Camera::POST_RENDER); - debugCameras[i]->setClearColor(osg::Vec4(1.0, 1.0, 0.0, 1.0)); - - debugGeometry.push_back(osg::createTexturedQuadGeometry(osg::Vec3(-1, -1, 0), osg::Vec3(2, 0, 0), osg::Vec3(0, 2, 0))); - debugGeometry[i]->setCullingActive(false); - debugCameras[i]->addChild(debugGeometry[i]); - osg::ref_ptr stateSet = debugGeometry[i]->getOrCreateStateSet(); - stateSet->setAttributeAndModes(debugProgram, osg::StateAttribute::ON); - osg::ref_ptr textureUniform = new osg::Uniform("texture", debugTextureUnit); - //textureUniform->setType(osg::Uniform::SAMPLER_2D); - stateSet->addUniform(textureUniform.get()); - } - } - } - - class VDSMCameraCullCallback : public osg::NodeCallback - { - public: - - VDSMCameraCullCallback(ViewDependentShadowMap* vdsm, osg::Polytope& polytope); - - virtual void operator()(osg::Node*, osg::NodeVisitor* nv); - - osg::RefMatrix* getProjectionMatrix() { return _projectionMatrix.get(); } - osgUtil::RenderStage* getRenderStage() { return _renderStage.get(); } - - protected: - - ViewDependentShadowMap* _vdsm; - osg::ref_ptr _projectionMatrix; - osg::ref_ptr _renderStage; - osg::Polytope _polytope; - }; - - VDSMCameraCullCallback::VDSMCameraCullCallback(ViewDependentShadowMap* vdsm, osg::Polytope& polytope) : - _vdsm(vdsm), - _polytope(polytope) - { - } - - void VDSMCameraCullCallback::operator()(osg::Node* node, osg::NodeVisitor* nv) - { - osgUtil::CullVisitor* cv = dynamic_cast(nv); - osg::Camera* camera = dynamic_cast(node); - OSG_INFO << "VDSMCameraCullCallback::operator()(osg::Node* " << camera << ", osg::NodeVisitor* " << cv << ")" << std::endl; - -#if 1 - if (!_polytope.empty()) - { - OSG_INFO << "Pushing custom Polytope" << std::endl; - - osg::CullingSet& cs = cv->getProjectionCullingStack().back(); - - cs.setFrustum(_polytope); - - cv->pushCullingSet(); - } -#endif - if (_vdsm->getShadowedScene()) - { - _vdsm->getShadowedScene()->osg::Group::traverse(*nv); - } -#if 1 - if (!_polytope.empty()) - { - OSG_INFO << "Popping custom Polytope" << std::endl; - cv->popCullingSet(); - } -#endif - - _renderStage = cv->getCurrentRenderBin()->getStage(); - - OSG_INFO << "VDSM second : _renderStage = " << _renderStage << std::endl; - - if (cv->getComputeNearFarMode() != osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR) - { - // make sure that the near plane is computed correctly. - cv->computeNearPlane(); - - osg::Matrixd projection = *(cv->getProjectionMatrix()); - - OSG_INFO << "RTT Projection matrix " << projection << std::endl; - - osg::Matrix::value_type left, right, bottom, top, zNear, zFar; - osg::Matrix::value_type epsilon = 1e-6; - if (fabs(projection(0, 3))setProjectionMatrix(projection); - - _projectionMatrix = cv->getProjectionMatrix(); - } - } - - ShadowManager::ComputeLightSpaceBounds::ComputeLightSpaceBounds(osg::Viewport* viewport, const osg::Matrixd& projectionMatrix, osg::Matrixd& viewMatrix) : - osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN) - { - setCullingMode(osg::CullSettings::VIEW_FRUSTUM_CULLING); - - pushViewport(viewport); - pushProjectionMatrix(new osg::RefMatrix(projectionMatrix)); - pushModelViewMatrix(new osg::RefMatrix(viewMatrix), osg::Transform::ABSOLUTE_RF); - } - - void ShadowManager::ComputeLightSpaceBounds::apply(osg::Node& node) - { - if (isCulled(node)) return; - - // push the culling mode. - pushCurrentMask(); - - traverse(node); - - // pop the culling mode. - popCurrentMask(); - } - - void ShadowManager::ComputeLightSpaceBounds::apply(osg::Geode& node) - { - if (isCulled(node)) return; - - // push the culling mode. - pushCurrentMask(); - - for (unsigned int i = 0; igetBoundingBox()); - } - } - - // pop the culling mode. - popCurrentMask(); - } - - void ShadowManager::ComputeLightSpaceBounds::apply(osg::Drawable& drawable) - { - if (isCulled(drawable)) return; - - // push the culling mode. - pushCurrentMask(); - - updateBound(drawable.getBoundingBox()); - - // pop the culling mode. - popCurrentMask(); - } - - void ShadowManager::ComputeLightSpaceBounds::apply(Terrain::QuadTreeWorld & quadTreeWorld) - { - // For now, just expand the bounds fully as terrain will fill them up and possible ways to detect which terrain definitely won't cast shadows aren't implemented. - - update(osg::Vec3(-1.0, -1.0, 0.0)); - update(osg::Vec3(1.0, 1.0, 0.0)); - } - - void ShadowManager::ComputeLightSpaceBounds::apply(osg::Billboard&) - { - OSG_INFO << "Warning Billboards not yet supported" << std::endl; - return; - } - - void ShadowManager::ComputeLightSpaceBounds::apply(osg::Projection&) - { - // projection nodes won't affect a shadow map so their subgraphs should be ignored - return; - } - - void ShadowManager::ComputeLightSpaceBounds::apply(osg::Transform& transform) - { - if (isCulled(transform)) return; - - // push the culling mode. - pushCurrentMask(); - - // absolute transforms won't affect a shadow map so their subgraphs should be ignored. - if (transform.getReferenceFrame() == osg::Transform::RELATIVE_RF) - { - osg::ref_ptr matrix = new osg::RefMatrix(*getModelViewMatrix()); - transform.computeLocalToWorldMatrix(*matrix, this); - pushModelViewMatrix(matrix.get(), transform.getReferenceFrame()); - - traverse(transform); - - popModelViewMatrix(); - } - - // pop the culling mode. - popCurrentMask(); - - } - - void ShadowManager::ComputeLightSpaceBounds::apply(osg::Camera&) - { - // camera nodes won't affect a shadow map so their subgraphs should be ignored - return; - } - - void ShadowManager::ComputeLightSpaceBounds::updateBound(const osg::BoundingBox& bb) - { - if (!bb.valid()) return; - - const osg::Matrix& matrix = *getModelViewMatrix() * *getProjectionMatrix(); - - update(bb.corner(0) * matrix); - update(bb.corner(1) * matrix); - update(bb.corner(2) * matrix); - update(bb.corner(3) * matrix); - update(bb.corner(4) * matrix); - update(bb.corner(5) * matrix); - update(bb.corner(6) * matrix); - update(bb.corner(7) * matrix); - } - - void ShadowManager::ComputeLightSpaceBounds::update(const osg::Vec3& v) - { - if (v.z()<-1.0f) - { - //OSG_NOTICE<<"discarding("<1.0f) x = 1.0f; - float y = v.y(); - if (y<-1.0f) y = -1.0f; - if (y>1.0f) y = 1.0f; - _bb.expandBy(osg::Vec3(x, y, v.z())); - } - - void ShadowManager::cull(osgUtil::CullVisitor& cv) - { - if (!enableShadows) - { - _shadowedScene->osg::Group::traverse(cv); - return; - } - - OSG_INFO << std::endl << std::endl << "ViewDependentShadowMap::cull(osg::CullVisitor&" << &cv << ")" << std::endl; - - if (!_shadowCastingStateSet) - { - OSG_INFO << "Warning, init() has not yet been called so ShadowCastingStateSet has not been setup yet, unable to create shadows." << std::endl; - _shadowedScene->osg::Group::traverse(cv); - return; - } - - ViewDependentData* vdd = getViewDependentData(&cv); - - if (!vdd) - { - OSG_INFO << "Warning, now ViewDependentData created, unable to create shadows." << std::endl; - _shadowedScene->osg::Group::traverse(cv); - return; - } - - ShadowSettings* settings = getShadowedScene()->getShadowSettings(); - - OSG_INFO << "cv->getProjectionMatrix()=" << *cv.getProjectionMatrix() << std::endl; - - osg::CullSettings::ComputeNearFarMode cachedNearFarMode = cv.getComputeNearFarMode(); - - osg::RefMatrix& viewProjectionMatrix = *cv.getProjectionMatrix(); - - // check whether this main views projection is perspective or orthographic - bool orthographicViewFrustum = viewProjectionMatrix(0, 3) == 0.0 && - viewProjectionMatrix(1, 3) == 0.0 && - viewProjectionMatrix(2, 3) == 0.0; - - double minZNear = 0.0; - double maxZFar = DBL_MAX; - - if (cachedNearFarMode == osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR) - { - double left, right, top, bottom; - if (orthographicViewFrustum) - { - viewProjectionMatrix.getOrtho(left, right, bottom, top, minZNear, maxZFar); - } - else - { - viewProjectionMatrix.getFrustum(left, right, bottom, top, minZNear, maxZFar); - } - OSG_INFO << "minZNear=" << minZNear << ", maxZFar=" << maxZFar << std::endl; - } - - // set the compute near/far mode to the highest quality setting to ensure we push the near plan out as far as possible - if (settings->getComputeNearFarModeOverride() != osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR) - { - cv.setComputeNearFarMode(settings->getComputeNearFarModeOverride()); - } - - // 1. Traverse main scene graph - cv.pushStateSet(_shadowRecievingPlaceholderStateSet.get()); - - osg::ref_ptr decoratorStateGraph = cv.getCurrentStateGraph(); - - cullShadowReceivingScene(&cv); - - cv.popStateSet(); - - if (cv.getComputeNearFarMode() != osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR) - { - OSG_INFO << "Just done main subgraph traversak" << std::endl; - // make sure that the near plane is computed correctly so that any projection matrix computations - // are all done correctly. - cv.computeNearPlane(); - } - - // clamp the minZNear and maxZFar to those provided by ShadowSettings - maxZFar = osg::minimum(settings->getMaximumShadowMapDistance(), maxZFar); - if (minZNear>maxZFar) minZNear = maxZFar*settings->getMinimumShadowMapNearFarRatio(); - - //OSG_NOTICE<<"maxZFar "<(cv.getCalculatedNearPlane(), minZNear); - reducedFar = osg::minimum(cv.getCalculatedFarPlane(), maxZFar); - } - else - { - reducedNear = minZNear; - reducedFar = maxZFar; - } - - // return compute near far mode back to it's original settings - cv.setComputeNearFarMode(cachedNearFarMode); - - OSG_INFO << "frustum.eye=" << frustum.eye << ", frustum.centerNearPlane, " << frustum.centerNearPlane << " distance = " << (frustum.eye - frustum.centerNearPlane).length() << std::endl; - - - // 2. select active light sources - // create a list of light sources + their matrices to place them - selectActiveLights(&cv, vdd); - - - unsigned int pos_x = 0; - unsigned int textureUnit = settings->getBaseShadowTextureUnit(); - unsigned int numValidShadows = 0; - - ShadowDataList& sdl = vdd->getShadowDataList(); - ShadowDataList previous_sdl; - previous_sdl.swap(sdl); - - unsigned int numShadowMapsPerLight = settings->getNumShadowMapsPerLight(); - /*if (numShadowMapsPerLight>2) - { - OSG_NOTICE << "numShadowMapsPerLight of " << numShadowMapsPerLight << " is greater than maximum supported, falling back to 2." << std::endl; - numShadowMapsPerLight = 2; - }*/ - - LightDataList& pll = vdd->getLightDataList(); - for (LightDataList::iterator itr = pll.begin(); - itr != pll.end(); - ++itr) - { - // 3. create per light/per shadow map division of lightspace/frustum - // create a list of light/shadow map data structures - - LightData& pl = **itr; - - // 3.1 compute light space polytope - // - osg::Polytope polytope = computeLightViewFrustumPolytope(frustum, pl); - - // if polytope is empty then no rendering. - if (polytope.empty()) - { - OSG_NOTICE << "Polytope empty no shadow to render" << std::endl; - continue; - } - - // 3.2 compute RTT camera view+projection matrix settings - // - osg::Matrixd projectionMatrix; - osg::Matrixd viewMatrix; - if (!computeShadowCameraSettings(frustum, pl, projectionMatrix, viewMatrix)) - { - OSG_NOTICE << "No valid Camera settings, no shadow to render" << std::endl; - continue; - } - - // if we are using multiple shadow maps and CastShadowTraversalMask is being used - // traverse the scene to compute the extents of the objects - if (/*numShadowMapsPerLight>1 &&*/ _shadowedScene->getCastsShadowTraversalMask() != 0xffffffff) - { - // osg::ElapsedTime timer; - - osg::ref_ptr viewport = new osg::Viewport(0, 0, 2048, 2048); - ComputeLightSpaceBounds clsb(viewport.get(), projectionMatrix, viewMatrix); - clsb.setTraversalMask(_shadowedScene->getCastsShadowTraversalMask()); - - osg::Matrixd invertModelView; - invertModelView.invert(viewMatrix); - osg::Polytope local_polytope(polytope); - local_polytope.transformProvidingInverse(invertModelView); - - osg::CullingSet& cs = clsb.getProjectionCullingStack().back(); - cs.setFrustum(local_polytope); - clsb.pushCullingSet(); - - _shadowedScene->accept(clsb); - - // OSG_NOTICE<<"Extents of LightSpace "<(maxZ, -corner.z()); - minZ = osg::minimum(minZ, -corner.z()); - } - reducedNear = osg::maximum(reducedNear, minZ); - reducedFar = osg::minimum(reducedFar, maxZ); - - // OSG_NOTICE<<" xMid="< texture = sd->_texture; - osg::ref_ptr stateSet = debugGeometry[sm_i]->getOrCreateStateSet(); - stateSet->setTextureAttributeAndModes(debugTextureUnit, texture, osg::StateAttribute::ON); - - unsigned int traversalMask = cv.getTraversalMask(); - cv.setTraversalMask(debugGeometry[sm_i]->getNodeMask()); - cv.pushStateSet(stateSet); - debugCameras[sm_i]->accept(cv); - cv.popStateSet(); - cv.setTraversalMask(traversalMask); - - cv.getState()->setCheckForGLErrors(osg::State::ONCE_PER_ATTRIBUTE); - } - - osg::ref_ptr camera = sd->_camera; - - camera->setProjectionMatrix(projectionMatrix); - camera->setViewMatrix(viewMatrix); - - if (settings->getDebugDraw()) - { - camera->getViewport()->x() = pos_x; - pos_x += static_cast(camera->getViewport()->width()) + 40; - } - - // transform polytope in model coords into light spaces eye coords. - osg::Matrixd invertModelView; - invertModelView.invert(camera->getViewMatrix()); - - osg::Polytope local_polytope(polytope); - local_polytope.transformProvidingInverse(invertModelView); - - - if (numShadowMapsPerLight>1) - { - // compute the start and end range in non-dimensional coords -#if 0 - double r_start = (sm_i == 0) ? -1.0 : (double(sm_i) / double(numShadowMapsPerLight)*2.0 - 1.0); - double r_end = (sm_i + 1 == numShadowMapsPerLight) ? 1.0 : (double(sm_i + 1) / double(numShadowMapsPerLight)*2.0 - 1.0); -#elif 0 - - // hardwired for 2 splits - double r_start = (sm_i == 0) ? -1.0 : splitPoint; - double r_end = (sm_i + 1 == numShadowMapsPerLight) ? 1.0 : splitPoint; -#elif 0 - double r_start, r_end; - // Split such that each shadow map covers a quarter of the area of the one after it - if (sm_i == 0) - r_start = -1.0; - else - { - r_start = (1 - pow(4.0, sm_i)) / (1 - pow(4.0, numShadowMapsPerLight)); - r_start *= 2.0; - //r_start += double(sm_i) / double(numShadowMapsPerLight); - r_start -= 1.0; - } - - if (sm_i + 1 == numShadowMapsPerLight) - r_end = 1.0; - else - { - r_end = (1 - pow(4.0, sm_i + 1)) / (1 - pow(4.0, numShadowMapsPerLight)); - r_end *= 2.0; - //r_end += double(sm_i + 1) / double(numShadowMapsPerLight); - r_end -= 1.0; - } -#else - double r_start, r_end; - - // split system based on the original Parallel Split Shadow Maps paper. - double n = reducedNear; - double f = reducedFar; - double i = double(sm_i); - double m = double(numShadowMapsPerLight); - double ratio = Settings::Manager::getFloat("split point uniform logarithmic ratio", "Shadows"); - double deltaBias = Settings::Manager::getFloat("split point bias", "Shadows"); - if (sm_i == 0) - r_start = -1.0; - else - { - // compute the split point in main camera view - double ciLog = n * pow(f / n, i / m); - double ciUniform = n + (f - n) * i / m; - double ci = ratio * ciLog + (1.0 - ratio) * ciUniform + deltaBias; - - // work out where this is in light space - osg::Vec3d worldSpacePos = frustum.eye + frustum.frustumCenterLine * ci; - osg::Vec3d lightSpacePos = worldSpacePos * viewMatrix * projectionMatrix; - r_start = lightSpacePos.y(); - } - - if (sm_i + 1 == numShadowMapsPerLight) - r_end = 1.0; - else - { - // compute the split point in main camera view - double ciLog = n * pow(f / n, (i + 1) / m); - double ciUniform = n + (f - n) * (i + 1) / m; - double ci = ratio * ciLog + (1.0 - ratio) * ciUniform + deltaBias; - - // work out where this is in light space - osg::Vec3d worldSpacePos = frustum.eye + frustum.frustumCenterLine * ci; - osg::Vec3d lightSpacePos = worldSpacePos * viewMatrix * projectionMatrix; - r_end = lightSpacePos.y(); - } -#endif - - // for all by the last shadowmap shift the r_end so that it overlaps slightly with the next shadowmap - // to prevent a seam showing through between the shadowmaps - if (sm_i + 10) - { - // not the first shadowmap so insert a polytope to clip the scene from before r_start - - // plane in clip space coords - osg::Plane plane(0.0, 1.0, 0.0, -r_start); - - // transform into eye coords - plane.transformProvidingInverse(projectionMatrix); - local_polytope.getPlaneList().push_back(plane); - - //OSG_NOTICE<<"Adding r_start plane "<0) - { - decoratorStateGraph->setStateSet(selectStateSetForRenderingShadow(*vdd)); - } - - // OSG_NOTICE<<"End of shadow setup Projection matrix "<<*cv.getProjectionMatrix()<setShadowTechnique(mShadowTechnique); + mShadowedScene->addChild(sceneRoot); + rootNode->addChild(mShadowedScene); } Shader::ShaderManager::DefineMap ShadowManager::getShadowDefines() diff --git a/components/sceneutil/shadow.hpp b/components/sceneutil/shadow.hpp index cfe1a4f3f..5ac271185 100644 --- a/components/sceneutil/shadow.hpp +++ b/components/sceneutil/shadow.hpp @@ -2,69 +2,35 @@ #define COMPONENTS_SCENEUTIL_SHADOW_H #include -#include #include #include +#include "mwshadowtechnique.hpp" + namespace SceneUtil { - class ShadowManager : public osgShadow::ViewDependentShadowMap + class ShadowManager { public: - static void setupShadowSettings(osg::ref_ptr settings, int castsShadowMask); - static void disableShadowsForStateSet(osg::ref_ptr stateSet); - ShadowManager(); + ShadowManager(osg::ref_ptr sceneRoot, osg::ref_ptr rootNode); - virtual void cull(osgUtil::CullVisitor& cv) override; + virtual void setupShadowSettings(int castsShadowMask); virtual Shader::ShaderManager::DefineMap getShadowDefines(); virtual Shader::ShaderManager::DefineMap getShadowsDisabledDefines(); - - class ComputeLightSpaceBounds : public osg::NodeVisitor, public osg::CullStack - { - public: - ComputeLightSpaceBounds(osg::Viewport* viewport, const osg::Matrixd& projectionMatrix, osg::Matrixd& viewMatrix); - - void apply(osg::Node& node); - - void apply(osg::Geode& node); - - void apply(osg::Drawable& drawable); - - void apply(Terrain::QuadTreeWorld& quadTreeWorld); - - void apply(osg::Billboard&); - - void apply(osg::Projection&); - - void apply(osg::Transform& transform); - - void apply(osg::Camera&); - - void updateBound(const osg::BoundingBox& bb); - - void update(const osg::Vec3& v); - - osg::BoundingBox _bb; - }; protected: - const int debugTextureUnit; - - std::vector> debugCameras; - - osg::ref_ptr debugProgram; - - std::vector> debugGeometry; - const int numberOfShadowMapsPerLight; const bool enableShadows; - const bool debugHud; const int baseShadowTextureUnit; + + osg::ref_ptr mShadowedScene; + + osg::ref_ptr mShadowTechnique; }; } diff --git a/components/terrain/quadtreeworld.cpp b/components/terrain/quadtreeworld.cpp index 85c43ce1d..651b2cd24 100644 --- a/components/terrain/quadtreeworld.cpp +++ b/components/terrain/quadtreeworld.cpp @@ -4,7 +4,7 @@ #include -#include +#include #include "quadtreenode.hpp" #include "storage.hpp" @@ -347,7 +347,7 @@ void QuadTreeWorld::accept(osg::NodeVisitor &nv) { if (nv.getVisitorType() != osg::NodeVisitor::CULL_VISITOR && nv.getVisitorType() != osg::NodeVisitor::INTERSECTION_VISITOR) { - SceneUtil::ShadowManager::ComputeLightSpaceBounds* shadowBoundsVisitor = dynamic_cast(&nv); + SceneUtil::MWShadowTechnique::ComputeLightSpaceBounds* shadowBoundsVisitor = dynamic_cast(&nv); if (shadowBoundsVisitor) shadowBoundsVisitor->apply(*this); return;