mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-10 21:40:15 +00:00
Add sharing for more State Attributes, most notably BlendFunc and AlphaFunc, to improve the state tracking in osg::State and reduce the number of GL calls
This commit is contained in:
parent
960d4a96c3
commit
9180089a3b
@ -1551,7 +1551,7 @@ namespace NifOsg
|
|||||||
case Nif::RC_NiStencilProperty:
|
case Nif::RC_NiStencilProperty:
|
||||||
{
|
{
|
||||||
const Nif::NiStencilProperty* stencilprop = static_cast<const Nif::NiStencilProperty*>(property);
|
const Nif::NiStencilProperty* stencilprop = static_cast<const Nif::NiStencilProperty*>(property);
|
||||||
osg::FrontFace* frontFace = new osg::FrontFace;
|
osg::ref_ptr<osg::FrontFace> frontFace = new osg::FrontFace;
|
||||||
switch (stencilprop->data.drawMode)
|
switch (stencilprop->data.drawMode)
|
||||||
{
|
{
|
||||||
case 2:
|
case 2:
|
||||||
@ -1563,6 +1563,7 @@ namespace NifOsg
|
|||||||
frontFace->setMode(osg::FrontFace::COUNTER_CLOCKWISE);
|
frontFace->setMode(osg::FrontFace::COUNTER_CLOCKWISE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
frontFace = shareAttribute(frontFace);
|
||||||
|
|
||||||
osg::StateSet* stateset = node->getOrCreateStateSet();
|
osg::StateSet* stateset = node->getOrCreateStateSet();
|
||||||
stateset->setAttribute(frontFace, osg::StateAttribute::ON);
|
stateset->setAttribute(frontFace, osg::StateAttribute::ON);
|
||||||
@ -1571,11 +1572,12 @@ namespace NifOsg
|
|||||||
|
|
||||||
if (stencilprop->data.enabled != 0)
|
if (stencilprop->data.enabled != 0)
|
||||||
{
|
{
|
||||||
osg::Stencil* stencil = new osg::Stencil;
|
osg::ref_ptr<osg::Stencil> stencil = new osg::Stencil;
|
||||||
stencil->setFunction(getStencilFunction(stencilprop->data.compareFunc), stencilprop->data.stencilRef, stencilprop->data.stencilMask);
|
stencil->setFunction(getStencilFunction(stencilprop->data.compareFunc), stencilprop->data.stencilRef, stencilprop->data.stencilMask);
|
||||||
stencil->setStencilFailOperation(getStencilOperation(stencilprop->data.failAction));
|
stencil->setStencilFailOperation(getStencilOperation(stencilprop->data.failAction));
|
||||||
stencil->setStencilPassAndDepthFailOperation(getStencilOperation(stencilprop->data.zFailAction));
|
stencil->setStencilPassAndDepthFailOperation(getStencilOperation(stencilprop->data.zFailAction));
|
||||||
stencil->setStencilPassAndDepthPassOperation(getStencilOperation(stencilprop->data.zPassAction));
|
stencil->setStencilPassAndDepthPassOperation(getStencilOperation(stencilprop->data.zPassAction));
|
||||||
|
stencil = shareAttribute(stencil);
|
||||||
|
|
||||||
stateset->setAttributeAndModes(stencil, osg::StateAttribute::ON);
|
stateset->setAttributeAndModes(stencil, osg::StateAttribute::ON);
|
||||||
}
|
}
|
||||||
@ -1584,9 +1586,10 @@ namespace NifOsg
|
|||||||
case Nif::RC_NiWireframeProperty:
|
case Nif::RC_NiWireframeProperty:
|
||||||
{
|
{
|
||||||
const Nif::NiWireframeProperty* wireprop = static_cast<const Nif::NiWireframeProperty*>(property);
|
const Nif::NiWireframeProperty* wireprop = static_cast<const Nif::NiWireframeProperty*>(property);
|
||||||
osg::PolygonMode* mode = new osg::PolygonMode;
|
osg::ref_ptr<osg::PolygonMode> mode = new osg::PolygonMode;
|
||||||
mode->setMode(osg::PolygonMode::FRONT_AND_BACK, wireprop->flags == 0 ? osg::PolygonMode::FILL
|
mode->setMode(osg::PolygonMode::FRONT_AND_BACK, wireprop->flags == 0 ? osg::PolygonMode::FILL
|
||||||
: osg::PolygonMode::LINE);
|
: osg::PolygonMode::LINE);
|
||||||
|
mode = shareAttribute(mode);
|
||||||
node->getOrCreateStateSet()->setAttributeAndModes(mode, osg::StateAttribute::ON);
|
node->getOrCreateStateSet()->setAttributeAndModes(mode, osg::StateAttribute::ON);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1594,8 +1597,12 @@ namespace NifOsg
|
|||||||
{
|
{
|
||||||
const Nif::NiZBufferProperty* zprop = static_cast<const Nif::NiZBufferProperty*>(property);
|
const Nif::NiZBufferProperty* zprop = static_cast<const Nif::NiZBufferProperty*>(property);
|
||||||
// VER_MW doesn't support a DepthFunction according to NifSkope
|
// VER_MW doesn't support a DepthFunction according to NifSkope
|
||||||
osg::Depth* depth = new osg::Depth;
|
static osg::ref_ptr<osg::Depth> depth;
|
||||||
depth->setWriteMask((zprop->flags>>1)&1);
|
if (!depth)
|
||||||
|
{
|
||||||
|
depth = new osg::Depth;
|
||||||
|
depth->setWriteMask((zprop->flags>>1)&1);
|
||||||
|
}
|
||||||
node->getOrCreateStateSet()->setAttributeAndModes(depth, osg::StateAttribute::ON);
|
node->getOrCreateStateSet()->setAttributeAndModes(depth, osg::StateAttribute::ON);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1632,23 +1639,25 @@ namespace NifOsg
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CompareMaterial
|
struct CompareStateAttribute
|
||||||
{
|
{
|
||||||
bool operator() (const osg::ref_ptr<osg::Material>& left, const osg::ref_ptr<osg::Material>& right) const
|
bool operator() (const osg::ref_ptr<osg::StateAttribute>& left, const osg::ref_ptr<osg::StateAttribute>& right) const
|
||||||
{
|
{
|
||||||
return left->compare(*right) < 0;
|
return left->compare(*right) < 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
osg::Material* shareMaterial(osg::Material* mat)
|
// global sharing of State Attributes will reduce the number of GL calls as the osg::State will check by pointer to see if state is the same
|
||||||
|
template <class Attribute>
|
||||||
|
Attribute* shareAttribute(const osg::ref_ptr<Attribute>& attr)
|
||||||
{
|
{
|
||||||
typedef std::set<osg::ref_ptr<osg::Material>, CompareMaterial> MatCache;
|
typedef std::set<osg::ref_ptr<Attribute>, CompareStateAttribute> Cache;
|
||||||
static MatCache sMats;
|
static Cache sCache;
|
||||||
static OpenThreads::Mutex sMutex;
|
static OpenThreads::Mutex sMutex;
|
||||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(sMutex);
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(sMutex);
|
||||||
MatCache::iterator found = sMats.find(mat);
|
typename Cache::iterator found = sCache.find(attr);
|
||||||
if (found == sMats.end())
|
if (found == sCache.end())
|
||||||
found = sMats.insert(mat).first;
|
found = sCache.insert(attr).first;
|
||||||
return *found;
|
return *found;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1715,9 +1724,10 @@ namespace NifOsg
|
|||||||
const Nif::NiAlphaProperty* alphaprop = static_cast<const Nif::NiAlphaProperty*>(property);
|
const Nif::NiAlphaProperty* alphaprop = static_cast<const Nif::NiAlphaProperty*>(property);
|
||||||
if (alphaprop->flags&1)
|
if (alphaprop->flags&1)
|
||||||
{
|
{
|
||||||
stateset->setAttributeAndModes(new osg::BlendFunc(getBlendMode((alphaprop->flags>>1)&0xf),
|
osg::ref_ptr<osg::BlendFunc> blendFunc (new osg::BlendFunc(getBlendMode((alphaprop->flags>>1)&0xf),
|
||||||
getBlendMode((alphaprop->flags>>5)&0xf)),
|
getBlendMode((alphaprop->flags>>5)&0xf)));
|
||||||
osg::StateAttribute::ON);
|
blendFunc = shareAttribute(blendFunc);
|
||||||
|
stateset->setAttributeAndModes(blendFunc, osg::StateAttribute::ON);
|
||||||
|
|
||||||
bool noSort = (alphaprop->flags>>13)&1;
|
bool noSort = (alphaprop->flags>>13)&1;
|
||||||
if (!noSort)
|
if (!noSort)
|
||||||
@ -1734,8 +1744,9 @@ namespace NifOsg
|
|||||||
|
|
||||||
if((alphaprop->flags>>9)&1)
|
if((alphaprop->flags>>9)&1)
|
||||||
{
|
{
|
||||||
stateset->setAttributeAndModes(new osg::AlphaFunc(getTestMode((alphaprop->flags>>10)&0x7),
|
osg::ref_ptr<osg::AlphaFunc> alphaFunc (new osg::AlphaFunc(getTestMode((alphaprop->flags>>10)&0x7), alphaprop->data.threshold/255.f));
|
||||||
alphaprop->data.threshold/255.f), osg::StateAttribute::ON);
|
alphaFunc = shareAttribute(alphaFunc);
|
||||||
|
stateset->setAttributeAndModes(alphaFunc, osg::StateAttribute::ON);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1767,9 +1778,7 @@ namespace NifOsg
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this could be replaced by a more generic mechanism of sharing any type of State Attribute
|
mat = shareAttribute(mat);
|
||||||
// apply only for Materials for now
|
|
||||||
mat = shareMaterial(mat);
|
|
||||||
|
|
||||||
stateset->setAttributeAndModes(mat, osg::StateAttribute::ON);
|
stateset->setAttributeAndModes(mat, osg::StateAttribute::ON);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user