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(
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);

View File

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

View File

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

View File

@ -13,6 +13,8 @@
#include <osg/TexMat>
#include <osg/ValueObject>
#include <yaml-cpp/yaml.h>
// resource
#include <components/debug/debuglog.hpp>
#include <components/misc/constants.hpp>
@ -23,6 +25,7 @@
#include <components/nif/parent.hpp>
#include <components/resource/bgsmfilemanager.hpp>
#include <components/resource/imagemanager.hpp>
#include <components/serialization/osgyaml.hpp>
// particle
#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
@ -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<const Bgsm::BGEMFile*>(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:

View File

@ -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;
};
}

View File

@ -42,7 +42,6 @@
#include <components/sceneutil/clone.hpp>
#include <components/sceneutil/controller.hpp>
#include <components/sceneutil/depth.hpp>
#include <components/sceneutil/extradata.hpp>
#include <components/sceneutil/lightmanager.hpp>
#include <components/sceneutil/optimizer.hpp>
#include <components/sceneutil/riggeometryosgaextension.hpp>
@ -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)
{

View File

@ -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<osg::ref_ptr<osg::Texture>, 2> mOpaqueDepthTex;
bool mSoftParticles = false;
bool mWeatherParticleOcclusion = false;
osg::ref_ptr<Resource::SharedStateManager> mSharedStateManager;

View File

@ -1,37 +1,28 @@
#include "extradata.hpp"
#include <unordered_set>
#include <osg/Node>
#include <osg/ValueObject>
#include <osgParticle/ParticleSystem>
#include <yaml-cpp/yaml.h>
#include <components/misc/osguservalues.hpp>
#include <components/misc/strings/algorithm.hpp>
#include <components/resource/scenemanager.hpp>
#include <components/sceneutil/depth.hpp>
#include <components/shader/shadermanager.hpp>
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
= 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<SceneUtil::AutoDepth> 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<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
#define OPENMW_COMPONENTS_RESOURCE_EXTRADATA_H
#include <osg/NodeVisitor>
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