1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-30 18:45:38 +00:00

Merge branch 'fix_shadows_bin_crash' into 'master'

Fix crash on exit with enabled shadows (#6256)

Closes #6256

See merge request OpenMW/openmw!1191
This commit is contained in:
psi29a 2021-11-09 15:58:03 +00:00
commit b72d59b012
4 changed files with 39 additions and 40 deletions

View file

@ -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<osg::StateSet> 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<osg::StateSet> 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;
}

View file

@ -21,6 +21,7 @@
#include <array>
#include <mutex>
#include <string>
#include <osg/Camera>
#include <osg/Material>
@ -215,8 +216,6 @@ namespace SceneUtil {
virtual void createShaders();
virtual std::array<osg::ref_ptr<osg::Program>, 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<osg::StateSet> getOrCreateShadowsBinStateSet();
protected:
virtual ~MWShadowTechnique();
@ -297,6 +298,9 @@ namespace SceneUtil {
osg::ref_ptr<DebugHUD> _debugHud;
std::array<osg::ref_ptr<osg::Program>, GL_ALWAYS - GL_NEVER + 1> _castingPrograms;
const std::string _shadowsBinName = "ShadowsBin_" + std::to_string(reinterpret_cast<std::uint64_t>(this));
osg::ref_ptr<osgUtil::RenderBin> _shadowsBin;
osg::ref_ptr<osg::StateSet> _shadowsBinStateSet;
};
}

View file

@ -42,11 +42,7 @@ namespace
namespace SceneUtil
{
std::array<osg::ref_ptr<osg::Program>, 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<osg::ref_ptr<osg::Program>, GL_ALWAYS - GL_NEVER + 1>& castingPrograms)
{
sCastingPrograms = castingPrograms;
osg::ref_ptr<osgUtil::RenderBin> bin(new ShadowsBin);
osgUtil::RenderBin::addRenderBinPrototype(name, bin);
}
inline bool ShadowsBin::State::needTexture() const
{
return mAlphaBlend || (mAlphaFunc && mAlphaFunc->getFunction() != GL_ALWAYS);

View file

@ -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<osg::ref_ptr<osg::Program>, GL_ALWAYS - GL_NEVER + 1> sCastingPrograms;
osg::ref_ptr<osg::StateSet> mNoTestStateSet;
osg::ref_ptr<osg::StateSet> mShaderAlphaTestStateSet;
std::array<osg::ref_ptr<osg::StateSet>, GL_ALWAYS - GL_NEVER + 1> mAlphaFuncShaders;
public:
template <class T>
using Array = std::array<T, GL_ALWAYS - GL_NEVER + 1>;
using CastingPrograms = Array<osg::ref_ptr<osg::Program>>;
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<osgUtil::StateGraph*>& uninteresting, bool cullFaceOverridden);
static void addPrototype(const std::string& name, const std::array<osg::ref_ptr<osg::Program>, GL_ALWAYS - GL_NEVER + 1>& castingPrograms);
};
private:
ShadowsBin() {}
class ShadowsBinAdder
{
public:
ShadowsBinAdder(const std::string& name, const std::array<osg::ref_ptr<osg::Program>, GL_ALWAYS - GL_NEVER + 1>& castingPrograms){ ShadowsBin::addPrototype(name, castingPrograms); }
};
osg::ref_ptr<osg::StateSet> mNoTestStateSet;
osg::ref_ptr<osg::StateSet> mShaderAlphaTestStateSet;
Array<osg::ref_ptr<osg::StateSet>> mAlphaFuncShaders;
};
}
#endif