From 535c5e328a7c11b6e36364e5e6f640c2708ae4fa Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Tue, 20 Feb 2024 21:02:31 +0000 Subject: [PATCH 1/7] 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; From 7391bf2814ce24683fb718f8367db8dbe799cba7 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Tue, 20 Feb 2024 21:23:23 +0000 Subject: [PATCH 2/7] Fix OpenGL errors There's no reason to use the AndModes variant as we never (intentionally) attempt to sample from a shadow map via the FFP. --- components/sceneutil/shadow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/sceneutil/shadow.cpp b/components/sceneutil/shadow.cpp index 273016501d..d1e4cf814c 100644 --- a/components/sceneutil/shadow.cpp +++ b/components/sceneutil/shadow.cpp @@ -101,7 +101,7 @@ namespace SceneUtil for (int i = mShadowSettings->getBaseShadowTextureUnit(); i < mShadowSettings->getBaseShadowTextureUnit() + mShadowSettings->getNumShadowMapsPerLight(); ++i) { - stateset.setTextureAttributeAndModes(i, fakeShadowMapTexture, + stateset.setTextureAttribute(i, fakeShadowMapTexture, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED); stateset.addUniform(new osg::Uniform( ("shadowTexture" + std::to_string(i - mShadowSettings->getBaseShadowTextureUnit())).c_str(), i)); From 132c43affa64c2d75678231bb2acdd4d9bd367c7 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Tue, 20 Feb 2024 22:14:13 +0000 Subject: [PATCH 3/7] Fix warning Also attempt to make an equivalent warning fire with MSVC, then have to fix other stuff because /WX wasn't working, then back out of enabling the warning because none of the ones I could find disliked the old code. --- CMakeLists.txt | 33 ++++++++++++++++----------------- components/sceneutil/shadow.cpp | 2 +- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f13def9ab0..d1ad7fa387 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -718,67 +718,66 @@ if (WIN32) ) foreach(d ${WARNINGS_DISABLE}) - set(WARNINGS "${WARNINGS} /wd${d}") + list(APPEND WARNINGS "/wd${d}") endforeach(d) if(OPENMW_MSVC_WERROR) - set(WARNINGS "${WARNINGS} /WX") + list(APPEND WARNINGS "/WX") endif() - set_target_properties(components PROPERTIES COMPILE_FLAGS "${WARNINGS}") - set_target_properties(osg-ffmpeg-videoplayer PROPERTIES COMPILE_FLAGS "${WARNINGS}") + target_compile_options(components PRIVATE ${WARNINGS}) + target_compile_options(osg-ffmpeg-videoplayer PRIVATE ${WARNINGS}) if (MSVC_VERSION GREATER_EQUAL 1915 AND MSVC_VERSION LESS 1920) target_compile_definitions(components INTERFACE _ENABLE_EXTENDED_ALIGNED_STORAGE) endif() if (BUILD_BSATOOL) - set_target_properties(bsatool PROPERTIES COMPILE_FLAGS "${WARNINGS}") + target_compile_options(bsatool PRIVATE ${WARNINGS}) endif() if (BUILD_ESMTOOL) - set_target_properties(esmtool PROPERTIES COMPILE_FLAGS "${WARNINGS}") + target_compile_options(esmtool PRIVATE ${WARNINGS}) endif() if (BUILD_ESSIMPORTER) - set_target_properties(openmw-essimporter PROPERTIES COMPILE_FLAGS "${WARNINGS}") + target_compile_options(openmw-essimporter PRIVATE ${WARNINGS}) endif() if (BUILD_LAUNCHER) - set_target_properties(openmw-launcher PROPERTIES COMPILE_FLAGS "${WARNINGS}") + target_compile_options(openmw-launcher PRIVATE ${WARNINGS}) endif() if (BUILD_MWINIIMPORTER) - set_target_properties(openmw-iniimporter PROPERTIES COMPILE_FLAGS "${WARNINGS}") + target_compile_options(openmw-iniimporter PRIVATE ${WARNINGS}) endif() if (BUILD_OPENCS) - set_target_properties(openmw-cs PROPERTIES COMPILE_FLAGS "${WARNINGS}") + target_compile_options(openmw-cs PRIVATE ${WARNINGS}) endif() if (BUILD_OPENMW) - set_target_properties(openmw PROPERTIES COMPILE_FLAGS "${WARNINGS}") + target_compile_options(openmw PRIVATE ${WARNINGS}) endif() if (BUILD_WIZARD) - set_target_properties(openmw-wizard PROPERTIES COMPILE_FLAGS "${WARNINGS}") + target_compile_options(openmw-wizard PRIVATE ${WARNINGS}) endif() if (BUILD_UNITTESTS) - set_target_properties(openmw_test_suite PROPERTIES COMPILE_FLAGS "${WARNINGS}") + target_compile_options(openmw_test_suite PRIVATE ${WARNINGS}) endif() if (BUILD_BENCHMARKS) - set_target_properties(openmw_detournavigator_navmeshtilescache_benchmark PROPERTIES COMPILE_FLAGS "${WARNINGS}") + target_compile_options(openmw_detournavigator_navmeshtilescache_benchmark PRIVATE ${WARNINGS}) endif() if (BUILD_NAVMESHTOOL) - set_target_properties(openmw-navmeshtool PROPERTIES COMPILE_FLAGS "${WARNINGS}") + target_compile_options(openmw-navmeshtool PRIVATE ${WARNINGS}) endif() if (BUILD_BULLETOBJECTTOOL) - set(WARNINGS "${WARNINGS} ${MT_BUILD}") - set_target_properties(openmw-bulletobjecttool PROPERTIES COMPILE_FLAGS "${WARNINGS}") + target_compile_options(openmw-bulletobjecttool PRIVATE ${WARNINGS} ${MT_BUILD}) endif() endif(MSVC) diff --git a/components/sceneutil/shadow.cpp b/components/sceneutil/shadow.cpp index d1e4cf814c..9351ec249e 100644 --- a/components/sceneutil/shadow.cpp +++ b/components/sceneutil/shadow.cpp @@ -98,7 +98,7 @@ 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 = mShadowSettings->getBaseShadowTextureUnit(); + for (unsigned int i = mShadowSettings->getBaseShadowTextureUnit(); i < mShadowSettings->getBaseShadowTextureUnit() + mShadowSettings->getNumShadowMapsPerLight(); ++i) { stateset.setTextureAttribute(i, fakeShadowMapTexture, From d282fdb77a7bfd6dd5a14dde30708b8f671c5ff8 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Tue, 20 Feb 2024 23:10:03 +0000 Subject: [PATCH 4/7] Eliminate unused uniform --- components/sceneutil/mwshadowtechnique.cpp | 9 --------- components/sceneutil/shadow.cpp | 2 -- files/shaders/compatibility/shadows_vertex.glsl | 1 - 3 files changed, 12 deletions(-) diff --git a/components/sceneutil/mwshadowtechnique.cpp b/components/sceneutil/mwshadowtechnique.cpp index 06930ebe59..d0c270971a 100644 --- a/components/sceneutil/mwshadowtechnique.cpp +++ b/components/sceneutil/mwshadowtechnique.cpp @@ -1025,7 +1025,6 @@ void MWShadowTechnique::cull(osgUtil::CullVisitor& cv) { dummyState->setTextureAttribute(i, _fallbackShadowMapTexture, osg::StateAttribute::ON); dummyState->addUniform(new osg::Uniform(("shadowTexture" + std::to_string(i - baseUnit)).c_str(), i)); - dummyState->addUniform(new osg::Uniform(("shadowTextureUnit" + std::to_string(i - baseUnit)).c_str(), i)); } cv.pushStateSet(dummyState); @@ -1711,14 +1710,6 @@ void MWShadowTechnique::createShaders() for (auto& perFrameUniformList : _uniforms) perFrameUniformList.emplace_back(shadowTextureSampler.get()); } - - { - std::stringstream sstr; - sstr<<"shadowTextureUnit"< shadowTextureUnit = new osg::Uniform(sstr.str().c_str(),(int)(settings->getBaseShadowTextureUnit()+sm_i)); - for (auto& perFrameUniformList : _uniforms) - perFrameUniformList.emplace_back(shadowTextureUnit.get()); - } } switch(settings->getShaderHint()) diff --git a/components/sceneutil/shadow.cpp b/components/sceneutil/shadow.cpp index 9351ec249e..b32be08386 100644 --- a/components/sceneutil/shadow.cpp +++ b/components/sceneutil/shadow.cpp @@ -105,8 +105,6 @@ namespace SceneUtil osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED); 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)); } } diff --git a/files/shaders/compatibility/shadows_vertex.glsl b/files/shaders/compatibility/shadows_vertex.glsl index a99a4a10e6..23fbc74988 100644 --- a/files/shaders/compatibility/shadows_vertex.glsl +++ b/files/shaders/compatibility/shadows_vertex.glsl @@ -3,7 +3,6 @@ #if SHADOWS @foreach shadow_texture_unit_index @shadow_texture_unit_list uniform mat4 shadowSpaceMatrix@shadow_texture_unit_index; - uniform int shadowTextureUnit@shadow_texture_unit_index; varying vec4 shadowSpaceCoords@shadow_texture_unit_index; #if @perspectiveShadowMaps From 8c92f6ee87f315255281c5ee7216b19a5de3d682 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Tue, 20 Feb 2024 23:10:23 +0000 Subject: [PATCH 5/7] Make uniform a signed int again --- components/sceneutil/shadow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/sceneutil/shadow.cpp b/components/sceneutil/shadow.cpp index b32be08386..37a11031aa 100644 --- a/components/sceneutil/shadow.cpp +++ b/components/sceneutil/shadow.cpp @@ -104,7 +104,7 @@ namespace SceneUtil stateset.setTextureAttribute(i, fakeShadowMapTexture, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED); stateset.addUniform(new osg::Uniform( - ("shadowTexture" + std::to_string(i - mShadowSettings->getBaseShadowTextureUnit())).c_str(), i)); + ("shadowTexture" + std::to_string(i - mShadowSettings->getBaseShadowTextureUnit())).c_str(), static_cast(i))); } } From 3335ccbc32facfe6afc8e6a433f8fa2bca2de23c Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Tue, 20 Feb 2024 23:51:42 +0000 Subject: [PATCH 6/7] Capitulate --- components/sceneutil/shadow.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/sceneutil/shadow.cpp b/components/sceneutil/shadow.cpp index 37a11031aa..0d68ccaa0f 100644 --- a/components/sceneutil/shadow.cpp +++ b/components/sceneutil/shadow.cpp @@ -104,7 +104,8 @@ namespace SceneUtil stateset.setTextureAttribute(i, fakeShadowMapTexture, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED); stateset.addUniform(new osg::Uniform( - ("shadowTexture" + std::to_string(i - mShadowSettings->getBaseShadowTextureUnit())).c_str(), static_cast(i))); + ("shadowTexture" + std::to_string(i - mShadowSettings->getBaseShadowTextureUnit())).c_str(), + static_cast(i))); } } From fdd88fd2953c2beccf83c913487fc82055728657 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Wed, 21 Feb 2024 13:30:09 +0000 Subject: [PATCH 7/7] c h a n g e l o g --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 671103cd21..7bf9d48b5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -71,6 +71,7 @@ Bug #7084: Resurrecting an actor doesn't take into account base record changes Bug #7088: Deleting last save game of last character doesn't clear character name/details Bug #7092: BSA archives from higher priority directories don't take priority + Bug #7102: Some HQ Creatures mod models can hit the 8 texture slots limit with 0.48 Bug #7103: Multiple paths pointing to the same plugin but with different cases lead to automatically removed config entries Bug #7122: Teleportation to underwater should cancel active water walking effect Bug #7131: MyGUI log spam when post processing HUD is open