From 017c9f7ac9f2f6b7f8adac319e5bb6e9b71d28f7 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 29 Jun 2015 20:19:46 +0200 Subject: [PATCH] Fading for weather particle effects --- apps/openmw/mwrender/sky.cpp | 81 ++++++++++++++++++++++++++++++------ apps/openmw/mwrender/sky.hpp | 2 + 2 files changed, 70 insertions(+), 13 deletions(-) diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 1aa2fd864..56afaadf1 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -687,10 +687,11 @@ private: float mAngle; }; -class RainFader : public SceneUtil::StateSetUpdater +// Updater for alpha value on a node's StateSet. Assumes the node has an existing Material StateAttribute. +class AlphaFader : public SceneUtil::StateSetUpdater { public: - RainFader() + AlphaFader() : mAlpha(1.f) { } @@ -700,20 +701,71 @@ public: mAlpha = alpha; } + virtual void apply(osg::StateSet* stateset, osg::NodeVisitor* nv) + { + osg::Material* mat = static_cast(stateset->getAttribute(osg::StateAttribute::MATERIAL)); + mat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(0,0,0,mAlpha)); + } + + // Helper for adding AlphaFader to a subgraph + class SetupVisitor : public osg::NodeVisitor + { + public: + SetupVisitor() + : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) + { + mAlphaFader = new AlphaFader; + } + + virtual void apply(osg::Node &node) + { + if (osg::StateSet* stateset = node.getStateSet()) + { + if (stateset->getAttribute(osg::StateAttribute::MATERIAL)) + { + SceneUtil::CompositeStateSetUpdater* composite = NULL; + osg::NodeCallback* callback = node.getUpdateCallback(); + while (callback) + { + if ((composite = dynamic_cast(callback))) + break; + callback = callback->getNestedCallback(); + } + + if (composite) + composite->addController(mAlphaFader); + else + node.addUpdateCallback(mAlphaFader); + } + } + traverse(node); + } + + osg::ref_ptr getAlphaFader() + { + return mAlphaFader; + } + + private: + osg::ref_ptr mAlphaFader; + }; + +private: + float mAlpha; +}; + +class RainFader : public AlphaFader +{ +public: virtual void setDefaults(osg::StateSet* stateset) { 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); } - virtual void apply(osg::StateSet* stateset, osg::NodeVisitor* nv) - { - osg::Material* mat = static_cast(stateset->getAttribute(osg::StateAttribute::MATERIAL)); - mat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(0,0,0,mAlpha)); - } - private: float mAlpha; }; @@ -928,6 +980,7 @@ void SkyManager::setWeather(const MWWorld::WeatherResult& weather) mParticleNode = NULL; } mParticleEffect = NULL; + mParticleFader = NULL; } else { @@ -940,6 +993,10 @@ void SkyManager::setWeather(const MWWorld::WeatherResult& weather) SceneUtil::AssignControllerSourcesVisitor assignVisitor(boost::shared_ptr(new SceneUtil::FrameTimeSource)); mParticleEffect->accept(assignVisitor); + + AlphaFader::SetupVisitor alphaFaderSetupVisitor; + mParticleEffect->accept(alphaFaderSetupVisitor); + mParticleFader = alphaFaderSetupVisitor.getAlphaFader(); } } @@ -1025,14 +1082,12 @@ void SkyManager::setWeather(const MWWorld::WeatherResult& weather) mSunGlare->setVisibility(weather.mGlareView * mGlareFade * strength); mSun->setVisibility(weather.mGlareView * strength); - - - if (mParticle.get()) - setAlpha(mParticle, weather.mEffectFade); - */ + */ if (mRainFader) mRainFader->setAlpha(weather.mEffectFade * 0.6); // * Rain_Threshold? + if (mParticleFader) + mParticleFader->setAlpha(weather.mEffectFade); } void SkyManager::setGlare(const float glare) diff --git a/apps/openmw/mwrender/sky.hpp b/apps/openmw/mwrender/sky.hpp index 85174896b..4d1c73e44 100644 --- a/apps/openmw/mwrender/sky.hpp +++ b/apps/openmw/mwrender/sky.hpp @@ -31,6 +31,7 @@ namespace MWRender class Moon; class RainShooter; class RainFader; + class AlphaFader; class SkyManager { @@ -104,6 +105,7 @@ namespace MWRender osg::ref_ptr mParticleNode; osg::ref_ptr mParticleEffect; + osg::ref_ptr mParticleFader; osg::ref_ptr mCloudNode;