mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-30 07:45:39 +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
4 changed files with 39 additions and 40 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue