diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 93061022c3..389944000c 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" @@ -1137,7 +1139,7 @@ SkyManager::SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneMana , mBaseWindSpeed(0.f) , mEnabled(true) , mSunEnabled(true) - , mWeatherAlpha(0.f) + , mEffectFade(0.f) { osg::ref_ptr skyroot (new CameraRelativeTransform); skyroot->setName("Sky Root"); @@ -1278,16 +1280,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 @@ -1301,19 +1297,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 @@ -1333,56 +1326,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) @@ -1466,6 +1427,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) @@ -1473,7 +1465,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); @@ -1492,6 +1484,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)); @@ -1524,6 +1522,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); @@ -1531,8 +1530,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); @@ -1550,7 +1548,6 @@ void SkyManager::destroyRain() mCounter = nullptr; mRainParticleSystem = nullptr; mRainShooter = nullptr; - mRainFader = nullptr; } SkyManager::~SkyManager() @@ -1589,17 +1586,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(); @@ -1714,7 +1712,6 @@ void SkyManager::setWeather(const WeatherResult& weather) { mParticleNode->removeChild(mParticleEffect); mParticleEffect = nullptr; - mParticleFaders.clear(); } if (mCurrentParticleEffect.empty()) @@ -1740,28 +1737,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); } } } @@ -1848,11 +1843,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; } float SkyManager::getBaseWindSpeed() const diff --git a/apps/openmw/mwrender/sky.hpp b/apps/openmw/mwrender/sky.hpp index 2ec134d09d..f32c40192d 100644 --- a/apps/openmw/mwrender/sky.hpp +++ b/apps/openmw/mwrender/sky.hpp @@ -203,7 +203,6 @@ namespace MWRender osg::ref_ptr mParticleNode; osg::ref_ptr mParticleEffect; - std::vector > mParticleFaders; osg::ref_ptr mUnderwaterSwitch; osg::ref_ptr mCloudNode; @@ -230,7 +229,6 @@ namespace MWRender osg::ref_ptr mPlacer; osg::ref_ptr mCounter; osg::ref_ptr mRainShooter; - osg::ref_ptr mRainFader; bool mCreated; @@ -273,7 +271,7 @@ namespace MWRender bool mEnabled; bool mSunEnabled; - float mWeatherAlpha; + float mEffectFade; osg::Vec4f mMoonScriptColor; };