mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-04-09 21:44:54 +00:00
Merge branch 'weatheralpha' into 'master'
Fix weather particle fading Closes #5455 See merge request OpenMW/openmw!506
This commit is contained in:
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…
x
Reference in New Issue
Block a user