From 535c5e328a7c11b6e36364e5e6f640c2708ae4fa Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Tue, 20 Feb 2024 21:02:31 +0000 Subject: [PATCH] Affect correct texture units when disabling shadows for stateset Knowing which are right required making the function non-static, so the shadow manager had to become a singleton as the results of passing it around to where it's needed were hellish. I'm seeing a bunch of OpenGL errors when actually using this, so I'll investigate whether they're happening on master. I'm hesitant to look into it too much, though, as I'm affected by https://gitlab.com/OpenMW/openmw/-/issues/7811, and also have the Windows setting enabled that turns driver timeouts into a BSOD so a kernel dump is collected that I can send to AMD. --- apps/openmw/mwrender/characterpreview.cpp | 2 +- apps/openmw/mwrender/localmap.cpp | 2 +- apps/openmw/mwrender/sky.cpp | 4 +-- apps/openmw/mwrender/water.cpp | 5 ++-- components/sceneutil/shadow.cpp | 36 +++++++++++++++-------- components/sceneutil/shadow.hpp | 10 +++++-- 6 files changed, 37 insertions(+), 22 deletions(-) diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index 9914aec7ca..a4c0181d35 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -247,7 +247,7 @@ namespace MWRender defaultMat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4f(0.f, 0.f, 0.f, 0.f)); stateset->setAttribute(defaultMat); - SceneUtil::ShadowManager::disableShadowsForStateSet(Settings::shadows(), *stateset); + SceneUtil::ShadowManager::instance().disableShadowsForStateSet(*stateset); // assign large value to effectively turn off fog // shaders don't respect glDisable(GL_FOG) diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 892a8b5428..9e934d6f20 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -763,7 +763,7 @@ namespace MWRender lightSource->setStateSetModes(*stateset, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); - SceneUtil::ShadowManager::disableShadowsForStateSet(Settings::shadows(), *stateset); + SceneUtil::ShadowManager::instance().disableShadowsForStateSet(*stateset); // override sun for local map SceneUtil::configureStateSetSunOverride(static_cast(mSceneRoot), light, stateset); diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index af41d2c590..9c8b0658a9 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -220,7 +220,7 @@ namespace camera->setNodeMask(MWRender::Mask_RenderToTexture); camera->setCullMask(MWRender::Mask_Sky); camera->addChild(mEarlyRenderBinRoot); - SceneUtil::ShadowManager::disableShadowsForStateSet(Settings::shadows(), *camera->getOrCreateStateSet()); + SceneUtil::ShadowManager::instance().disableShadowsForStateSet(*camera->getOrCreateStateSet()); } private: @@ -274,7 +274,7 @@ namespace MWRender if (!mSceneManager->getForceShaders()) skyroot->getOrCreateStateSet()->setAttributeAndModes(new osg::Program(), osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED | osg::StateAttribute::ON); - SceneUtil::ShadowManager::disableShadowsForStateSet(Settings::shadows(), *skyroot->getOrCreateStateSet()); + SceneUtil::ShadowManager::instance().disableShadowsForStateSet(*skyroot->getOrCreateStateSet()); parentNode->addChild(skyroot); mEarlyRenderBinRoot = new osg::Group; diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 9fdb0583a2..35c10b81f4 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -276,8 +276,7 @@ namespace MWRender camera->setNodeMask(Mask_RenderToTexture); if (Settings::water().mRefractionScale != 1) // TODO: to be removed with issue #5709 - SceneUtil::ShadowManager::disableShadowsForStateSet( - Settings::shadows(), *camera->getOrCreateStateSet()); + SceneUtil::ShadowManager::instance().disableShadowsForStateSet(*camera->getOrCreateStateSet()); } void apply(osg::Camera* camera) override @@ -353,7 +352,7 @@ namespace MWRender camera->addChild(mClipCullNode); camera->setNodeMask(Mask_RenderToTexture); - SceneUtil::ShadowManager::disableShadowsForStateSet(Settings::shadows(), *camera->getOrCreateStateSet()); + SceneUtil::ShadowManager::instance().disableShadowsForStateSet(*camera->getOrCreateStateSet()); } void apply(osg::Camera* camera) override diff --git a/components/sceneutil/shadow.cpp b/components/sceneutil/shadow.cpp index 04f3b65edd..273016501d 100644 --- a/components/sceneutil/shadow.cpp +++ b/components/sceneutil/shadow.cpp @@ -13,6 +13,16 @@ namespace SceneUtil { using namespace osgShadow; + ShadowManager* ShadowManager::sInstance = nullptr; + + const ShadowManager& ShadowManager::instance() + { + if (sInstance) + return *sInstance; + else + throw std::logic_error("No ShadowManager exists yet"); + } + void ShadowManager::setupShadowSettings( const Settings::ShadowsCategory& settings, Shader::ShaderManager& shaderManager) { @@ -75,15 +85,11 @@ namespace SceneUtil mShadowTechnique->disableDebugHUD(); } - void ShadowManager::disableShadowsForStateSet(const Settings::ShadowsCategory& settings, osg::StateSet& stateset) + void ShadowManager::disableShadowsForStateSet(osg::StateSet& stateset) const { - if (!settings.mEnableShadows) + if (!mEnableShadows) return; - const int numberOfShadowMapsPerLight = settings.mNumberOfShadowMaps; - - int baseShadowTextureUnit = 8 - numberOfShadowMapsPerLight; - osg::ref_ptr fakeShadowMapImage = new osg::Image(); fakeShadowMapImage->allocateImage(1, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT); *(float*)fakeShadowMapImage->data() = std::numeric_limits::infinity(); @@ -92,14 +98,15 @@ namespace SceneUtil fakeShadowMapTexture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); fakeShadowMapTexture->setShadowComparison(true); fakeShadowMapTexture->setShadowCompareFunc(osg::Texture::ShadowCompareFunc::ALWAYS); - for (int i = baseShadowTextureUnit; i < baseShadowTextureUnit + numberOfShadowMapsPerLight; ++i) + for (int i = mShadowSettings->getBaseShadowTextureUnit(); + i < mShadowSettings->getBaseShadowTextureUnit() + mShadowSettings->getNumShadowMapsPerLight(); ++i) { stateset.setTextureAttributeAndModes(i, fakeShadowMapTexture, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED); - stateset.addUniform( - new osg::Uniform(("shadowTexture" + std::to_string(i - baseShadowTextureUnit)).c_str(), i)); - stateset.addUniform( - new osg::Uniform(("shadowTextureUnit" + std::to_string(i - baseShadowTextureUnit)).c_str(), i)); + stateset.addUniform(new osg::Uniform( + ("shadowTexture" + std::to_string(i - mShadowSettings->getBaseShadowTextureUnit())).c_str(), i)); + stateset.addUniform(new osg::Uniform( + ("shadowTextureUnit" + std::to_string(i - mShadowSettings->getBaseShadowTextureUnit())).c_str(), i)); } } @@ -111,6 +118,9 @@ namespace SceneUtil , mOutdoorShadowCastingMask(outdoorShadowCastingMask) , mIndoorShadowCastingMask(indoorShadowCastingMask) { + if (sInstance) + throw std::logic_error("A ShadowManager already exists"); + mShadowedScene->setShadowTechnique(mShadowTechnique); if (Stereo::getStereo()) @@ -127,6 +137,8 @@ namespace SceneUtil mShadowTechnique->setWorldMask(worldMask); enableOutdoorMode(); + + sInstance = this; } ShadowManager::~ShadowManager() @@ -135,7 +147,7 @@ namespace SceneUtil Stereo::Manager::instance().setShadowTechnique(nullptr); } - Shader::ShaderManager::DefineMap ShadowManager::getShadowDefines(const Settings::ShadowsCategory& settings) + Shader::ShaderManager::DefineMap ShadowManager::getShadowDefines(const Settings::ShadowsCategory& settings) const { if (!mEnableShadows) return getShadowsDisabledDefines(); diff --git a/components/sceneutil/shadow.hpp b/components/sceneutil/shadow.hpp index fd82e828b6..952d750051 100644 --- a/components/sceneutil/shadow.hpp +++ b/components/sceneutil/shadow.hpp @@ -26,10 +26,10 @@ namespace SceneUtil class ShadowManager { public: - static void disableShadowsForStateSet(const Settings::ShadowsCategory& settings, osg::StateSet& stateset); - static Shader::ShaderManager::DefineMap getShadowsDisabledDefines(); + static const ShadowManager& instance(); + explicit ShadowManager(osg::ref_ptr sceneRoot, osg::ref_ptr rootNode, unsigned int outdoorShadowCastingMask, unsigned int indoorShadowCastingMask, unsigned int worldMask, const Settings::ShadowsCategory& settings, Shader::ShaderManager& shaderManager); @@ -37,13 +37,17 @@ namespace SceneUtil void setupShadowSettings(const Settings::ShadowsCategory& settings, Shader::ShaderManager& shaderManager); - Shader::ShaderManager::DefineMap getShadowDefines(const Settings::ShadowsCategory& settings); + void disableShadowsForStateSet(osg::StateSet& stateset) const; + + Shader::ShaderManager::DefineMap getShadowDefines(const Settings::ShadowsCategory& settings) const; void enableIndoorMode(const Settings::ShadowsCategory& settings); void enableOutdoorMode(); protected: + static ShadowManager* sInstance; + bool mEnableShadows; osg::ref_ptr mShadowedScene;