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.
openmw-37
scrawl 9 years ago
parent 93565eccbf
commit 2ee6b41887

@ -57,8 +57,8 @@ namespace
} }
} }
// Collect all properties affecting the given node that should be applied to an osg::Material. // Collect all properties affecting the given drawable that should be handled on drawable basis rather than on the node hierarchy above it.
void collectMaterialProperties(const Nif::Node* nifNode, std::vector<const Nif::Property*>& out) void collectDrawableProperties(const Nif::Node* nifNode, std::vector<const Nif::Property*>& out)
{ {
const Nif::PropertyList& props = nifNode->props; const Nif::PropertyList& props = nifNode->props;
for (size_t i = 0; i <props.length();++i) for (size_t i = 0; i <props.length();++i)
@ -70,6 +70,7 @@ namespace
case Nif::RC_NiMaterialProperty: case Nif::RC_NiMaterialProperty:
case Nif::RC_NiVertexColorProperty: case Nif::RC_NiVertexColorProperty:
case Nif::RC_NiSpecularProperty: case Nif::RC_NiSpecularProperty:
case Nif::RC_NiAlphaProperty:
out.push_back(props[i].getPtr()); out.push_back(props[i].getPtr());
break; break;
default: default:
@ -78,7 +79,7 @@ namespace
} }
} }
if (nifNode->parent) if (nifNode->parent)
collectMaterialProperties(nifNode->parent, out); collectDrawableProperties(nifNode->parent, out);
} }
class FrameSwitch : public osg::Group class FrameSwitch : public osg::Group
@ -872,9 +873,9 @@ namespace NifOsg
osg::ref_ptr<osg::Geode> geode (new osg::Geode); osg::ref_ptr<osg::Geode> geode (new osg::Geode);
geode->addDrawable(partsys); geode->addDrawable(partsys);
std::vector<const Nif::Property*> materialProps; std::vector<const Nif::Property*> drawableProps;
collectMaterialProperties(nifNode, materialProps); collectDrawableProperties(nifNode, drawableProps);
applyMaterialProperties(parentNode, materialProps, composite, true, animflags); applyDrawableProperties(parentNode, drawableProps, composite, true, animflags);
// Particles don't have normals, so can't be diffuse lit. // Particles don't have normals, so can't be diffuse lit.
osg::Material* mat = static_cast<osg::Material*>(parentNode->getStateSet()->getAttribute(osg::StateAttribute::MATERIAL)); osg::Material* mat = static_cast<osg::Material*>(parentNode->getStateSet()->getAttribute(osg::StateAttribute::MATERIAL));
@ -934,9 +935,9 @@ namespace NifOsg
// - if there are no vertex colors, we need to disable colorMode. // - 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 // - there are 3 "overlapping" nif properties that all affect the osg::Material, handling them
// above the actual renderable would be tedious. // above the actual renderable would be tedious.
std::vector<const Nif::Property*> materialProps; std::vector<const Nif::Property*> drawableProps;
collectMaterialProperties(triShape, materialProps); collectDrawableProperties(triShape, drawableProps);
applyMaterialProperties(parentNode, materialProps, composite, !data->colors->empty(), animflags); applyDrawableProperties(parentNode, drawableProps, composite, !data->colors->empty(), animflags);
} }
void handleTriShape(const Nif::NiTriShape* triShape, osg::Group* parentNode, SceneUtil::CompositeStateSetUpdater* composite, const std::vector<int>& boundTextures, int animflags) void handleTriShape(const Nif::NiTriShape* triShape, osg::Group* parentNode, SceneUtil::CompositeStateSetUpdater* composite, const std::vector<int>& boundTextures, int animflags)
@ -1223,42 +1224,12 @@ namespace NifOsg
case Nif::RC_NiVertexColorProperty: case Nif::RC_NiVertexColorProperty:
case Nif::RC_NiSpecularProperty: 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; break;
} }
case Nif::RC_NiAlphaProperty: case Nif::RC_NiAlphaProperty:
{ {
const Nif::NiAlphaProperty* alphaprop = static_cast<const Nif::NiAlphaProperty*>(property); // Handled on drawable level to prevent RenderBin nesting issues
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);
break; break;
} }
case Nif::RC_NiTexturingProperty: case Nif::RC_NiTexturingProperty:
@ -1388,7 +1359,7 @@ namespace NifOsg
} }
} }
void applyMaterialProperties(osg::Node* node, const std::vector<const Nif::Property*>& properties, SceneUtil::CompositeStateSetUpdater* composite, void applyDrawableProperties(osg::Node* node, const std::vector<const Nif::Property*>& properties, SceneUtil::CompositeStateSetUpdater* composite,
bool hasVertexColors, int animflags) bool hasVertexColors, int animflags)
{ {
osg::StateSet* stateset = node->getOrCreateStateSet(); osg::StateSet* stateset = node->getOrCreateStateSet();
@ -1444,6 +1415,43 @@ namespace NifOsg
mat->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE); mat->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
break; break;
} }
break;
}
case Nif::RC_NiAlphaProperty:
{
const Nif::NiAlphaProperty* alphaprop = static_cast<const Nif::NiAlphaProperty*>(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;
} }
} }
} }

Loading…
Cancel
Save