Merge branch 'weatheralpha' into 'master'

Fix weather particle fading

Closes #5455

See merge request OpenMW/openmw!506
pull/3047/head
psi29a 4 years ago
commit bcbe144a1d

@ -45,6 +45,8 @@
#include <components/sceneutil/visitor.hpp> #include <components/sceneutil/visitor.hpp>
#include <components/sceneutil/shadow.hpp> #include <components/sceneutil/shadow.hpp>
#include <components/nifosg/particle.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
@ -1137,7 +1139,7 @@ SkyManager::SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneMana
, mBaseWindSpeed(0.f) , mBaseWindSpeed(0.f)
, mEnabled(true) , mEnabled(true)
, mSunEnabled(true) , mSunEnabled(true)
, mWeatherAlpha(0.f) , mEffectFade(0.f)
{ {
osg::ref_ptr<CameraRelativeTransform> skyroot (new CameraRelativeTransform); osg::ref_ptr<CameraRelativeTransform> skyroot (new CameraRelativeTransform);
skyroot->setName("Sky Root"); skyroot->setName("Sky Root");
@ -1278,16 +1280,10 @@ private:
class AlphaFader : public SceneUtil::StateSetUpdater class AlphaFader : public SceneUtil::StateSetUpdater
{ {
public: public:
/// @param alphaUpdate variable which to update with alpha value /// @param alpha the variable alpha value is recovered from
AlphaFader(float *alphaUpdate) AlphaFader(float& alpha)
: mAlpha(1.f) : mAlpha(alpha)
{
mAlphaUpdate = alphaUpdate;
}
void setAlpha(float alpha)
{ {
mAlpha = alpha;
} }
void setDefaults(osg::StateSet* stateset) override void setDefaults(osg::StateSet* stateset) override
@ -1301,19 +1297,16 @@ public:
{ {
osg::Material* mat = static_cast<osg::Material*>(stateset->getAttribute(osg::StateAttribute::MATERIAL)); osg::Material* mat = static_cast<osg::Material*>(stateset->getAttribute(osg::StateAttribute::MATERIAL));
mat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(0,0,0,mAlpha)); mat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(0,0,0,mAlpha));
if (mAlphaUpdate)
*mAlphaUpdate = mAlpha;
} }
// Helper for adding AlphaFaders to a subgraph // Helper for adding AlphaFaders to a subgraph
class SetupVisitor : public osg::NodeVisitor class SetupVisitor : public osg::NodeVisitor
{ {
public: public:
SetupVisitor(float *alphaUpdate) SetupVisitor(float &alpha)
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
, mAlpha(alpha)
{ {
mAlphaUpdate = alphaUpdate;
} }
void apply(osg::Node &node) override void apply(osg::Node &node) override
@ -1333,56 +1326,24 @@ public:
callback = callback->getNestedCallback(); callback = callback->getNestedCallback();
} }
osg::ref_ptr<AlphaFader> alphaFader (new AlphaFader(mAlphaUpdate)); osg::ref_ptr<AlphaFader> alphaFader (new AlphaFader(mAlpha));
if (composite) if (composite)
composite->addController(alphaFader); composite->addController(alphaFader);
else else
node.addUpdateCallback(alphaFader); node.addUpdateCallback(alphaFader);
mAlphaFaders.push_back(alphaFader);
} }
} }
traverse(node); traverse(node);
} }
std::vector<osg::ref_ptr<AlphaFader> > getAlphaFaders()
{
return mAlphaFaders;
}
private: private:
std::vector<osg::ref_ptr<AlphaFader> > mAlphaFaders; float &mAlpha;
float *mAlphaUpdate;
}; };
protected: protected:
float mAlpha; float &mAlpha;
float *mAlphaUpdate;
};
class RainFader : public AlphaFader
{
public:
RainFader(float *alphaUpdate): AlphaFader(alphaUpdate)
{
}
void setDefaults(osg::StateSet* stateset) override
{
osg::ref_ptr<osg::Material> 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
}
}; };
void SkyManager::setCamera(osg::Camera *camera) 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() void SkyManager::createRain()
{ {
if (mRainNode) if (mRainNode)
@ -1473,7 +1465,7 @@ void SkyManager::createRain()
mRainNode = new osg::Group; mRainNode = new osg::Group;
mRainParticleSystem = new osgParticle::ParticleSystem; mRainParticleSystem = new NifOsg::ParticleSystem;
osg::Vec3 rainRange = osg::Vec3(mRainDiameter, mRainDiameter, (mRainMinHeight+mRainMaxHeight)/2.f); osg::Vec3 rainRange = osg::Vec3(mRainDiameter, mRainDiameter, (mRainMinHeight+mRainMaxHeight)/2.f);
mRainParticleSystem->setParticleAlignment(osgParticle::ParticleSystem::FIXED); mRainParticleSystem->setParticleAlignment(osgParticle::ParticleSystem::FIXED);
@ -1492,6 +1484,12 @@ void SkyManager::createRain()
stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF); stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
stateset->setMode(GL_BLEND, osg::StateAttribute::ON); stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
osg::ref_ptr<osg::Material> 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(); osgParticle::Particle& particleTemplate = mRainParticleSystem->getDefaultParticleTemplate();
particleTemplate.setSizeRange(osgParticle::rangef(5.f, 15.f)); particleTemplate.setSizeRange(osgParticle::rangef(5.f, 15.f));
particleTemplate.setAlphaRange(osgParticle::rangef(1.f, 1.f)); particleTemplate.setAlphaRange(osgParticle::rangef(1.f, 1.f));
@ -1524,6 +1522,7 @@ void SkyManager::createRain()
osg::ref_ptr<osgParticle::ModularProgram> program (new osgParticle::ModularProgram); osg::ref_ptr<osgParticle::ModularProgram> program (new osgParticle::ModularProgram);
program->addOperator(new WrapAroundOperator(mCamera,rainRange)); program->addOperator(new WrapAroundOperator(mCamera,rainRange));
program->addOperator(new WeatherAlphaOperator(mEffectFade, true));
program->setParticleSystem(mRainParticleSystem); program->setParticleSystem(mRainParticleSystem);
mRainNode->addChild(program); mRainNode->addChild(program);
@ -1531,8 +1530,7 @@ void SkyManager::createRain()
mRainNode->addChild(mRainParticleSystem); mRainNode->addChild(mRainParticleSystem);
mRainNode->addChild(updater); mRainNode->addChild(updater);
mRainFader = new RainFader(&mWeatherAlpha); // Note: if we ever switch to regular geometry rain, it'll need to use an AlphaFader.
mRainNode->addUpdateCallback(mRainFader);
mRainNode->addCullCallback(mUnderwaterSwitch); mRainNode->addCullCallback(mUnderwaterSwitch);
mRainNode->setNodeMask(Mask_WeatherParticles); mRainNode->setNodeMask(Mask_WeatherParticles);
@ -1550,7 +1548,6 @@ void SkyManager::destroyRain()
mCounter = nullptr; mCounter = nullptr;
mRainParticleSystem = nullptr; mRainParticleSystem = nullptr;
mRainShooter = nullptr; mRainShooter = nullptr;
mRainFader = nullptr;
} }
SkyManager::~SkyManager() SkyManager::~SkyManager()
@ -1589,17 +1586,18 @@ void SkyManager::update(float duration)
if (!mEnabled) if (!mEnabled)
{ {
if (mRainIntensityUniform) if (mRainIntensityUniform)
mRainIntensityUniform->set((float) 0.0); mRainIntensityUniform->set(0.f);
return; return;
} }
if (mRainIntensityUniform) if (mRainIntensityUniform)
{ {
if (mIsStorm || (!hasRain() && !mParticleNode)) float rainIntensity = 0.f;
mRainIntensityUniform->set((float) 0.0); if (!mIsStorm && (hasRain() || mParticleNode))
else rainIntensity = mEffectFade;
mRainIntensityUniform->set((float) mWeatherAlpha);
mRainIntensityUniform->set(rainIntensity);
} }
switchUnderwaterRain(); switchUnderwaterRain();
@ -1714,7 +1712,6 @@ void SkyManager::setWeather(const WeatherResult& weather)
{ {
mParticleNode->removeChild(mParticleEffect); mParticleNode->removeChild(mParticleEffect);
mParticleEffect = nullptr; mParticleEffect = nullptr;
mParticleFaders.clear();
} }
if (mCurrentParticleEffect.empty()) if (mCurrentParticleEffect.empty())
@ -1740,28 +1737,26 @@ void SkyManager::setWeather(const WeatherResult& weather)
SceneUtil::AssignControllerSourcesVisitor assignVisitor(std::shared_ptr<SceneUtil::ControllerSource>(new SceneUtil::FrameTimeSource)); SceneUtil::AssignControllerSourcesVisitor assignVisitor(std::shared_ptr<SceneUtil::ControllerSource>(new SceneUtil::FrameTimeSource));
mParticleEffect->accept(assignVisitor); mParticleEffect->accept(assignVisitor);
AlphaFader::SetupVisitor alphaFaderSetupVisitor(&mWeatherAlpha); AlphaFader::SetupVisitor alphaFaderSetupVisitor(mEffectFade);
mParticleEffect->accept(alphaFaderSetupVisitor); mParticleEffect->accept(alphaFaderSetupVisitor);
mParticleFaders = alphaFaderSetupVisitor.getAlphaFaders();
SceneUtil::DisableFreezeOnCullVisitor disableFreezeOnCullVisitor; SceneUtil::DisableFreezeOnCullVisitor disableFreezeOnCullVisitor;
mParticleEffect->accept(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) for (unsigned int i = 0; i < findPSVisitor.mFoundNodes.size(); ++i)
{ {
osgParticle::ParticleSystem *ps = static_cast<osgParticle::ParticleSystem *>(findPSVisitor.mFoundNodes[i]); osgParticle::ParticleSystem *ps = static_cast<osgParticle::ParticleSystem *>(findPSVisitor.mFoundNodes[i]);
osg::ref_ptr<osgParticle::ModularProgram> program (new osgParticle::ModularProgram); osg::ref_ptr<osgParticle::ModularProgram> program (new osgParticle::ModularProgram);
if (!mIsStorm)
program->addOperator(new WrapAroundOperator(mCamera,osg::Vec3(1024,1024,800))); program->addOperator(new WrapAroundOperator(mCamera,osg::Vec3(1024,1024,800)));
program->setParticleSystem(ps); program->addOperator(new WeatherAlphaOperator(mEffectFade, false));
mParticleNode->addChild(program); program->setParticleSystem(ps);
} mParticleNode->addChild(program);
} }
} }
} }
@ -1848,11 +1843,7 @@ void SkyManager::setWeather(const WeatherResult& weather)
mAtmosphereNightNode->setNodeMask(weather.mNight ? ~0 : 0); mAtmosphereNightNode->setNodeMask(weather.mNight ? ~0 : 0);
if (mRainFader) mEffectFade = weather.mEffectFade;
mRainFader->setAlpha(weather.mEffectFade * 0.6); // * Rain_Threshold?
for (AlphaFader* fader : mParticleFaders)
fader->setAlpha(weather.mEffectFade);
} }
float SkyManager::getBaseWindSpeed() const float SkyManager::getBaseWindSpeed() const

@ -203,7 +203,6 @@ namespace MWRender
osg::ref_ptr<osg::PositionAttitudeTransform> mParticleNode; osg::ref_ptr<osg::PositionAttitudeTransform> mParticleNode;
osg::ref_ptr<osg::Node> mParticleEffect; osg::ref_ptr<osg::Node> mParticleEffect;
std::vector<osg::ref_ptr<AlphaFader> > mParticleFaders;
osg::ref_ptr<UnderwaterSwitchCallback> mUnderwaterSwitch; osg::ref_ptr<UnderwaterSwitchCallback> mUnderwaterSwitch;
osg::ref_ptr<osg::PositionAttitudeTransform> mCloudNode; osg::ref_ptr<osg::PositionAttitudeTransform> mCloudNode;
@ -230,7 +229,6 @@ namespace MWRender
osg::ref_ptr<osgParticle::BoxPlacer> mPlacer; osg::ref_ptr<osgParticle::BoxPlacer> mPlacer;
osg::ref_ptr<RainCounter> mCounter; osg::ref_ptr<RainCounter> mCounter;
osg::ref_ptr<RainShooter> mRainShooter; osg::ref_ptr<RainShooter> mRainShooter;
osg::ref_ptr<RainFader> mRainFader;
bool mCreated; bool mCreated;
@ -273,7 +271,7 @@ namespace MWRender
bool mEnabled; bool mEnabled;
bool mSunEnabled; bool mSunEnabled;
float mWeatherAlpha; float mEffectFade;
osg::Vec4f mMoonScriptColor; osg::Vec4f mMoonScriptColor;
}; };

Loading…
Cancel
Save