#ifndef OPENMW_COMPONENTS_SCENEUTIL_SHADOWBIN_H #define OPENMW_COMPONENTS_SCENEUTIL_SHADOWBIN_H #include #include #include namespace osg { class Material; class AlphaFunc; } namespace SceneUtil { /// renderbin which culls redundant state for shadow map rendering class ShadowsBin : public osgUtil::RenderBin { public: template using Array = std::array; using CastingPrograms = Array>; META_Object(SceneUtil, ShadowsBin) ShadowsBin(const CastingPrograms& castingPrograms); ShadowsBin(const ShadowsBin& rhs, const osg::CopyOp& copyop) : osgUtil::RenderBin(rhs, copyop) , mNoTestStateSet(rhs.mNoTestStateSet) , mShaderAlphaTestStateSet(rhs.mShaderAlphaTestStateSet) , mAlphaFuncShaders(rhs.mAlphaFuncShaders) { } void sortImplementation() override; struct State { bool mAlphaBlend = false; bool mAlphaBlendOverride = false; osg::AlphaFunc* mAlphaFunc = nullptr; bool mAlphaFuncOverride = false; osg::Material* mMaterial = nullptr; bool mMaterialOverride = false; bool mImportantState = false; osg::StateSet* mShadowCastingStateSet = nullptr; bool needTexture() const; bool needShadows() const; // A state is interesting if there's anything about it that might affect whether we can optimise child state bool interesting() const { return !needShadows() || needTexture() || mAlphaBlendOverride || mAlphaFuncOverride || mMaterialOverride || mImportantState; } }; osgUtil::StateGraph* cullStateGraph(osgUtil::StateGraph* sg, osgUtil::StateGraph* root, std::unordered_set& uninteresting, bool cullFaceOverridden); private: ShadowsBin() {} osg::ref_ptr mNoTestStateSet; osg::ref_ptr mShaderAlphaTestStateSet; Array> mAlphaFuncShaders; }; } #endif