From d805886de70eec037db6cd49a9433caa3070bd8a Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Mon, 8 Mar 2021 10:58:51 +0400 Subject: [PATCH 1/2] Double-buffer shader water stateset (bug #5026) --- CHANGELOG.md | 1 + apps/openmw/mwrender/renderingmanager.cpp | 4 +- apps/openmw/mwrender/sky.cpp | 31 ++++--------- apps/openmw/mwrender/sky.hpp | 8 ++-- apps/openmw/mwrender/water.cpp | 55 ++++++++++++++++++----- apps/openmw/mwrender/water.hpp | 7 ++- 6 files changed, 62 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e4b70780..58a09429b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ Bug #4764: Data race in osg ParticleSystem Bug #4765: Data race in ChunkManager -> Array::setBinding Bug #4774: Guards are ignorant of an invisible player that tries to attack them + Bug #5026: Data races with rain intensity uniform set by sky and used by water Bug #5101: Hostile followers travel with the player Bug #5108: Savegame bloating due to inefficient fog textures format Bug #5165: Active spells should use real time intead of timestamps diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index a3aee5c0f..452104642 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -370,7 +370,6 @@ namespace MWRender mSky.reset(new SkyManager(sceneRoot, resourceSystem->getSceneManager())); mSky->setCamera(mViewer->getCamera()); - mSky->setRainIntensityUniform(mWater->getRainIntensityUniform()); source->setStateSetModes(*mRootNode->getOrCreateStateSet(), osg::StateAttribute::ON); @@ -658,6 +657,9 @@ namespace MWRender mUnrefQueue->flush(mWorkQueue.get()); + float rainIntensity = mSky->getEffectFade(); + mWater->setRainIntensity(rainIntensity); + if (!paused) { mEffectManager->update(dt); diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 389944000..d6b1f9066 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -1113,7 +1113,6 @@ private: SkyManager::SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneManager) : mSceneManager(sceneManager) , mCamera(nullptr) - , mRainIntensityUniform(nullptr) , mAtmosphereNightRoll(0.f) , mCreated(false) , mIsStorm(false) @@ -1163,11 +1162,6 @@ SkyManager::SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneMana mUnderwaterSwitch = new UnderwaterSwitchCallback(skyroot); } -void SkyManager::setRainIntensityUniform(osg::Uniform *uniform) -{ - mRainIntensityUniform = uniform; -} - void SkyManager::create() { assert(!mCreated); @@ -1576,30 +1570,21 @@ bool SkyManager::isEnabled() return mEnabled; } -bool SkyManager::hasRain() +bool SkyManager::hasRain() const { return mRainNode != nullptr; } -void SkyManager::update(float duration) +float SkyManager::getEffectFade() const { - if (!mEnabled) - { - if (mRainIntensityUniform) - mRainIntensityUniform->set(0.f); - - return; - } - - if (mRainIntensityUniform) - { - float rainIntensity = 0.f; - if (!mIsStorm && (hasRain() || mParticleNode)) - rainIntensity = mEffectFade; + if (mEnabled && !mIsStorm && (hasRain() || mParticleNode)) + return mEffectFade; - mRainIntensityUniform->set(rainIntensity); - } + return 0.f; +} +void SkyManager::update(float duration) +{ switchUnderwaterRain(); if (mIsStorm) diff --git a/apps/openmw/mwrender/sky.hpp b/apps/openmw/mwrender/sky.hpp index f32c40192..081221398 100644 --- a/apps/openmw/mwrender/sky.hpp +++ b/apps/openmw/mwrender/sky.hpp @@ -7,7 +7,6 @@ #include #include -#include namespace osg { @@ -157,7 +156,9 @@ namespace MWRender bool isEnabled(); - bool hasRain(); + bool hasRain() const; + + float getEffectFade() const; void setRainSpeed(float speed); @@ -180,8 +181,6 @@ namespace MWRender void setCamera(osg::Camera *camera); - void setRainIntensityUniform(osg::Uniform *uniform); - float getBaseWindSpeed() const; private: @@ -196,7 +195,6 @@ namespace MWRender Resource::SceneManager* mSceneManager; osg::Camera *mCamera; - osg::Uniform *mRainIntensityUniform; osg::ref_ptr mRootNode; osg::ref_ptr mEarlyRenderBinRoot; diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 1cc5a3cb7..af24a8648 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -208,6 +208,37 @@ public: } }; +class RainIntensityUpdater : public SceneUtil::StateSetUpdater +{ +public: + RainIntensityUpdater() + : mRainIntensity(0.f) + { + } + + void setRainIntensity(float rainIntensity) + { + mRainIntensity = rainIntensity; + } + +protected: + void setDefaults(osg::StateSet* stateset) override + { + osg::ref_ptr rainIntensityUniform = new osg::Uniform("rainIntensity", 0.0f); + stateset->addUniform(rainIntensityUniform.get()); + } + + void apply(osg::StateSet* stateset, osg::NodeVisitor* /*nv*/) override + { + osg::ref_ptr rainIntensityUniform = stateset->getUniform("rainIntensity"); + if (rainIntensityUniform != nullptr) + rainIntensityUniform->set(mRainIntensity); + } + +private: + float mRainIntensity; +}; + osg::ref_ptr readPngImage (const std::string& file) { // use boost in favor of osgDB::readImage, to handle utf-8 path issues on Windows @@ -431,7 +462,8 @@ public: Water::Water(osg::Group *parent, osg::Group* sceneRoot, Resource::ResourceSystem *resourceSystem, osgUtil::IncrementalCompileOperation *ico, const std::string& resourcePath) - : mParent(parent) + : mRainIntensityUpdater(nullptr) + , mParent(parent) , mSceneRoot(sceneRoot) , mResourceSystem(resourceSystem) , mResourcePath(resourcePath) @@ -463,8 +495,6 @@ Water::Water(osg::Group *parent, osg::Group* sceneRoot, Resource::ResourceSystem setHeight(mTop); - mRainIntensityUniform = new osg::Uniform("rainIntensity",(float) 0.0); - updateWaterMaterial(); if (ico) @@ -494,11 +524,6 @@ void Water::setCullCallback(osg::Callback* callback) } } -osg::Uniform *Water::getRainIntensityUniform() -{ - return mRainIntensityUniform.get(); -} - void Water::updateWaterMaterial() { if (mReflection) @@ -556,6 +581,8 @@ void Water::createSimpleWaterStateSet(osg::Node* node, float alpha) osg::ref_ptr stateset = SceneUtil::createSimpleWaterStateSet(alpha, MWRender::RenderBin_Water); node->setStateSet(stateset); + node->setUpdateCallback(nullptr); + mRainIntensityUpdater = nullptr; // Add animated textures std::vector > textures; @@ -639,15 +666,15 @@ void Water::createShaderWaterStateSet(osg::Node* node, Reflection* reflection, R shaderStateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF); - shaderStateset->addUniform(mRainIntensityUniform.get()); - osg::ref_ptr program (new osg::Program); program->addShader(vertexShader); program->addShader(fragmentShader); shaderStateset->setAttributeAndModes(program, osg::StateAttribute::ON); node->setStateSet(shaderStateset); - node->setUpdateCallback(nullptr); + + mRainIntensityUpdater = new RainIntensityUpdater(); + node->setUpdateCallback(mRainIntensityUpdater); } void Water::processChangedSettings(const Settings::CategorySettingVector& settings) @@ -730,6 +757,12 @@ void Water::setHeight(const float height) mRefraction->setWaterLevel(mTop); } +void Water::setRainIntensity(float rainIntensity) +{ + if (mRainIntensityUpdater) + mRainIntensityUpdater->setRainIntensity(rainIntensity); +} + void Water::update(float dt) { mSimulation->update(dt); diff --git a/apps/openmw/mwrender/water.hpp b/apps/openmw/mwrender/water.hpp index 3787ef426..ec7dc95db 100644 --- a/apps/openmw/mwrender/water.hpp +++ b/apps/openmw/mwrender/water.hpp @@ -6,7 +6,6 @@ #include #include -#include #include #include @@ -46,11 +45,12 @@ namespace MWRender class Refraction; class Reflection; class RippleSimulation; + class RainIntensityUpdater; /// Water rendering class Water { - osg::ref_ptr mRainIntensityUniform; + osg::ref_ptr mRainIntensityUpdater; osg::ref_ptr mParent; osg::ref_ptr mSceneRoot; @@ -112,6 +112,7 @@ namespace MWRender void changeCell(const MWWorld::CellStore* store); void setHeight(const float height); + void setRainIntensity(const float rainIntensity); void update(float dt); @@ -119,8 +120,6 @@ namespace MWRender osg::Camera *getRefractionCamera(); void processChangedSettings(const Settings::CategorySettingVector& settings); - - osg::Uniform *getRainIntensityUniform(); }; } From 38679013fe6e426e3609ff833c1b55b02e0e644a Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Wed, 10 Mar 2021 19:10:17 +0400 Subject: [PATCH 2/2] Give meaningful name to the mEffectFade --- apps/openmw/mwrender/renderingmanager.cpp | 2 +- apps/openmw/mwrender/sky.cpp | 14 +++++++------- apps/openmw/mwrender/sky.hpp | 6 +++--- apps/openmw/mwworld/weather.cpp | 6 +++--- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 452104642..a6062f444 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -657,7 +657,7 @@ namespace MWRender mUnrefQueue->flush(mWorkQueue.get()); - float rainIntensity = mSky->getEffectFade(); + float rainIntensity = mSky->getPrecipitationAlpha(); mWater->setRainIntensity(rainIntensity); if (!paused) diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index d6b1f9066..ddd4a0660 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -1138,7 +1138,7 @@ SkyManager::SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneMana , mBaseWindSpeed(0.f) , mEnabled(true) , mSunEnabled(true) - , mEffectFade(0.f) + , mPrecipitationAlpha(0.f) { osg::ref_ptr skyroot (new CameraRelativeTransform); skyroot->setName("Sky Root"); @@ -1516,7 +1516,7 @@ void SkyManager::createRain() osg::ref_ptr program (new osgParticle::ModularProgram); program->addOperator(new WrapAroundOperator(mCamera,rainRange)); - program->addOperator(new WeatherAlphaOperator(mEffectFade, true)); + program->addOperator(new WeatherAlphaOperator(mPrecipitationAlpha, true)); program->setParticleSystem(mRainParticleSystem); mRainNode->addChild(program); @@ -1575,10 +1575,10 @@ bool SkyManager::hasRain() const return mRainNode != nullptr; } -float SkyManager::getEffectFade() const +float SkyManager::getPrecipitationAlpha() const { if (mEnabled && !mIsStorm && (hasRain() || mParticleNode)) - return mEffectFade; + return mPrecipitationAlpha; return 0.f; } @@ -1722,7 +1722,7 @@ void SkyManager::setWeather(const WeatherResult& weather) SceneUtil::AssignControllerSourcesVisitor assignVisitor(std::shared_ptr(new SceneUtil::FrameTimeSource)); mParticleEffect->accept(assignVisitor); - AlphaFader::SetupVisitor alphaFaderSetupVisitor(mEffectFade); + AlphaFader::SetupVisitor alphaFaderSetupVisitor(mPrecipitationAlpha); mParticleEffect->accept(alphaFaderSetupVisitor); @@ -1739,7 +1739,7 @@ void SkyManager::setWeather(const WeatherResult& weather) osg::ref_ptr program (new osgParticle::ModularProgram); if (!mIsStorm) program->addOperator(new WrapAroundOperator(mCamera,osg::Vec3(1024,1024,800))); - program->addOperator(new WeatherAlphaOperator(mEffectFade, false)); + program->addOperator(new WeatherAlphaOperator(mPrecipitationAlpha, false)); program->setParticleSystem(ps); mParticleNode->addChild(program); } @@ -1828,7 +1828,7 @@ void SkyManager::setWeather(const WeatherResult& weather) mAtmosphereNightNode->setNodeMask(weather.mNight ? ~0 : 0); - mEffectFade = weather.mEffectFade; + mPrecipitationAlpha = weather.mPrecipitationAlpha; } float SkyManager::getBaseWindSpeed() const diff --git a/apps/openmw/mwrender/sky.hpp b/apps/openmw/mwrender/sky.hpp index 081221398..f8c501dda 100644 --- a/apps/openmw/mwrender/sky.hpp +++ b/apps/openmw/mwrender/sky.hpp @@ -87,7 +87,7 @@ namespace MWRender std::string mParticleEffect; std::string mRainEffect; - float mEffectFade; + float mPrecipitationAlpha; float mRainDiameter; float mRainMinHeight; @@ -158,7 +158,7 @@ namespace MWRender bool hasRain() const; - float getEffectFade() const; + float getPrecipitationAlpha() const; void setRainSpeed(float speed); @@ -269,7 +269,7 @@ namespace MWRender bool mEnabled; bool mSunEnabled; - float mEffectFade; + float mPrecipitationAlpha; osg::Vec4f mMoonScriptColor; }; diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index 415e69d20..4bdd784db 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -1129,7 +1129,7 @@ inline void WeatherManager::calculateResult(const int weatherID, const float gam mResult.mGlareView = current.mGlareView; mResult.mAmbientLoopSoundID = current.mAmbientLoopSoundID; mResult.mAmbientSoundVolume = 1.f; - mResult.mEffectFade = 1.f; + mResult.mPrecipitationAlpha = 1.f; mResult.mIsStorm = current.mIsStorm; @@ -1236,7 +1236,7 @@ inline void WeatherManager::calculateTransitionResult(const float factor, const mResult.mRainSpeed = current.mRainSpeed; mResult.mRainEntranceSpeed = current.mRainEntranceSpeed; mResult.mAmbientSoundVolume = 1 - factor / threshold; - mResult.mEffectFade = mResult.mAmbientSoundVolume; + mResult.mPrecipitationAlpha = mResult.mAmbientSoundVolume; mResult.mAmbientLoopSoundID = current.mAmbientLoopSoundID; mResult.mRainDiameter = current.mRainDiameter; mResult.mRainMinHeight = current.mRainMinHeight; @@ -1251,7 +1251,7 @@ inline void WeatherManager::calculateTransitionResult(const float factor, const mResult.mRainSpeed = other.mRainSpeed; mResult.mRainEntranceSpeed = other.mRainEntranceSpeed; mResult.mAmbientSoundVolume = (factor - threshold) / (1 - threshold); - mResult.mEffectFade = mResult.mAmbientSoundVolume; + mResult.mPrecipitationAlpha = mResult.mAmbientSoundVolume; mResult.mAmbientLoopSoundID = other.mAmbientLoopSoundID; mResult.mRainDiameter = other.mRainDiameter;