remove unecassary visitor for soft particles

This commit is contained in:
Cody Glassman 2025-08-23 09:09:18 -07:00
parent 14d9be7885
commit d72451da62
9 changed files with 93 additions and 104 deletions

View File

@ -512,7 +512,6 @@ namespace MWRender
resourceSystem->getSceneManager()->setOpaqueDepthTex( resourceSystem->getSceneManager()->setOpaqueDepthTex(
mPostProcessor->getTexture(PostProcessor::Tex_OpaqueDepth, 0), mPostProcessor->getTexture(PostProcessor::Tex_OpaqueDepth, 0),
mPostProcessor->getTexture(PostProcessor::Tex_OpaqueDepth, 1)); mPostProcessor->getTexture(PostProcessor::Tex_OpaqueDepth, 1));
resourceSystem->getSceneManager()->setSoftParticles(Settings::shaders().mSoftParticles);
resourceSystem->getSceneManager()->setSupportsNormalsRT(mPostProcessor->getSupportsNormalsRT()); resourceSystem->getSceneManager()->setSupportsNormalsRT(mPostProcessor->getSupportsNormalsRT());
resourceSystem->getSceneManager()->setWeatherParticleOcclusion(Settings::shaders().mWeatherParticleOcclusion); resourceSystem->getSceneManager()->setWeatherParticleOcclusion(Settings::shaders().mWeatherParticleOcclusion);
@ -583,6 +582,7 @@ namespace MWRender
MWBase::Environment::get().getWindowManager()->setCullMask(mask); MWBase::Environment::get().getWindowManager()->setCullMask(mask);
NifOsg::Loader::setHiddenNodeMask(Mask_UpdateVisitor); NifOsg::Loader::setHiddenNodeMask(Mask_UpdateVisitor);
NifOsg::Loader::setIntersectionDisabledNodeMask(Mask_Effect); NifOsg::Loader::setIntersectionDisabledNodeMask(Mask_Effect);
NifOsg::Loader::setSoftEffectEnabled(Settings::shaders().mSoftParticles);
Nif::Reader::setLoadUnsupportedFiles(Settings::models().mLoadUnsupportedNifFiles); Nif::Reader::setLoadUnsupportedFiles(Settings::models().mLoadUnsupportedNifFiles);
mStateUpdater->setFogEnd(mViewDistance); mStateUpdater->setFogEnd(mViewDistance);

View File

@ -3,6 +3,5 @@
namespace Misc namespace Misc
{ {
const std::string OsgUserValues::sFileHash = "fileHash"; const std::string OsgUserValues::sFileHash = "fileHash";
const std::string OsgUserValues::sExtraData = "xData";
const std::string OsgUserValues::sXSoftEffect = "xSoftEffect"; const std::string OsgUserValues::sXSoftEffect = "xSoftEffect";
} }

View File

@ -8,7 +8,6 @@ namespace Misc
struct OsgUserValues struct OsgUserValues
{ {
static const std::string sFileHash; static const std::string sFileHash;
static const std::string sExtraData;
static const std::string sXSoftEffect; static const std::string sXSoftEffect;
}; };
} }

View File

@ -13,6 +13,8 @@
#include <osg/TexMat> #include <osg/TexMat>
#include <osg/ValueObject> #include <osg/ValueObject>
#include <yaml-cpp/yaml.h>
// resource // resource
#include <components/debug/debuglog.hpp> #include <components/debug/debuglog.hpp>
#include <components/misc/constants.hpp> #include <components/misc/constants.hpp>
@ -23,6 +25,7 @@
#include <components/nif/parent.hpp> #include <components/nif/parent.hpp>
#include <components/resource/bgsmfilemanager.hpp> #include <components/resource/bgsmfilemanager.hpp>
#include <components/resource/imagemanager.hpp> #include <components/resource/imagemanager.hpp>
#include <components/serialization/osgyaml.hpp>
// particle // particle
#include <osgParticle/BoxPlacer> #include <osgParticle/BoxPlacer>
@ -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<std::string>();
if (key == "soft_effect" && NifOsg::Loader::getSoftEffectEnabled())
{
SceneUtil::SoftEffectConfig config;
config.mSize = it.second["size"].as<float>(config.mSize);
config.mFalloff = it.second["falloff"].as<bool>(config.mFalloff);
config.mFalloffDepth = it.second["falloffDepth"].as<float>(config.mFalloffDepth);
SceneUtil::setupSoftEffect(*node, config);
}
else if (key == "distortion")
{
SceneUtil::DistortionConfig config;
config.mStrength = it.second["strength"].as<float>(config.mStrength);
SceneUtil::setupDistortion(*node, config);
}
}
}
} }
namespace NifOsg namespace NifOsg
@ -236,6 +266,18 @@ namespace NifOsg
return sIntersectionDisabledNodeMask; return sIntersectionDisabledNodeMask;
} }
bool Loader::sSoftEffectEnabled = false;
void Loader::setSoftEffectEnabled(bool enabled)
{
sSoftEffectEnabled = enabled;
}
bool Loader::getSoftEffectEnabled()
{
return sSoftEffectEnabled;
}
class LoaderImpl class LoaderImpl
{ {
public: public:
@ -649,6 +691,8 @@ namespace NifOsg
// - finding a random child NiNode in NiBspArrayController // - finding a random child NiNode in NiBspArrayController
node->setUserValue("recIndex", nifNode->recIndex); node->setUserValue("recIndex", nifNode->recIndex);
std::string extraData;
for (const auto& e : nifNode->getExtraList()) for (const auto& e : nifNode->getExtraList())
{ {
if (e->recType == Nif::RC_NiTextKeyExtraData && args.mTextKeys) if (e->recType == Nif::RC_NiTextKeyExtraData && args.mTextKeys)
@ -676,8 +720,7 @@ namespace NifOsg
} }
else if (sd->mData.rfind(extraDataIdentifer, 0) == 0) else if (sd->mData.rfind(extraDataIdentifer, 0) == 0)
{ {
node->setUserValue( extraData = sd->mData.substr(extraDataIdentifer.length());
Misc::OsgUserValues::sExtraData, sd->mData.substr(extraDataIdentifer.length()));
} }
} }
else if (e->recType == Nif::RC_BSXFlags) else if (e->recType == Nif::RC_BSXFlags)
@ -751,6 +794,13 @@ namespace NifOsg
applyNodeProperties(nifNode, node, composite, args.mBoundTextures, args.mAnimFlags); 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 isNiGeometry = isTypeNiGeometry(nifNode->recType);
const bool isBSGeometry = isTypeBSGeometry(nifNode->recType); const bool isBSGeometry = isTypeBSGeometry(nifNode->recType);
const bool isGeometry = isNiGeometry || isBSGeometry; 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) if (composite->getNumControllers() > 0)
{ {
osg::Callback* cb = composite; osg::Callback* cb = composite;
@ -1412,6 +1459,12 @@ namespace NifOsg
trans->addChild(toAttach); trans->addChild(toAttach);
parentNode->addChild(trans); 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, void handleNiGeometryData(const Nif::NiAVObject* nifNode, const Nif::Parent* parent, osg::Geometry* geometry,
@ -2313,8 +2366,9 @@ namespace NifOsg
{ {
auto bgem = static_cast<const Bgsm::BGEMFile*>(shaderMat); auto bgem = static_cast<const Bgsm::BGEMFile*>(shaderMat);
mat->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4f(bgem->mEmittanceColor, 1.f)); mat->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4f(bgem->mEmittanceColor, 1.f));
if (bgem->mSoft) if (bgem->mSoft && Loader::getSoftEffectEnabled())
SceneUtil::setupSoftEffect(node, bgem->mSoftDepth, true, bgem->mSoftDepth); SceneUtil::setupSoftEffect(
node, { .mSize = bgem->mSoftDepth, .mFalloffDepth = bgem->mSoftDepth, .mFalloff = true });
} }
} }
@ -2507,7 +2561,7 @@ namespace NifOsg
node->getName(), stateset, boundTextures); node->getName(), stateset, boundTextures);
handleTextureControllers(texprop, composite, stateset, animflags); handleTextureControllers(texprop, composite, stateset, animflags);
if (texprop->refraction()) if (texprop->refraction())
SceneUtil::setupDistortion(*node, texprop->mRefraction.mStrength); SceneUtil::setupDistortion(*node, { .mStrength = texprop->mRefraction.mStrength });
break; break;
} }
case Nif::RC_BSShaderNoLightingProperty: case Nif::RC_BSShaderNoLightingProperty:
@ -2558,7 +2612,7 @@ namespace NifOsg
stateset->addUniform(new osg::Uniform("useTreeAnim", true)); stateset->addUniform(new osg::Uniform("useTreeAnim", true));
handleDepthFlags(stateset, texprop->depthTest(), texprop->depthWrite()); handleDepthFlags(stateset, texprop->depthTest(), texprop->depthWrite());
if (texprop->refraction()) if (texprop->refraction())
SceneUtil::setupDistortion(*node, texprop->mRefractionStrength); SceneUtil::setupDistortion(*node, { .mStrength = texprop->mRefractionStrength });
break; break;
} }
case Nif::RC_BSEffectShaderProperty: case Nif::RC_BSEffectShaderProperty:
@ -2821,9 +2875,13 @@ namespace NifOsg
break; break;
} }
handleDecal(shaderprop->decal(), hasSortAlpha, *node); handleDecal(shaderprop->decal(), hasSortAlpha, *node);
if (shaderprop->softEffect()) if (shaderprop->softEffect() && Loader::getSoftEffectEnabled())
SceneUtil::setupSoftEffect( SceneUtil::setupSoftEffect(*node,
*node, shaderprop->mFalloffDepth, true, shaderprop->mFalloffDepth); {
.mSize = shaderprop->mFalloffDepth,
.mFalloffDepth = shaderprop->mFalloffDepth,
.mFalloff = true,
});
break; break;
} }
default: default:

View File

@ -55,10 +55,14 @@ namespace NifOsg
static void setIntersectionDisabledNodeMask(unsigned int mask); static void setIntersectionDisabledNodeMask(unsigned int mask);
static unsigned int getIntersectionDisabledNodeMask(); static unsigned int getIntersectionDisabledNodeMask();
static void setSoftEffectEnabled(bool enabled);
static bool getSoftEffectEnabled();
private: private:
static unsigned int sHiddenNodeMask; static unsigned int sHiddenNodeMask;
static unsigned int sIntersectionDisabledNodeMask; static unsigned int sIntersectionDisabledNodeMask;
static bool sShowMarkers; static bool sShowMarkers;
static bool sSoftEffectEnabled;
}; };
} }

View File

@ -42,7 +42,6 @@
#include <components/sceneutil/clone.hpp> #include <components/sceneutil/clone.hpp>
#include <components/sceneutil/controller.hpp> #include <components/sceneutil/controller.hpp>
#include <components/sceneutil/depth.hpp> #include <components/sceneutil/depth.hpp>
#include <components/sceneutil/extradata.hpp>
#include <components/sceneutil/lightmanager.hpp> #include <components/sceneutil/lightmanager.hpp>
#include <components/sceneutil/optimizer.hpp> #include <components/sceneutil/optimizer.hpp>
#include <components/sceneutil/riggeometryosgaextension.hpp> #include <components/sceneutil/riggeometryosgaextension.hpp>
@ -1002,9 +1001,6 @@ namespace Resource
try try
{ {
loaded = load(path, mVFS, mImageManager, mNifFileManager, mBgsmFileManager); loaded = load(path, mVFS, mImageManager, mNifFileManager, mBgsmFileManager);
SceneUtil::ProcessExtraDataVisitor extraDataVisitor(this);
loaded->accept(extraDataVisitor);
} }
catch (const std::exception& e) catch (const std::exception& e)
{ {

View File

@ -230,9 +230,6 @@ namespace Resource
void setUpNormalsRTForStateSet(osg::StateSet* stateset, bool enabled); void setUpNormalsRTForStateSet(osg::StateSet* stateset, bool enabled);
void setSoftParticles(bool enabled) { mSoftParticles = enabled; }
bool getSoftParticles() const { return mSoftParticles; }
void setWeatherParticleOcclusion(bool value) { mWeatherParticleOcclusion = value; } void setWeatherParticleOcclusion(bool value) { mWeatherParticleOcclusion = value; }
private: private:
@ -255,7 +252,6 @@ namespace Resource
bool mAdjustCoverageForAlphaTest; bool mAdjustCoverageForAlphaTest;
bool mSupportsNormalsRT; bool mSupportsNormalsRT;
std::array<osg::ref_ptr<osg::Texture>, 2> mOpaqueDepthTex; std::array<osg::ref_ptr<osg::Texture>, 2> mOpaqueDepthTex;
bool mSoftParticles = false;
bool mWeatherParticleOcclusion = false; bool mWeatherParticleOcclusion = false;
osg::ref_ptr<Resource::SharedStateManager> mSharedStateManager; osg::ref_ptr<Resource::SharedStateManager> mSharedStateManager;

View File

@ -1,37 +1,28 @@
#include "extradata.hpp" #include "extradata.hpp"
#include <unordered_set>
#include <osg/Node> #include <osg/Node>
#include <osg/ValueObject>
#include <osgParticle/ParticleSystem>
#include <yaml-cpp/yaml.h>
#include <components/misc/osguservalues.hpp> #include <components/misc/osguservalues.hpp>
#include <components/misc/strings/algorithm.hpp>
#include <components/resource/scenemanager.hpp>
#include <components/sceneutil/depth.hpp> #include <components/sceneutil/depth.hpp>
#include <components/shader/shadermanager.hpp>
namespace SceneUtil 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<SceneUtil::AutoDepth> depth static const osg::ref_ptr<SceneUtil::AutoDepth> depth
= new SceneUtil::AutoDepth(osg::Depth::LEQUAL, 0, 1, false); = new SceneUtil::AutoDepth(osg::Depth::LEQUAL, 0, 1, false);
osg::StateSet* stateset = node.getOrCreateStateSet(); osg::StateSet* stateset = node.getOrCreateStateSet();
stateset->addUniform(new osg::Uniform("particleSize", size)); stateset->addUniform(new osg::Uniform("particleSize", config.mSize));
stateset->addUniform(new osg::Uniform("particleFade", falloff)); stateset->addUniform(new osg::Uniform("particleFade", config.mFalloff));
stateset->addUniform(new osg::Uniform("softFalloffDepth", falloffDepth)); stateset->addUniform(new osg::Uniform("softFalloffDepth", config.mFalloffDepth));
stateset->setAttributeAndModes(depth, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); stateset->setAttributeAndModes(depth, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
node.setUserValue(Misc::OsgUserValues::sXSoftEffect, true); 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<SceneUtil::AutoDepth> depth static const osg::ref_ptr<SceneUtil::AutoDepth> depth
= new SceneUtil::AutoDepth(osg::Depth::ALWAYS, 0, 1, false); = new SceneUtil::AutoDepth(osg::Depth::ALWAYS, 0, 1, false);
@ -40,52 +31,8 @@ namespace SceneUtil
stateset->setNestRenderBins(false); stateset->setNestRenderBins(false);
stateset->setRenderBinDetails(14, "Distortion", osg::StateSet::OVERRIDE_PROTECTED_RENDERBIN_DETAILS); 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); 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<std::string>();
if (key == "soft_effect")
{
auto size = it.second["size"].as<float>(45.f);
auto falloff = it.second["falloff"].as<bool>(false);
auto falloffDepth = it.second["falloffDepth"].as<float>(defaultFalloffDepth);
setupSoftEffect(node, size, falloff, falloffDepth);
}
else if (key == "distortion")
{
auto strength = it.second["strength"].as<float>(0.1f);
setupDistortion(node, strength);
}
}
node.setUserValue(Misc::OsgUserValues::sExtraData, std::string{});
}
else if (osgParticle::ParticleSystem* partsys = dynamic_cast<osgParticle::ParticleSystem*>(&node))
{
setupSoftEffect(
node, partsys->getDefaultParticleTemplate().getSizeRange().maximum, false, defaultFalloffDepth);
}
traverse(node);
}
} }

View File

@ -1,13 +1,6 @@
#ifndef OPENMW_COMPONENTS_RESOURCE_EXTRADATA_H #ifndef OPENMW_COMPONENTS_RESOURCE_EXTRADATA_H
#define OPENMW_COMPONENTS_RESOURCE_EXTRADATA_H #define OPENMW_COMPONENTS_RESOURCE_EXTRADATA_H
#include <osg/NodeVisitor>
namespace Resource
{
class SceneManager;
}
namespace osg namespace osg
{ {
class Node; class Node;
@ -15,23 +8,20 @@ namespace osg
namespace SceneUtil namespace SceneUtil
{ {
void setupSoftEffect(osg::Node& node, float size, bool falloff, float falloffDepth); struct SoftEffectConfig
void setupDistortion(osg::Node& node, float distortionStrength);
class ProcessExtraDataVisitor : public osg::NodeVisitor
{ {
public: float mSize = 45.f;
ProcessExtraDataVisitor(Resource::SceneManager* sceneMgr) float mFalloffDepth = 300.f;
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) bool mFalloff = false;
, mSceneMgr(sceneMgr)
{
}
void apply(osg::Node& node) override;
private:
Resource::SceneManager* mSceneMgr;
}; };
struct DistortionConfig
{
float mStrength = 0.1f;
};
void setupSoftEffect(osg::Node& node, const SoftEffectConfig& config);
void setupDistortion(osg::Node& node, const DistortionConfig& config);
} }
#endif #endif