diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 0698e8c4ae..67d1cfb587 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -512,7 +512,6 @@ namespace MWRender resourceSystem->getSceneManager()->setOpaqueDepthTex( mPostProcessor->getTexture(PostProcessor::Tex_OpaqueDepth, 0), mPostProcessor->getTexture(PostProcessor::Tex_OpaqueDepth, 1)); - resourceSystem->getSceneManager()->setSoftParticles(Settings::shaders().mSoftParticles); resourceSystem->getSceneManager()->setSupportsNormalsRT(mPostProcessor->getSupportsNormalsRT()); resourceSystem->getSceneManager()->setWeatherParticleOcclusion(Settings::shaders().mWeatherParticleOcclusion); @@ -583,6 +582,7 @@ namespace MWRender MWBase::Environment::get().getWindowManager()->setCullMask(mask); NifOsg::Loader::setHiddenNodeMask(Mask_UpdateVisitor); NifOsg::Loader::setIntersectionDisabledNodeMask(Mask_Effect); + NifOsg::Loader::setSoftEffectEnabled(Settings::shaders().mSoftParticles); Nif::Reader::setLoadUnsupportedFiles(Settings::models().mLoadUnsupportedNifFiles); mStateUpdater->setFogEnd(mViewDistance); diff --git a/components/misc/osguservalues.cpp b/components/misc/osguservalues.cpp index b70647a63e..706b5dc2df 100644 --- a/components/misc/osguservalues.cpp +++ b/components/misc/osguservalues.cpp @@ -3,6 +3,5 @@ namespace Misc { const std::string OsgUserValues::sFileHash = "fileHash"; - const std::string OsgUserValues::sExtraData = "xData"; const std::string OsgUserValues::sXSoftEffect = "xSoftEffect"; } diff --git a/components/misc/osguservalues.hpp b/components/misc/osguservalues.hpp index 443e6132e1..54d0e52043 100644 --- a/components/misc/osguservalues.hpp +++ b/components/misc/osguservalues.hpp @@ -8,7 +8,6 @@ namespace Misc struct OsgUserValues { static const std::string sFileHash; - static const std::string sExtraData; static const std::string sXSoftEffect; }; } diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index f3b85ec2fd..f8c76aab15 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -13,6 +13,8 @@ #include #include +#include + // resource #include #include @@ -23,6 +25,7 @@ #include #include #include +#include // particle #include @@ -197,6 +200,33 @@ namespace } } } + + void handleExtraData(const std::string& data, osg::Group* node) + { + YAML::Node root = YAML::Load(data); + + for (const auto& it : root["shader"]) + { + std::string key = it.first.as(); + + if (key == "soft_effect" && NifOsg::Loader::getSoftEffectEnabled()) + { + SceneUtil::SoftEffectConfig config; + config.mSize = it.second["size"].as(config.mSize); + config.mFalloff = it.second["falloff"].as(config.mFalloff); + config.mFalloffDepth = it.second["falloffDepth"].as(config.mFalloffDepth); + + SceneUtil::setupSoftEffect(*node, config); + } + else if (key == "distortion") + { + SceneUtil::DistortionConfig config; + config.mStrength = it.second["strength"].as(config.mStrength); + + SceneUtil::setupDistortion(*node, config); + } + } + } } namespace NifOsg @@ -236,6 +266,18 @@ namespace NifOsg return sIntersectionDisabledNodeMask; } + bool Loader::sSoftEffectEnabled = false; + + void Loader::setSoftEffectEnabled(bool enabled) + { + sSoftEffectEnabled = enabled; + } + + bool Loader::getSoftEffectEnabled() + { + return sSoftEffectEnabled; + } + class LoaderImpl { public: @@ -649,6 +691,8 @@ namespace NifOsg // - finding a random child NiNode in NiBspArrayController node->setUserValue("recIndex", nifNode->recIndex); + std::string extraData; + for (const auto& e : nifNode->getExtraList()) { if (e->recType == Nif::RC_NiTextKeyExtraData && args.mTextKeys) @@ -676,8 +720,7 @@ namespace NifOsg } else if (sd->mData.rfind(extraDataIdentifer, 0) == 0) { - node->setUserValue( - Misc::OsgUserValues::sExtraData, sd->mData.substr(extraDataIdentifer.length())); + extraData = sd->mData.substr(extraDataIdentifer.length()); } } else if (e->recType == Nif::RC_BSXFlags) @@ -751,6 +794,13 @@ namespace NifOsg applyNodeProperties(nifNode, node, composite, args.mBoundTextures, args.mAnimFlags); + if (nifNode->recType == Nif::RC_NiParticles) + handleParticleSystem(nifNode, parent, node, composite, args.mAnimFlags); + + // Apply any extra effects after processing the nodes children and particle system handling + if (!extraData.empty()) + handleExtraData(extraData, node); + const bool isNiGeometry = isTypeNiGeometry(nifNode->recType); const bool isBSGeometry = isTypeBSGeometry(nifNode->recType); const bool isGeometry = isNiGeometry || isBSGeometry; @@ -782,9 +832,6 @@ namespace NifOsg } } - if (nifNode->recType == Nif::RC_NiParticles) - handleParticleSystem(nifNode, parent, node, composite, args.mAnimFlags); - if (composite->getNumControllers() > 0) { osg::Callback* cb = composite; @@ -1412,6 +1459,12 @@ namespace NifOsg trans->addChild(toAttach); parentNode->addChild(trans); } + + if (Loader::getSoftEffectEnabled()) + SceneUtil::setupSoftEffect(*partsys, + { + .mSize = partsys->getDefaultParticleTemplate().getSizeRange().maximum, + }); } void handleNiGeometryData(const Nif::NiAVObject* nifNode, const Nif::Parent* parent, osg::Geometry* geometry, @@ -2313,8 +2366,9 @@ namespace NifOsg { auto bgem = static_cast(shaderMat); mat->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4f(bgem->mEmittanceColor, 1.f)); - if (bgem->mSoft) - SceneUtil::setupSoftEffect(node, bgem->mSoftDepth, true, bgem->mSoftDepth); + if (bgem->mSoft && Loader::getSoftEffectEnabled()) + SceneUtil::setupSoftEffect( + node, { .mSize = bgem->mSoftDepth, .mFalloffDepth = bgem->mSoftDepth, .mFalloff = true }); } } @@ -2507,7 +2561,7 @@ namespace NifOsg node->getName(), stateset, boundTextures); handleTextureControllers(texprop, composite, stateset, animflags); if (texprop->refraction()) - SceneUtil::setupDistortion(*node, texprop->mRefraction.mStrength); + SceneUtil::setupDistortion(*node, { .mStrength = texprop->mRefraction.mStrength }); break; } case Nif::RC_BSShaderNoLightingProperty: @@ -2558,7 +2612,7 @@ namespace NifOsg stateset->addUniform(new osg::Uniform("useTreeAnim", true)); handleDepthFlags(stateset, texprop->depthTest(), texprop->depthWrite()); if (texprop->refraction()) - SceneUtil::setupDistortion(*node, texprop->mRefractionStrength); + SceneUtil::setupDistortion(*node, { .mStrength = texprop->mRefractionStrength }); break; } case Nif::RC_BSEffectShaderProperty: @@ -2821,9 +2875,13 @@ namespace NifOsg break; } handleDecal(shaderprop->decal(), hasSortAlpha, *node); - if (shaderprop->softEffect()) - SceneUtil::setupSoftEffect( - *node, shaderprop->mFalloffDepth, true, shaderprop->mFalloffDepth); + if (shaderprop->softEffect() && Loader::getSoftEffectEnabled()) + SceneUtil::setupSoftEffect(*node, + { + .mSize = shaderprop->mFalloffDepth, + .mFalloffDepth = shaderprop->mFalloffDepth, + .mFalloff = true, + }); break; } default: diff --git a/components/nifosg/nifloader.hpp b/components/nifosg/nifloader.hpp index 14f16088cc..3a06e71e5b 100644 --- a/components/nifosg/nifloader.hpp +++ b/components/nifosg/nifloader.hpp @@ -55,10 +55,14 @@ namespace NifOsg static void setIntersectionDisabledNodeMask(unsigned int mask); static unsigned int getIntersectionDisabledNodeMask(); + static void setSoftEffectEnabled(bool enabled); + static bool getSoftEffectEnabled(); + private: static unsigned int sHiddenNodeMask; static unsigned int sIntersectionDisabledNodeMask; static bool sShowMarkers; + static bool sSoftEffectEnabled; }; } diff --git a/components/resource/scenemanager.cpp b/components/resource/scenemanager.cpp index 6100d0ccaa..e7edfc1630 100644 --- a/components/resource/scenemanager.cpp +++ b/components/resource/scenemanager.cpp @@ -42,7 +42,6 @@ #include #include #include -#include #include #include #include @@ -1002,9 +1001,6 @@ namespace Resource try { loaded = load(path, mVFS, mImageManager, mNifFileManager, mBgsmFileManager); - - SceneUtil::ProcessExtraDataVisitor extraDataVisitor(this); - loaded->accept(extraDataVisitor); } catch (const std::exception& e) { diff --git a/components/resource/scenemanager.hpp b/components/resource/scenemanager.hpp index 8141b5308f..370383975d 100644 --- a/components/resource/scenemanager.hpp +++ b/components/resource/scenemanager.hpp @@ -230,9 +230,6 @@ namespace Resource void setUpNormalsRTForStateSet(osg::StateSet* stateset, bool enabled); - void setSoftParticles(bool enabled) { mSoftParticles = enabled; } - bool getSoftParticles() const { return mSoftParticles; } - void setWeatherParticleOcclusion(bool value) { mWeatherParticleOcclusion = value; } private: @@ -255,7 +252,6 @@ namespace Resource bool mAdjustCoverageForAlphaTest; bool mSupportsNormalsRT; std::array, 2> mOpaqueDepthTex; - bool mSoftParticles = false; bool mWeatherParticleOcclusion = false; osg::ref_ptr mSharedStateManager; diff --git a/components/sceneutil/extradata.cpp b/components/sceneutil/extradata.cpp index 2d00980565..7455992dbb 100644 --- a/components/sceneutil/extradata.cpp +++ b/components/sceneutil/extradata.cpp @@ -1,37 +1,28 @@ #include "extradata.hpp" -#include - #include -#include -#include - -#include #include -#include -#include #include -#include namespace SceneUtil { - void setupSoftEffect(osg::Node& node, float size, bool falloff, float falloffDepth) + void setupSoftEffect(osg::Node& node, const SoftEffectConfig& config) { static const osg::ref_ptr depth = new SceneUtil::AutoDepth(osg::Depth::LEQUAL, 0, 1, false); osg::StateSet* stateset = node.getOrCreateStateSet(); - stateset->addUniform(new osg::Uniform("particleSize", size)); - stateset->addUniform(new osg::Uniform("particleFade", falloff)); - stateset->addUniform(new osg::Uniform("softFalloffDepth", falloffDepth)); + stateset->addUniform(new osg::Uniform("particleSize", config.mSize)); + stateset->addUniform(new osg::Uniform("particleFade", config.mFalloff)); + stateset->addUniform(new osg::Uniform("softFalloffDepth", config.mFalloffDepth)); stateset->setAttributeAndModes(depth, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); node.setUserValue(Misc::OsgUserValues::sXSoftEffect, true); } - void setupDistortion(osg::Node& node, float distortionStrength) + void setupDistortion(osg::Node& node, const DistortionConfig& config) { static const osg::ref_ptr depth = new SceneUtil::AutoDepth(osg::Depth::ALWAYS, 0, 1, false); @@ -40,52 +31,8 @@ namespace SceneUtil stateset->setNestRenderBins(false); stateset->setRenderBinDetails(14, "Distortion", osg::StateSet::OVERRIDE_PROTECTED_RENDERBIN_DETAILS); - stateset->addUniform(new osg::Uniform("distortionStrength", distortionStrength)); + stateset->addUniform(new osg::Uniform("distortionStrength", config.mStrength)); stateset->setAttributeAndModes(depth, osg::StateAttribute::ON); } - - void ProcessExtraDataVisitor::apply(osg::Node& node) - { - if (!mSceneMgr->getSoftParticles()) - return; - - std::string source; - - constexpr float defaultFalloffDepth = 300.f; // arbitrary value that simply looks good with common cases - - if (node.getUserValue(Misc::OsgUserValues::sExtraData, source) && !source.empty()) - { - YAML::Node root = YAML::Load(source); - - for (const auto& it : root["shader"]) - { - std::string key = it.first.as(); - - if (key == "soft_effect") - { - auto size = it.second["size"].as(45.f); - auto falloff = it.second["falloff"].as(false); - auto falloffDepth = it.second["falloffDepth"].as(defaultFalloffDepth); - - setupSoftEffect(node, size, falloff, falloffDepth); - } - else if (key == "distortion") - { - auto strength = it.second["strength"].as(0.1f); - - setupDistortion(node, strength); - } - } - - node.setUserValue(Misc::OsgUserValues::sExtraData, std::string{}); - } - else if (osgParticle::ParticleSystem* partsys = dynamic_cast(&node)) - { - setupSoftEffect( - node, partsys->getDefaultParticleTemplate().getSizeRange().maximum, false, defaultFalloffDepth); - } - - traverse(node); - } } diff --git a/components/sceneutil/extradata.hpp b/components/sceneutil/extradata.hpp index 7054ac91b3..b3c6388c78 100644 --- a/components/sceneutil/extradata.hpp +++ b/components/sceneutil/extradata.hpp @@ -1,13 +1,6 @@ #ifndef OPENMW_COMPONENTS_RESOURCE_EXTRADATA_H #define OPENMW_COMPONENTS_RESOURCE_EXTRADATA_H -#include - -namespace Resource -{ - class SceneManager; -} - namespace osg { class Node; @@ -15,23 +8,20 @@ namespace osg namespace SceneUtil { - void setupSoftEffect(osg::Node& node, float size, bool falloff, float falloffDepth); - void setupDistortion(osg::Node& node, float distortionStrength); - - class ProcessExtraDataVisitor : public osg::NodeVisitor + struct SoftEffectConfig { - public: - ProcessExtraDataVisitor(Resource::SceneManager* sceneMgr) - : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) - , mSceneMgr(sceneMgr) - { - } - - void apply(osg::Node& node) override; - - private: - Resource::SceneManager* mSceneMgr; + float mSize = 45.f; + float mFalloffDepth = 300.f; + bool mFalloff = false; }; + + struct DistortionConfig + { + float mStrength = 0.1f; + }; + + void setupSoftEffect(osg::Node& node, const SoftEffectConfig& config); + void setupDistortion(osg::Node& node, const DistortionConfig& config); } #endif