From 396667f801927b6ea8912e5fded9c5445a4bdc15 Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Tue, 29 Dec 2020 14:49:22 +0300 Subject: [PATCH] Fix weather particle fading Update rain particle system setup --- apps/openmw/mwrender/sky.cpp | 147 ++++++++++++++++------------------- apps/openmw/mwrender/sky.hpp | 4 +- 2 files changed, 70 insertions(+), 81 deletions(-) diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 2920e07dde..3c63c58c66 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -45,6 +45,8 @@ #include #include +#include + #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -1136,7 +1138,7 @@ SkyManager::SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneMana , mWindSpeed(0.f) , mEnabled(true) , mSunEnabled(true) - , mWeatherAlpha(0.f) + , mEffectFade(0.f) { osg::ref_ptr skyroot (new CameraRelativeTransform); skyroot->setName("Sky Root"); @@ -1277,16 +1279,10 @@ private: class AlphaFader : public SceneUtil::StateSetUpdater { public: - /// @param alphaUpdate variable which to update with alpha value - AlphaFader(float *alphaUpdate) - : mAlpha(1.f) - { - mAlphaUpdate = alphaUpdate; - } - - void setAlpha(float alpha) + /// @param alpha the variable alpha value is recovered from + AlphaFader(float& alpha) + : mAlpha(alpha) { - mAlpha = alpha; } void setDefaults(osg::StateSet* stateset) override @@ -1300,19 +1296,16 @@ public: { osg::Material* mat = static_cast(stateset->getAttribute(osg::StateAttribute::MATERIAL)); mat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(0,0,0,mAlpha)); - - if (mAlphaUpdate) - *mAlphaUpdate = mAlpha; } // Helper for adding AlphaFaders to a subgraph class SetupVisitor : public osg::NodeVisitor { public: - SetupVisitor(float *alphaUpdate) + SetupVisitor(float &alpha) : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) + , mAlpha(alpha) { - mAlphaUpdate = alphaUpdate; } void apply(osg::Node &node) override @@ -1332,56 +1325,24 @@ public: callback = callback->getNestedCallback(); } - osg::ref_ptr alphaFader (new AlphaFader(mAlphaUpdate)); + osg::ref_ptr alphaFader (new AlphaFader(mAlpha)); if (composite) composite->addController(alphaFader); else node.addUpdateCallback(alphaFader); - - mAlphaFaders.push_back(alphaFader); } } traverse(node); } - std::vector > getAlphaFaders() - { - return mAlphaFaders; - } - private: - std::vector > mAlphaFaders; - float *mAlphaUpdate; + float &mAlpha; }; protected: - float mAlpha; - float *mAlphaUpdate; -}; - -class RainFader : public AlphaFader -{ -public: - RainFader(float *alphaUpdate): AlphaFader(alphaUpdate) - { - } - - void setDefaults(osg::StateSet* stateset) override - { - osg::ref_ptr mat (new osg::Material); - mat->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4f(1,1,1,1)); - mat->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4f(0,0,0,1)); - mat->setColorMode(osg::Material::OFF); - stateset->setAttributeAndModes(mat, osg::StateAttribute::ON); - } - - void apply(osg::StateSet *stateset, osg::NodeVisitor *nv) override - { - AlphaFader::apply(stateset,nv); - *mAlphaUpdate = mAlpha * 2.0; // mAlpha is limited to 0.6 so multiply by 2 to reach full intensity - } + float &mAlpha; }; void SkyManager::setCamera(osg::Camera *camera) @@ -1465,6 +1426,37 @@ protected: } }; +class WeatherAlphaOperator : public osgParticle::Operator +{ +public: + WeatherAlphaOperator(float& alpha, bool rain) + : mAlpha(alpha) + , mIsRain(rain) + { + } + + osg::Object *cloneType() const override + { + return nullptr; + } + + osg::Object *clone(const osg::CopyOp &op) const override + { + return nullptr; + } + + void operate(osgParticle::Particle *particle, double dt) override + { + constexpr float rainThreshold = 0.6f; // Rain_Threshold? + const float alpha = mIsRain ? mAlpha * rainThreshold : mAlpha; + particle->setAlphaRange(osgParticle::rangef(alpha, alpha)); + } + +private: + float &mAlpha; + bool mIsRain; +}; + void SkyManager::createRain() { if (mRainNode) @@ -1472,7 +1464,7 @@ void SkyManager::createRain() mRainNode = new osg::Group; - mRainParticleSystem = new osgParticle::ParticleSystem; + mRainParticleSystem = new NifOsg::ParticleSystem; osg::Vec3 rainRange = osg::Vec3(mRainDiameter, mRainDiameter, (mRainMinHeight+mRainMaxHeight)/2.f); mRainParticleSystem->setParticleAlignment(osgParticle::ParticleSystem::FIXED); @@ -1491,6 +1483,12 @@ void SkyManager::createRain() stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF); stateset->setMode(GL_BLEND, osg::StateAttribute::ON); + osg::ref_ptr mat (new osg::Material); + mat->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4f(1,1,1,1)); + mat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(1,1,1,1)); + mat->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE); + stateset->setAttributeAndModes(mat, osg::StateAttribute::ON); + osgParticle::Particle& particleTemplate = mRainParticleSystem->getDefaultParticleTemplate(); particleTemplate.setSizeRange(osgParticle::rangef(5.f, 15.f)); particleTemplate.setAlphaRange(osgParticle::rangef(1.f, 1.f)); @@ -1523,6 +1521,7 @@ void SkyManager::createRain() osg::ref_ptr program (new osgParticle::ModularProgram); program->addOperator(new WrapAroundOperator(mCamera,rainRange)); + program->addOperator(new WeatherAlphaOperator(mEffectFade, true)); program->setParticleSystem(mRainParticleSystem); mRainNode->addChild(program); @@ -1530,8 +1529,7 @@ void SkyManager::createRain() mRainNode->addChild(mRainParticleSystem); mRainNode->addChild(updater); - mRainFader = new RainFader(&mWeatherAlpha); - mRainNode->addUpdateCallback(mRainFader); + // Note: if we ever switch to regular geometry rain, it'll need to use an AlphaFader. mRainNode->addCullCallback(mUnderwaterSwitch); mRainNode->setNodeMask(Mask_WeatherParticles); @@ -1549,7 +1547,6 @@ void SkyManager::destroyRain() mCounter = nullptr; mRainParticleSystem = nullptr; mRainShooter = nullptr; - mRainFader = nullptr; } SkyManager::~SkyManager() @@ -1588,17 +1585,18 @@ void SkyManager::update(float duration) if (!mEnabled) { if (mRainIntensityUniform) - mRainIntensityUniform->set((float) 0.0); + mRainIntensityUniform->set(0.f); return; } if (mRainIntensityUniform) { - if (mIsStorm || (!hasRain() && !mParticleNode)) - mRainIntensityUniform->set((float) 0.0); - else - mRainIntensityUniform->set((float) mWeatherAlpha); + float rainIntensity = 0.f; + if (!mIsStorm && (hasRain() || mParticleNode)) + rainIntensity = mEffectFade; + + mRainIntensityUniform->set(rainIntensity); } switchUnderwaterRain(); @@ -1712,7 +1710,6 @@ void SkyManager::setWeather(const WeatherResult& weather) { mParticleNode->removeChild(mParticleEffect); mParticleEffect = nullptr; - mParticleFaders.clear(); } if (mCurrentParticleEffect.empty()) @@ -1738,28 +1735,26 @@ void SkyManager::setWeather(const WeatherResult& weather) SceneUtil::AssignControllerSourcesVisitor assignVisitor(std::shared_ptr(new SceneUtil::FrameTimeSource)); mParticleEffect->accept(assignVisitor); - AlphaFader::SetupVisitor alphaFaderSetupVisitor(&mWeatherAlpha); + AlphaFader::SetupVisitor alphaFaderSetupVisitor(mEffectFade); mParticleEffect->accept(alphaFaderSetupVisitor); - mParticleFaders = alphaFaderSetupVisitor.getAlphaFaders(); SceneUtil::DisableFreezeOnCullVisitor disableFreezeOnCullVisitor; mParticleEffect->accept(disableFreezeOnCullVisitor); - if (!weather.mIsStorm) - { - SceneUtil::FindByClassVisitor findPSVisitor(std::string("ParticleSystem")); - mParticleEffect->accept(findPSVisitor); + SceneUtil::FindByClassVisitor findPSVisitor(std::string("ParticleSystem")); + mParticleEffect->accept(findPSVisitor); - for (unsigned int i = 0; i < findPSVisitor.mFoundNodes.size(); ++i) - { - osgParticle::ParticleSystem *ps = static_cast(findPSVisitor.mFoundNodes[i]); + for (unsigned int i = 0; i < findPSVisitor.mFoundNodes.size(); ++i) + { + osgParticle::ParticleSystem *ps = static_cast(findPSVisitor.mFoundNodes[i]); - osg::ref_ptr program (new osgParticle::ModularProgram); + osg::ref_ptr program (new osgParticle::ModularProgram); + if (!mIsStorm) program->addOperator(new WrapAroundOperator(mCamera,osg::Vec3(1024,1024,800))); - program->setParticleSystem(ps); - mParticleNode->addChild(program); - } + program->addOperator(new WeatherAlphaOperator(mEffectFade, false)); + program->setParticleSystem(ps); + mParticleNode->addChild(program); } } } @@ -1846,11 +1841,7 @@ void SkyManager::setWeather(const WeatherResult& weather) mAtmosphereNightNode->setNodeMask(weather.mNight ? ~0 : 0); - if (mRainFader) - mRainFader->setAlpha(weather.mEffectFade * 0.6); // * Rain_Threshold? - - for (AlphaFader* fader : mParticleFaders) - fader->setAlpha(weather.mEffectFade); + mEffectFade = weather.mEffectFade; } void SkyManager::sunEnable() diff --git a/apps/openmw/mwrender/sky.hpp b/apps/openmw/mwrender/sky.hpp index cf697bd44f..c4e0b57738 100644 --- a/apps/openmw/mwrender/sky.hpp +++ b/apps/openmw/mwrender/sky.hpp @@ -200,7 +200,6 @@ namespace MWRender osg::ref_ptr mParticleNode; osg::ref_ptr mParticleEffect; - std::vector > mParticleFaders; osg::ref_ptr mUnderwaterSwitch; osg::ref_ptr mCloudNode; @@ -227,7 +226,6 @@ namespace MWRender osg::ref_ptr mPlacer; osg::ref_ptr mCounter; osg::ref_ptr mRainShooter; - osg::ref_ptr mRainFader; bool mCreated; @@ -269,7 +267,7 @@ namespace MWRender bool mEnabled; bool mSunEnabled; - float mWeatherAlpha; + float mEffectFade; osg::Vec4f mMoonScriptColor; };