mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-04-23 11:42: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:
commit
b72d59b012
@ -279,14 +279,7 @@ void VDSMCameraCullCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// bin has to go inside camera cull or the rendertexture stage will override it
|
// bin has to go inside camera cull or the rendertexture stage will override it
|
||||||
static osg::ref_ptr<osg::StateSet> ss;
|
cv->pushStateSet(_vdsm->getOrCreateShadowsBinStateSet());
|
||||||
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);
|
|
||||||
if (_vdsm->getShadowedScene())
|
if (_vdsm->getShadowedScene())
|
||||||
{
|
{
|
||||||
_vdsm->getShadowedScene()->osg::Group::traverse(*nv);
|
_vdsm->getShadowedScene()->osg::Group::traverse(*nv);
|
||||||
@ -811,6 +804,8 @@ MWShadowTechnique::MWShadowTechnique(const MWShadowTechnique& vdsm, const osg::C
|
|||||||
|
|
||||||
MWShadowTechnique::~MWShadowTechnique()
|
MWShadowTechnique::~MWShadowTechnique()
|
||||||
{
|
{
|
||||||
|
if (_shadowsBin != nullptr)
|
||||||
|
osgUtil::RenderBin::removeRenderBinPrototype(_shadowsBin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3282,3 +3277,18 @@ void SceneUtil::MWShadowTechnique::DebugHUD::addAnotherShadowMap()
|
|||||||
for(auto& uniformVector : mFrustumUniforms)
|
for(auto& uniformVector : mFrustumUniforms)
|
||||||
uniformVector.push_back(new osg::Uniform(osg::Uniform::FLOAT_MAT4, "transform"));
|
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;
|
||||||
|
}
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include <osg/Camera>
|
#include <osg/Camera>
|
||||||
#include <osg/Material>
|
#include <osg/Material>
|
||||||
@ -215,8 +216,6 @@ namespace SceneUtil {
|
|||||||
|
|
||||||
virtual void createShaders();
|
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 bool selectActiveLights(osgUtil::CullVisitor* cv, ViewDependentData* vdd) const;
|
||||||
|
|
||||||
virtual osg::Polytope computeLightViewFrustumPolytope(Frustum& frustum, LightData& positionedLight);
|
virtual osg::Polytope computeLightViewFrustumPolytope(Frustum& frustum, LightData& positionedLight);
|
||||||
@ -237,6 +236,8 @@ namespace SceneUtil {
|
|||||||
|
|
||||||
void setWorldMask(unsigned int worldMask) { _worldMask = worldMask; }
|
void setWorldMask(unsigned int worldMask) { _worldMask = worldMask; }
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::StateSet> getOrCreateShadowsBinStateSet();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~MWShadowTechnique();
|
virtual ~MWShadowTechnique();
|
||||||
|
|
||||||
@ -297,6 +298,9 @@ namespace SceneUtil {
|
|||||||
|
|
||||||
osg::ref_ptr<DebugHUD> _debugHud;
|
osg::ref_ptr<DebugHUD> _debugHud;
|
||||||
std::array<osg::ref_ptr<osg::Program>, GL_ALWAYS - GL_NEVER + 1> _castingPrograms;
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -42,11 +42,7 @@ namespace
|
|||||||
namespace SceneUtil
|
namespace SceneUtil
|
||||||
{
|
{
|
||||||
|
|
||||||
std::array<osg::ref_ptr<osg::Program>, GL_ALWAYS - GL_NEVER + 1> ShadowsBin::sCastingPrograms = {
|
ShadowsBin::ShadowsBin(const CastingPrograms& castingPrograms)
|
||||||
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr
|
|
||||||
};
|
|
||||||
|
|
||||||
ShadowsBin::ShadowsBin()
|
|
||||||
{
|
{
|
||||||
mNoTestStateSet = new osg::StateSet;
|
mNoTestStateSet = new osg::StateSet;
|
||||||
mNoTestStateSet->addUniform(new osg::Uniform("useDiffuseMapForShadowAlpha", false));
|
mNoTestStateSet->addUniform(new osg::Uniform("useDiffuseMapForShadowAlpha", false));
|
||||||
@ -57,10 +53,10 @@ ShadowsBin::ShadowsBin()
|
|||||||
mShaderAlphaTestStateSet->addUniform(new osg::Uniform("useDiffuseMapForShadowAlpha", true));
|
mShaderAlphaTestStateSet->addUniform(new osg::Uniform("useDiffuseMapForShadowAlpha", true));
|
||||||
mShaderAlphaTestStateSet->setMode(GL_BLEND, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED | osg::StateAttribute::OVERRIDE);
|
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] = 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;
|
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
|
inline bool ShadowsBin::State::needTexture() const
|
||||||
{
|
{
|
||||||
return mAlphaBlend || (mAlphaFunc && mAlphaFunc->getFunction() != GL_ALWAYS);
|
return mAlphaBlend || (mAlphaFunc && mAlphaFunc->getFunction() != GL_ALWAYS);
|
||||||
|
@ -12,20 +12,17 @@ namespace osg
|
|||||||
|
|
||||||
namespace SceneUtil
|
namespace SceneUtil
|
||||||
{
|
{
|
||||||
|
|
||||||
/// renderbin which culls redundant state for shadow map rendering
|
/// renderbin which culls redundant state for shadow map rendering
|
||||||
class ShadowsBin : public osgUtil::RenderBin
|
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:
|
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)
|
META_Object(SceneUtil, ShadowsBin)
|
||||||
ShadowsBin();
|
ShadowsBin(const CastingPrograms& castingPrograms);
|
||||||
ShadowsBin(const ShadowsBin& rhs, const osg::CopyOp& copyop)
|
ShadowsBin(const ShadowsBin& rhs, const osg::CopyOp& copyop)
|
||||||
: osgUtil::RenderBin(rhs, copyop)
|
: osgUtil::RenderBin(rhs, copyop)
|
||||||
, mNoTestStateSet(rhs.mNoTestStateSet)
|
, 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);
|
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
|
osg::ref_ptr<osg::StateSet> mNoTestStateSet;
|
||||||
{
|
osg::ref_ptr<osg::StateSet> mShaderAlphaTestStateSet;
|
||||||
public:
|
|
||||||
ShadowsBinAdder(const std::string& name, const std::array<osg::ref_ptr<osg::Program>, GL_ALWAYS - GL_NEVER + 1>& castingPrograms){ ShadowsBin::addPrototype(name, castingPrograms); }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
Array<osg::ref_ptr<osg::StateSet>> mAlphaFuncShaders;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user