1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-02-21 00:39:58 +00:00

Merge branch 'sort_me_baby_one_more_time' into 'master'

NiSortAdjustNode support (#6600)

Closes #6600

See merge request OpenMW/openmw!1644
This commit is contained in:
psi29a 2022-02-17 10:29:42 +00:00
commit 1b3acc85f7
4 changed files with 91 additions and 12 deletions

View File

@ -133,6 +133,7 @@
Feature #6443: NiStencilProperty is not fully supported
Feature #6534: Shader-based object texture blending
Feature #6592: Missing support for NiTriShape particle emitters
Feature #6600: Support NiSortAdjustNode
Task #6201: Remove the "Note: No relevant classes found. No output generated" warnings
Task #6264: Remove the old classes in animation.cpp
Task #6553: Simplify interpreter instruction registration

View File

@ -31,7 +31,8 @@ using CreateRecord = std::unique_ptr<Record> (*)();
///These are all the record types we know how to read.
static std::map<std::string, CreateRecord> makeFactory()
{
return {
return
{
{"NiNode" , &construct <NiNode , RC_NiNode >},
{"NiSwitchNode" , &construct <NiSwitchNode , RC_NiSwitchNode >},
{"NiLODNode" , &construct <NiLODNode , RC_NiLODNode >},
@ -147,7 +148,7 @@ static std::map<std::string, CreateRecord> makeFactory()
{"bhkRigidBody" , &construct <bhkRigidBody , RC_bhkRigidBody >},
{"bhkRigidBodyT" , &construct <bhkRigidBody , RC_bhkRigidBodyT >},
{"BSLightingShaderProperty" , &construct <BSLightingShaderProperty , RC_BSLightingShaderProperty >},
{"NiSortAdjustNode" , &construct <NiSortAdjustNode , RC_NiNode >},
{"NiSortAdjustNode" , &construct <NiSortAdjustNode , RC_NiSortAdjustNode >},
{"NiClusterAccumulator" , &construct <NiClusterAccumulator , RC_NiClusterAccumulator >},
{"NiAlphaAccumulator" , &construct <NiAlphaAccumulator , RC_NiAlphaAccumulator >},
};

View File

@ -142,7 +142,8 @@ enum RecordType
RC_bhkRigidBodyT,
RC_BSLightingShaderProperty,
RC_NiClusterAccumulator,
RC_NiAlphaAccumulator
RC_NiAlphaAccumulator,
RC_NiSortAdjustNode
};
/// Base class for all records

View File

@ -220,6 +220,9 @@ namespace NifOsg
bool mHasHerbalismLabel = false;
bool mHasStencilProperty = false;
const Nif::NiSortAdjustNode* mPushedSorter = nullptr;
const Nif::NiSortAdjustNode* mLastAppliedNoInheritSorter = nullptr;
// This is used to queue emitters that weren't attached to their node yet.
std::vector<std::pair<size_t, osg::ref_ptr<Emitter>>> mEmitterQueue;
@ -310,10 +313,6 @@ namespace NifOsg
if (mHasHerbalismLabel)
created->getOrCreateUserDataContainer()->addDescription(Constants::HerbalismLabel);
// When dealing with stencil buffer, draw order is especially sensitive. Make sure such objects are drawn with traversal order.
if (mHasStencilProperty)
created->getOrCreateStateSet()->setRenderBinDetails(2, "TraversalOrderBin");
// Attach particle emitters to their nodes which should all be loaded by now.
handleQueuedParticleEmitters(created, nif);
@ -598,6 +597,22 @@ namespace NifOsg
if (nifNode->recType == Nif::RC_NiBSAnimationNode || nifNode->recType == Nif::RC_NiBSParticleNode)
animflags = nifNode->flags;
if (nifNode->recType == Nif::RC_NiSortAdjustNode)
{
auto sortNode = static_cast<const Nif::NiSortAdjustNode*>(nifNode);
if (sortNode->mSubSorter.empty())
{
Log(Debug::Warning) << "Empty accumulator found in '" << nifNode->recName << "' node " << nifNode->recIndex;
}
else
{
if (mPushedSorter && !mPushedSorter->mSubSorter.empty() && mPushedSorter->mMode != Nif::NiSortAdjustNode::SortingMode_Inherit)
mLastAppliedNoInheritSorter = mPushedSorter;
mPushedSorter = sortNode;
}
}
// Hide collision shapes, but don't skip the subgraph
// We still need to animate the hidden bones so the physics system can access them
if (nifNode->recType == Nif::RC_RootCollisionNode)
@ -2000,6 +2015,13 @@ namespace NifOsg
mat->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4f(1,1,1,1));
bool hasMatCtrl = false;
bool hasSortAlpha = false;
osg::StateSet* blendFuncStateSet = nullptr;
auto setBin_Transparent = [] (osg::StateSet* ss) { ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); };
auto setBin_BackToFront = [] (osg::StateSet* ss) { ss->setRenderBinDetails(0, "SORT_BACK_TO_FRONT"); };
auto setBin_Traversal = [] (osg::StateSet* ss) { ss->setRenderBinDetails(2, "TraversalOrderBin"); };
auto setBin_Inherit = [] (osg::StateSet* ss) { ss->setRenderBinToInherit(); };
int lightmode = 1;
float emissiveMult = 1.f;
@ -2077,17 +2099,23 @@ namespace NifOsg
bool noSort = (alphaprop->flags>>13)&1;
if (!noSort)
{
node->getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
node->getOrCreateStateSet()->setNestRenderBins(false);
hasSortAlpha = true;
if (!mPushedSorter)
setBin_Transparent(node->getStateSet());
}
else
node->getOrCreateStateSet()->setRenderBinToInherit();
{
if (!mPushedSorter)
setBin_Inherit(node->getStateSet());
}
}
else if (osg::StateSet* stateset = node->getStateSet())
{
stateset->removeAttribute(osg::StateAttribute::BLENDFUNC);
stateset->removeMode(GL_BLEND);
stateset->setRenderBinToInherit();
blendFuncStateSet = stateset;
if (!mPushedSorter)
blendFuncStateSet->setRenderBinToInherit();
}
if((alphaprop->flags>>9)&1)
@ -2152,7 +2180,10 @@ namespace NifOsg
mat->setColorMode(osg::Material::OFF);
}
if (!hasMatCtrl && mat->getColorMode() == osg::Material::OFF
if (!mPushedSorter && !hasSortAlpha && mHasStencilProperty)
setBin_Traversal(node->getOrCreateStateSet());
if (!mPushedSorter && !hasMatCtrl && mat->getColorMode() == osg::Material::OFF
&& mat->getEmission(osg::Material::FRONT_AND_BACK) == osg::Vec4f(0,0,0,1)
&& mat->getDiffuse(osg::Material::FRONT_AND_BACK) == osg::Vec4f(1,1,1,1)
&& mat->getAmbient(osg::Material::FRONT_AND_BACK) == osg::Vec4f(1,1,1,1)
@ -2171,6 +2202,51 @@ namespace NifOsg
stateset->addUniform(new osg::Uniform("emissiveMult", emissiveMult));
if (specStrength != 1.f)
stateset->addUniform(new osg::Uniform("specStrength", specStrength));
if (!mPushedSorter)
return;
auto assignBin = [&] (int mode, int type) {
if (mode == Nif::NiSortAdjustNode::SortingMode_Off)
{
setBin_Traversal(stateset);
return;
}
if (type == Nif::RC_NiAlphaAccumulator)
{
if (hasSortAlpha)
setBin_BackToFront(stateset);
else
setBin_Traversal(stateset);
}
else if (type == Nif::RC_NiClusterAccumulator)
setBin_BackToFront(stateset);
else
Log(Debug::Error) << "Unrecognized NiAccumulator in " << mFilename;
};
switch (mPushedSorter->mMode)
{
case Nif::NiSortAdjustNode::SortingMode_Inherit:
{
if (mLastAppliedNoInheritSorter)
assignBin(mLastAppliedNoInheritSorter->mMode, mLastAppliedNoInheritSorter->mSubSorter->recType);
else
assignBin(mPushedSorter->mMode, Nif::RC_NiAlphaAccumulator);
break;
}
case Nif::NiSortAdjustNode::SortingMode_Off:
{
setBin_Traversal(stateset);
break;
}
case Nif::NiSortAdjustNode::SortingMode_Subsort:
{
assignBin(mPushedSorter->mMode, mPushedSorter->mSubSorter->recType);
break;
}
}
}
};