diff --git a/CHANGELOG.md b/CHANGELOG.md index df3cff951..24f5d7f76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -84,6 +84,7 @@ Bug #4989: Object dimension-dependent VFX scaling behavior is inconsistent Bug #4990: Dead bodies prevent you from hitting Bug #4999: Drop instruction behaves differently from vanilla + Bug #5001: Possible data race in the Animation::setAlpha() Bug #5004: Werewolves shield their eyes during storm Feature #1774: Handle AvoidNode Feature #2229: Improve pathfinding AI diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 2de39aee4..e341778ac 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -479,6 +479,46 @@ namespace namespace MWRender { + class TransparencyUpdater : public SceneUtil::StateSetUpdater + { + public: + TransparencyUpdater(const float alpha) + : mAlpha(alpha) + { + } + + void setAlpha(const float alpha) + { + mAlpha = alpha; + } + + protected: + virtual void setDefaults(osg::StateSet* stateset) + { + osg::Material* material = static_cast(stateset->getAttribute(osg::StateAttribute::MATERIAL)); + + osg::BlendFunc* blendfunc (new osg::BlendFunc); + stateset->setAttributeAndModes(blendfunc, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE); + + // FIXME: overriding diffuse/ambient/emissive colors + material = new osg::Material; + material->setColorMode(osg::Material::OFF); + material->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(1,1,1,mAlpha)); + material->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4f(1,1,1,1)); + stateset->setAttributeAndModes(material, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE); + stateset->addUniform(new osg::Uniform("colorMode", 0), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE); + } + + virtual void apply(osg::StateSet* stateset, osg::NodeVisitor* /*nv*/) + { + osg::Material* material = static_cast(stateset->getAttribute(osg::StateAttribute::MATERIAL)); + material->setAlpha(osg::Material::FRONT_AND_BACK, mAlpha); + } + + private: + float mAlpha; + }; + class GlowUpdater : public SceneUtil::StateSetUpdater { public: @@ -1791,32 +1831,21 @@ namespace MWRender return; mAlpha = alpha; + // TODO: we use it to fade actors away too, but it would be nice to have a dithering shader instead. if (alpha != 1.f) { - // If we have an existing material for alpha transparency, just override alpha level - osg::StateSet* stateset = mObjectRoot->getOrCreateStateSet(); - osg::Material* material = static_cast(stateset->getAttribute(osg::StateAttribute::MATERIAL)); - if (material) + if (mTransparencyUpdater == nullptr) { - material->setAlpha(osg::Material::FRONT_AND_BACK, alpha); + mTransparencyUpdater = new TransparencyUpdater(alpha); + mObjectRoot->addUpdateCallback(mTransparencyUpdater); } else - { - osg::BlendFunc* blendfunc (new osg::BlendFunc); - stateset->setAttributeAndModes(blendfunc, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE); - - // FIXME: overriding diffuse/ambient/emissive colors - material = new osg::Material; - material->setColorMode(osg::Material::OFF); - material->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(1,1,1,alpha)); - material->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4f(1,1,1,1)); - stateset->setAttributeAndModes(material, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE); - stateset->addUniform(new osg::Uniform("colorMode", 0), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE); - mObjectRoot->setStateSet(stateset); - } + mTransparencyUpdater->setAlpha(alpha); } else { + mObjectRoot->removeUpdateCallback(mTransparencyUpdater); + mTransparencyUpdater = nullptr; mObjectRoot->setStateSet(nullptr); } diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index ab5dc8192..95007d888 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -35,6 +35,7 @@ namespace MWRender class ResetAccumRootCallback; class RotateController; class GlowUpdater; +class TransparencyUpdater; class EffectAnimationTime : public SceneUtil::ControllerSource { @@ -266,6 +267,7 @@ protected: osg::ref_ptr mGlowLight; osg::ref_ptr mGlowUpdater; + osg::ref_ptr mTransparencyUpdater; float mAlpha;