diff --git a/components/sceneutil/mwshadowtechnique.cpp b/components/sceneutil/mwshadowtechnique.cpp index 024123b3e1..770917eda7 100644 --- a/components/sceneutil/mwshadowtechnique.cpp +++ b/components/sceneutil/mwshadowtechnique.cpp @@ -279,14 +279,7 @@ void VDSMCameraCullCallback::operator()(osg::Node* node, osg::NodeVisitor* nv) } #endif // bin has to go inside camera cull or the rendertexture stage will override it - static osg::ref_ptr ss; - if (!ss) - { - ShadowsBinAdder adder("ShadowsBin", _vdsm->getCastingPrograms()); - ss = new osg::StateSet; - ss->setRenderBinDetails(osg::StateSet::OPAQUE_BIN, "ShadowsBin", osg::StateSet::OVERRIDE_PROTECTED_RENDERBIN_DETAILS); - } - cv->pushStateSet(ss); + cv->pushStateSet(_vdsm->getOrCreateShadowsBinStateSet()); if (_vdsm->getShadowedScene()) { _vdsm->getShadowedScene()->osg::Group::traverse(*nv); @@ -811,6 +804,8 @@ MWShadowTechnique::MWShadowTechnique(const MWShadowTechnique& vdsm, const osg::C MWShadowTechnique::~MWShadowTechnique() { + if (_shadowsBin != nullptr) + osgUtil::RenderBin::removeRenderBinPrototype(_shadowsBin); } @@ -3282,3 +3277,18 @@ void SceneUtil::MWShadowTechnique::DebugHUD::addAnotherShadowMap() for(auto& uniformVector : mFrustumUniforms) uniformVector.push_back(new osg::Uniform(osg::Uniform::FLOAT_MAT4, "transform")); } + +osg::ref_ptr SceneUtil::MWShadowTechnique::getOrCreateShadowsBinStateSet() +{ + if (_shadowsBinStateSet == nullptr) + { + if (_shadowsBin == nullptr) + { + _shadowsBin = new ShadowsBin(_castingPrograms); + osgUtil::RenderBin::addRenderBinPrototype(_shadowsBinName, _shadowsBin); + } + _shadowsBinStateSet = new osg::StateSet; + _shadowsBinStateSet->setRenderBinDetails(osg::StateSet::OPAQUE_BIN, _shadowsBinName, osg::StateSet::OVERRIDE_PROTECTED_RENDERBIN_DETAILS); + } + return _shadowsBinStateSet; +} diff --git a/components/sceneutil/mwshadowtechnique.hpp b/components/sceneutil/mwshadowtechnique.hpp index 3f6c0fb765..574d054204 100644 --- a/components/sceneutil/mwshadowtechnique.hpp +++ b/components/sceneutil/mwshadowtechnique.hpp @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -215,8 +216,6 @@ namespace SceneUtil { virtual void createShaders(); - virtual std::array, GL_ALWAYS - GL_NEVER + 1> getCastingPrograms() const { return _castingPrograms; } - virtual bool selectActiveLights(osgUtil::CullVisitor* cv, ViewDependentData* vdd) const; virtual osg::Polytope computeLightViewFrustumPolytope(Frustum& frustum, LightData& positionedLight); @@ -237,6 +236,8 @@ namespace SceneUtil { void setWorldMask(unsigned int worldMask) { _worldMask = worldMask; } + osg::ref_ptr getOrCreateShadowsBinStateSet(); + protected: virtual ~MWShadowTechnique(); @@ -297,6 +298,9 @@ namespace SceneUtil { osg::ref_ptr _debugHud; std::array, GL_ALWAYS - GL_NEVER + 1> _castingPrograms; + const std::string _shadowsBinName = "ShadowsBin_" + std::to_string(reinterpret_cast(this)); + osg::ref_ptr _shadowsBin; + osg::ref_ptr _shadowsBinStateSet; }; } diff --git a/components/sceneutil/shadowsbin.cpp b/components/sceneutil/shadowsbin.cpp index af62b581c9..3e933cbb98 100644 --- a/components/sceneutil/shadowsbin.cpp +++ b/components/sceneutil/shadowsbin.cpp @@ -42,11 +42,7 @@ namespace namespace SceneUtil { -std::array, GL_ALWAYS - GL_NEVER + 1> ShadowsBin::sCastingPrograms = { - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr -}; - -ShadowsBin::ShadowsBin() +ShadowsBin::ShadowsBin(const CastingPrograms& castingPrograms) { mNoTestStateSet = new osg::StateSet; mNoTestStateSet->addUniform(new osg::Uniform("useDiffuseMapForShadowAlpha", false)); @@ -57,10 +53,10 @@ ShadowsBin::ShadowsBin() mShaderAlphaTestStateSet->addUniform(new osg::Uniform("useDiffuseMapForShadowAlpha", true)); mShaderAlphaTestStateSet->setMode(GL_BLEND, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED | osg::StateAttribute::OVERRIDE); - for (size_t i = 0; i < sCastingPrograms.size(); ++i) + for (size_t i = 0; i < castingPrograms.size(); ++i) { mAlphaFuncShaders[i] = new osg::StateSet; - mAlphaFuncShaders[i]->setAttribute(sCastingPrograms[i], osg::StateAttribute::ON | osg::StateAttribute::PROTECTED | osg::StateAttribute::OVERRIDE); + mAlphaFuncShaders[i]->setAttribute(castingPrograms[i], osg::StateAttribute::ON | osg::StateAttribute::PROTECTED | osg::StateAttribute::OVERRIDE); } } @@ -150,13 +146,6 @@ StateGraph* ShadowsBin::cullStateGraph(StateGraph* sg, StateGraph* root, std::un return sg; } -void ShadowsBin::addPrototype(const std::string & name, const std::array, GL_ALWAYS - GL_NEVER + 1>& castingPrograms) -{ - sCastingPrograms = castingPrograms; - osg::ref_ptr bin(new ShadowsBin); - osgUtil::RenderBin::addRenderBinPrototype(name, bin); -} - inline bool ShadowsBin::State::needTexture() const { return mAlphaBlend || (mAlphaFunc && mAlphaFunc->getFunction() != GL_ALWAYS); diff --git a/components/sceneutil/shadowsbin.hpp b/components/sceneutil/shadowsbin.hpp index 1c63caf4bb..2c838d509e 100644 --- a/components/sceneutil/shadowsbin.hpp +++ b/components/sceneutil/shadowsbin.hpp @@ -12,20 +12,17 @@ namespace osg namespace SceneUtil { - /// renderbin which culls redundant state for shadow map rendering class ShadowsBin : public osgUtil::RenderBin { - private: - static std::array, GL_ALWAYS - GL_NEVER + 1> sCastingPrograms; - - osg::ref_ptr mNoTestStateSet; - osg::ref_ptr mShaderAlphaTestStateSet; - - std::array, GL_ALWAYS - GL_NEVER + 1> mAlphaFuncShaders; public: + template + using Array = std::array; + + using CastingPrograms = Array>; + META_Object(SceneUtil, ShadowsBin) - ShadowsBin(); + ShadowsBin(const CastingPrograms& castingPrograms); ShadowsBin(const ShadowsBin& rhs, const osg::CopyOp& copyop) : osgUtil::RenderBin(rhs, copyop) , mNoTestStateSet(rhs.mNoTestStateSet) @@ -65,15 +62,14 @@ namespace SceneUtil osgUtil::StateGraph* cullStateGraph(osgUtil::StateGraph* sg, osgUtil::StateGraph* root, std::unordered_set& uninteresting, bool cullFaceOverridden); - static void addPrototype(const std::string& name, const std::array, GL_ALWAYS - GL_NEVER + 1>& castingPrograms); - }; + private: + ShadowsBin() {} - class ShadowsBinAdder - { - public: - ShadowsBinAdder(const std::string& name, const std::array, GL_ALWAYS - GL_NEVER + 1>& castingPrograms){ ShadowsBin::addPrototype(name, castingPrograms); } - }; + osg::ref_ptr mNoTestStateSet; + osg::ref_ptr mShaderAlphaTestStateSet; + Array> mAlphaFuncShaders; + }; } #endif