From 2ee6b41887b8dff5231f9925c6a0205a75d67159 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 19 Oct 2015 15:46:53 +0200 Subject: [PATCH] Handle NiAlphaProperty on a drawable basis Removes the RenderBin nesting complication. Also results in leaner StateSets, so the cull phase should be a bit faster. --- components/nifosg/nifloader.cpp | 92 ++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 42 deletions(-) diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 75a427c5a..2b73f779f 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -57,8 +57,8 @@ namespace } } - // Collect all properties affecting the given node that should be applied to an osg::Material. - void collectMaterialProperties(const Nif::Node* nifNode, std::vector& out) + // Collect all properties affecting the given drawable that should be handled on drawable basis rather than on the node hierarchy above it. + void collectDrawableProperties(const Nif::Node* nifNode, std::vector& out) { const Nif::PropertyList& props = nifNode->props; for (size_t i = 0; i parent) - collectMaterialProperties(nifNode->parent, out); + collectDrawableProperties(nifNode->parent, out); } class FrameSwitch : public osg::Group @@ -872,9 +873,9 @@ namespace NifOsg osg::ref_ptr geode (new osg::Geode); geode->addDrawable(partsys); - std::vector materialProps; - collectMaterialProperties(nifNode, materialProps); - applyMaterialProperties(parentNode, materialProps, composite, true, animflags); + std::vector drawableProps; + collectDrawableProperties(nifNode, drawableProps); + applyDrawableProperties(parentNode, drawableProps, composite, true, animflags); // Particles don't have normals, so can't be diffuse lit. osg::Material* mat = static_cast(parentNode->getStateSet()->getAttribute(osg::StateAttribute::MATERIAL)); @@ -934,9 +935,9 @@ namespace NifOsg // - if there are no vertex colors, we need to disable colorMode. // - there are 3 "overlapping" nif properties that all affect the osg::Material, handling them // above the actual renderable would be tedious. - std::vector materialProps; - collectMaterialProperties(triShape, materialProps); - applyMaterialProperties(parentNode, materialProps, composite, !data->colors->empty(), animflags); + std::vector drawableProps; + collectDrawableProperties(triShape, drawableProps); + applyDrawableProperties(parentNode, drawableProps, composite, !data->colors->empty(), animflags); } void handleTriShape(const Nif::NiTriShape* triShape, osg::Group* parentNode, SceneUtil::CompositeStateSetUpdater* composite, const std::vector& boundTextures, int animflags) @@ -1223,42 +1224,12 @@ namespace NifOsg case Nif::RC_NiVertexColorProperty: case Nif::RC_NiSpecularProperty: { - // Handled in handleTriShape so we know whether vertex colors are available + // Handled on drawable level so we know whether vertex colors are available break; } case Nif::RC_NiAlphaProperty: { - const Nif::NiAlphaProperty* alphaprop = static_cast(property); - osg::BlendFunc* blendfunc = new osg::BlendFunc; - osg::StateSet* stateset = node->getOrCreateStateSet(); - if (alphaprop->flags&1) - { - blendfunc->setFunction(getBlendMode((alphaprop->flags>>1)&0xf), - getBlendMode((alphaprop->flags>>5)&0xf)); - stateset->setAttributeAndModes(blendfunc, osg::StateAttribute::ON); - - bool noSort = (alphaprop->flags>>13)&1; - if (!noSort) - { - stateset->setNestRenderBins(false); - stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); - } - } - else - { - stateset->setAttributeAndModes(blendfunc, osg::StateAttribute::OFF); - stateset->setNestRenderBins(false); - stateset->setRenderingHint(osg::StateSet::OPAQUE_BIN); - } - - osg::AlphaFunc* alphafunc = new osg::AlphaFunc; - if((alphaprop->flags>>9)&1) - { - alphafunc->setFunction(getTestMode((alphaprop->flags>>10)&0x7), alphaprop->data.threshold/255.f); - stateset->setAttributeAndModes(alphafunc, osg::StateAttribute::ON); - } - else - stateset->setAttributeAndModes(alphafunc, osg::StateAttribute::OFF); + // Handled on drawable level to prevent RenderBin nesting issues break; } case Nif::RC_NiTexturingProperty: @@ -1388,7 +1359,7 @@ namespace NifOsg } } - void applyMaterialProperties(osg::Node* node, const std::vector& properties, SceneUtil::CompositeStateSetUpdater* composite, + void applyDrawableProperties(osg::Node* node, const std::vector& properties, SceneUtil::CompositeStateSetUpdater* composite, bool hasVertexColors, int animflags) { osg::StateSet* stateset = node->getOrCreateStateSet(); @@ -1444,6 +1415,43 @@ namespace NifOsg mat->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE); break; } + break; + } + case Nif::RC_NiAlphaProperty: + { + const Nif::NiAlphaProperty* alphaprop = static_cast(property); + osg::BlendFunc* blendfunc = new osg::BlendFunc; + if (alphaprop->flags&1) + { + blendfunc->setFunction(getBlendMode((alphaprop->flags>>1)&0xf), + getBlendMode((alphaprop->flags>>5)&0xf)); + stateset->setAttributeAndModes(blendfunc, osg::StateAttribute::ON); + + bool noSort = (alphaprop->flags>>13)&1; + if (!noSort) + stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); + else + stateset->setRenderBinToInherit(); + } + else + { + stateset->removeAttribute(osg::StateAttribute::BLENDFUNC); + stateset->removeMode(GL_BLEND); + stateset->setRenderBinToInherit(); + } + + osg::AlphaFunc* alphafunc = new osg::AlphaFunc; + if((alphaprop->flags>>9)&1) + { + alphafunc->setFunction(getTestMode((alphaprop->flags>>10)&0x7), alphaprop->data.threshold/255.f); + stateset->setAttributeAndModes(alphafunc, osg::StateAttribute::ON); + } + else + { + stateset->removeAttribute(osg::StateAttribute::ALPHAFUNC); + stateset->removeMode(GL_ALPHA_TEST); + } + break; } } }