mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-12-13 08:23:06 +00:00
allow statesetupdater as cullcallback = faster + works in paging
Signed-off-by: Bret Curtis <psi29a@gmail.com>
This commit is contained in:
parent
4238fbccdf
commit
f12879a04c
10 changed files with 62 additions and 50 deletions
|
|
@ -513,6 +513,9 @@ namespace MWRender
|
||||||
if (mShadowUniform)
|
if (mShadowUniform)
|
||||||
stateset->addUniform(mShadowUniform);
|
stateset->addUniform(mShadowUniform);
|
||||||
|
|
||||||
|
stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
||||||
|
stateset->setRenderBinMode(osg::StateSet::OVERRIDE_RENDERBIN_DETAILS);
|
||||||
|
|
||||||
// FIXME: overriding diffuse/ambient/emissive colors
|
// FIXME: overriding diffuse/ambient/emissive colors
|
||||||
osg::Material* material = new osg::Material;
|
osg::Material* material = new osg::Material;
|
||||||
material->setColorMode(osg::Material::OFF);
|
material->setColorMode(osg::Material::OFF);
|
||||||
|
|
@ -1741,31 +1744,16 @@ namespace MWRender
|
||||||
if (mTransparencyUpdater == nullptr)
|
if (mTransparencyUpdater == nullptr)
|
||||||
{
|
{
|
||||||
mTransparencyUpdater = new TransparencyUpdater(alpha, mResourceSystem->getSceneManager()->getShaderManager().getShadowMapAlphaTestEnableUniform());
|
mTransparencyUpdater = new TransparencyUpdater(alpha, mResourceSystem->getSceneManager()->getShaderManager().getShadowMapAlphaTestEnableUniform());
|
||||||
mObjectRoot->addUpdateCallback(mTransparencyUpdater);
|
mObjectRoot->addCullCallback(mTransparencyUpdater);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
mTransparencyUpdater->setAlpha(alpha);
|
mTransparencyUpdater->setAlpha(alpha);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mObjectRoot->removeUpdateCallback(mTransparencyUpdater);
|
mObjectRoot->removeCullCallback(mTransparencyUpdater);
|
||||||
mTransparencyUpdater = nullptr;
|
mTransparencyUpdater = nullptr;
|
||||||
mObjectRoot->setStateSet(nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setRenderBin();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Animation::setRenderBin()
|
|
||||||
{
|
|
||||||
if (mAlpha != 1.f)
|
|
||||||
{
|
|
||||||
osg::StateSet* stateset = mObjectRoot->getOrCreateStateSet();
|
|
||||||
stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
|
||||||
stateset->setRenderBinMode(osg::StateSet::OVERRIDE_RENDERBIN_DETAILS);
|
|
||||||
}
|
|
||||||
else if (osg::StateSet* stateset = mObjectRoot->getStateSet())
|
|
||||||
stateset->setRenderBinToInherit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Animation::setLightEffect(float effect)
|
void Animation::setLightEffect(float effect)
|
||||||
|
|
|
||||||
|
|
@ -336,9 +336,6 @@ protected:
|
||||||
*/
|
*/
|
||||||
virtual void addControllers();
|
virtual void addControllers();
|
||||||
|
|
||||||
/// Set the render bin for this animation's object root. May be customized by subclasses.
|
|
||||||
virtual void setRenderBin();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Animation(const MWWorld::Ptr &ptr, osg::ref_ptr<osg::Group> parentNode, Resource::ResourceSystem* resourceSystem);
|
Animation(const MWWorld::Ptr &ptr, osg::ref_ptr<osg::Group> parentNode, Resource::ResourceSystem* resourceSystem);
|
||||||
|
|
|
||||||
|
|
@ -435,12 +435,10 @@ void NpcAnimation::setRenderBin()
|
||||||
osgUtil::RenderBin::addRenderBinPrototype("DepthClear", depthClearBin);
|
osgUtil::RenderBin::addRenderBinPrototype("DepthClear", depthClearBin);
|
||||||
prototypeAdded = true;
|
prototypeAdded = true;
|
||||||
}
|
}
|
||||||
|
mObjectRoot->getOrCreateStateSet()->setRenderBinDetails(RenderBin_FirstPerson, "DepthClear", osg::StateSet::OVERRIDE_RENDERBIN_DETAILS);
|
||||||
osg::StateSet* stateset = mObjectRoot->getOrCreateStateSet();
|
|
||||||
stateset->setRenderBinDetails(RenderBin_FirstPerson, "DepthClear", osg::StateSet::OVERRIDE_RENDERBIN_DETAILS);
|
|
||||||
}
|
}
|
||||||
else
|
else if (osg::StateSet* stateset = mObjectRoot->getStateSet())
|
||||||
Animation::setRenderBin();
|
stateset->setRenderBinToInherit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NpcAnimation::rebuild()
|
void NpcAnimation::rebuild()
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ private:
|
||||||
void addPartGroup(int group, int priority, const std::vector<ESM::PartReference> &parts,
|
void addPartGroup(int group, int priority, const std::vector<ESM::PartReference> &parts,
|
||||||
bool enchantedGlow=false, osg::Vec4f* glowColor=nullptr);
|
bool enchantedGlow=false, osg::Vec4f* glowColor=nullptr);
|
||||||
|
|
||||||
virtual void setRenderBin();
|
void setRenderBin();
|
||||||
|
|
||||||
osg::ref_ptr<NeckController> mFirstPersonNeckController;
|
osg::ref_ptr<NeckController> mFirstPersonNeckController;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -162,6 +162,17 @@ namespace MWRender
|
||||||
{
|
{
|
||||||
if (callback->className() == std::string("BillboardCallback"))
|
if (callback->className() == std::string("BillboardCallback"))
|
||||||
handleBillboard(cloned);
|
handleBillboard(cloned);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (node->getCullCallback()->getNestedCallback())
|
||||||
|
{
|
||||||
|
osg::Callback *clonedCallback = osg::clone(callback, osg::CopyOp::SHALLOW_COPY);
|
||||||
|
clonedCallback->setNestedCallback(nullptr);
|
||||||
|
cloned->addCullCallback(clonedCallback);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cloned->addCullCallback(const_cast<osg::Callback*>(callback));
|
||||||
|
}
|
||||||
callback = callback->getNestedCallback();
|
callback = callback->getNestedCallback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -352,8 +352,9 @@ void RollController::operator() (osg::Node* node, osg::NodeVisitor* nv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AlphaController::AlphaController(const Nif::NiFloatData *data)
|
AlphaController::AlphaController(const Nif::NiFloatData *data, const osg::Material* baseMaterial)
|
||||||
: mData(data->mKeyList, 1.f)
|
: mData(data->mKeyList, 1.f)
|
||||||
|
, mBaseMaterial(baseMaterial)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -365,14 +366,13 @@ AlphaController::AlphaController()
|
||||||
AlphaController::AlphaController(const AlphaController ©, const osg::CopyOp ©op)
|
AlphaController::AlphaController(const AlphaController ©, const osg::CopyOp ©op)
|
||||||
: StateSetUpdater(copy, copyop), Controller(copy)
|
: StateSetUpdater(copy, copyop), Controller(copy)
|
||||||
, mData(copy.mData)
|
, mData(copy.mData)
|
||||||
|
, mBaseMaterial(copy.mBaseMaterial)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void AlphaController::setDefaults(osg::StateSet *stateset)
|
void AlphaController::setDefaults(osg::StateSet *stateset)
|
||||||
{
|
{
|
||||||
// need to create a deep copy of StateAttributes we will modify
|
stateset->setAttribute(osg::clone(mBaseMaterial.get(), osg::CopyOp::DEEP_COPY_ALL), osg::StateAttribute::ON);
|
||||||
osg::Material* mat = static_cast<osg::Material*>(stateset->getAttribute(osg::StateAttribute::MATERIAL));
|
|
||||||
stateset->setAttribute(osg::clone(mat, osg::CopyOp::DEEP_COPY_ALL), osg::StateAttribute::ON);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AlphaController::apply(osg::StateSet *stateset, osg::NodeVisitor *nv)
|
void AlphaController::apply(osg::StateSet *stateset, osg::NodeVisitor *nv)
|
||||||
|
|
@ -387,9 +387,10 @@ void AlphaController::apply(osg::StateSet *stateset, osg::NodeVisitor *nv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialColorController::MaterialColorController(const Nif::NiPosData *data, TargetColor color)
|
MaterialColorController::MaterialColorController(const Nif::NiPosData *data, TargetColor color, const osg::Material* baseMaterial)
|
||||||
: mData(data->mKeyList, osg::Vec3f(1,1,1))
|
: mData(data->mKeyList, osg::Vec3f(1,1,1))
|
||||||
, mTargetColor(color)
|
, mTargetColor(color)
|
||||||
|
, mBaseMaterial(baseMaterial)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -401,14 +402,13 @@ MaterialColorController::MaterialColorController(const MaterialColorController &
|
||||||
: StateSetUpdater(copy, copyop), Controller(copy)
|
: StateSetUpdater(copy, copyop), Controller(copy)
|
||||||
, mData(copy.mData)
|
, mData(copy.mData)
|
||||||
, mTargetColor(copy.mTargetColor)
|
, mTargetColor(copy.mTargetColor)
|
||||||
|
, mBaseMaterial(copy.mBaseMaterial)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void MaterialColorController::setDefaults(osg::StateSet *stateset)
|
void MaterialColorController::setDefaults(osg::StateSet *stateset)
|
||||||
{
|
{
|
||||||
// need to create a deep copy of StateAttributes we will modify
|
stateset->setAttribute(osg::clone(mBaseMaterial.get(), osg::CopyOp::DEEP_COPY_ALL), osg::StateAttribute::ON);
|
||||||
osg::Material* mat = static_cast<osg::Material*>(stateset->getAttribute(osg::StateAttribute::MATERIAL));
|
|
||||||
stateset->setAttribute(osg::clone(mat, osg::CopyOp::DEEP_COPY_ALL), osg::StateAttribute::ON);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MaterialColorController::apply(osg::StateSet *stateset, osg::NodeVisitor *nv)
|
void MaterialColorController::apply(osg::StateSet *stateset, osg::NodeVisitor *nv)
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ namespace osg
|
||||||
{
|
{
|
||||||
class Node;
|
class Node;
|
||||||
class StateSet;
|
class StateSet;
|
||||||
|
class Material;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace osgParticle
|
namespace osgParticle
|
||||||
|
|
@ -268,9 +269,9 @@ namespace NifOsg
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
FloatInterpolator mData;
|
FloatInterpolator mData;
|
||||||
|
osg::ref_ptr<const osg::Material> mBaseMaterial;
|
||||||
public:
|
public:
|
||||||
AlphaController(const Nif::NiFloatData *data);
|
AlphaController(const Nif::NiFloatData *data, const osg::Material* baseMaterial);
|
||||||
AlphaController();
|
AlphaController();
|
||||||
AlphaController(const AlphaController& copy, const osg::CopyOp& copyop);
|
AlphaController(const AlphaController& copy, const osg::CopyOp& copyop);
|
||||||
|
|
||||||
|
|
@ -291,7 +292,7 @@ namespace NifOsg
|
||||||
Specular = 2,
|
Specular = 2,
|
||||||
Emissive = 3
|
Emissive = 3
|
||||||
};
|
};
|
||||||
MaterialColorController(const Nif::NiPosData *data, TargetColor color);
|
MaterialColorController(const Nif::NiPosData *data, TargetColor color, const osg::Material* baseMaterial);
|
||||||
MaterialColorController();
|
MaterialColorController();
|
||||||
MaterialColorController(const MaterialColorController& copy, const osg::CopyOp& copyop);
|
MaterialColorController(const MaterialColorController& copy, const osg::CopyOp& copyop);
|
||||||
|
|
||||||
|
|
@ -304,6 +305,7 @@ namespace NifOsg
|
||||||
private:
|
private:
|
||||||
Vec3Interpolator mData;
|
Vec3Interpolator mData;
|
||||||
TargetColor mTargetColor = Ambient;
|
TargetColor mTargetColor = Ambient;
|
||||||
|
osg::ref_ptr<const osg::Material> mBaseMaterial;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FlipController : public SceneUtil::StateSetUpdater, public SceneUtil::Controller
|
class FlipController : public SceneUtil::StateSetUpdater, public SceneUtil::Controller
|
||||||
|
|
|
||||||
|
|
@ -639,7 +639,15 @@ namespace NifOsg
|
||||||
handleParticleSystem(nifNode, node, composite, animflags, rootNode);
|
handleParticleSystem(nifNode, node, composite, animflags, rootNode);
|
||||||
|
|
||||||
if (composite->getNumControllers() > 0)
|
if (composite->getNumControllers() > 0)
|
||||||
node->addUpdateCallback(composite);
|
{
|
||||||
|
osg::Callback *cb = composite;
|
||||||
|
if (composite->getNumControllers() == 1)
|
||||||
|
cb = composite->getController(0);
|
||||||
|
if (animflags & Nif::NiNode::AnimFlag_AutoPlay)
|
||||||
|
node->addCullCallback(cb);
|
||||||
|
else
|
||||||
|
node->addUpdateCallback(cb); // have to remain as UpdateCallback so AssignControllerSourcesVisitor can find it.
|
||||||
|
}
|
||||||
|
|
||||||
bool isAnimated = false;
|
bool isAnimated = false;
|
||||||
handleNodeControllers(nifNode, node, animflags, isAnimated);
|
handleNodeControllers(nifNode, node, animflags, isAnimated);
|
||||||
|
|
@ -778,7 +786,7 @@ namespace NifOsg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleMaterialControllers(const Nif::Property *materialProperty, SceneUtil::CompositeStateSetUpdater* composite, int animflags)
|
void handleMaterialControllers(const Nif::Property *materialProperty, SceneUtil::CompositeStateSetUpdater* composite, int animflags, const osg::Material* baseMaterial)
|
||||||
{
|
{
|
||||||
for (Nif::ControllerPtr ctrl = materialProperty->controller; !ctrl.empty(); ctrl = ctrl->next)
|
for (Nif::ControllerPtr ctrl = materialProperty->controller; !ctrl.empty(); ctrl = ctrl->next)
|
||||||
{
|
{
|
||||||
|
|
@ -789,7 +797,7 @@ namespace NifOsg
|
||||||
const Nif::NiAlphaController* alphactrl = static_cast<const Nif::NiAlphaController*>(ctrl.getPtr());
|
const Nif::NiAlphaController* alphactrl = static_cast<const Nif::NiAlphaController*>(ctrl.getPtr());
|
||||||
if (alphactrl->data.empty())
|
if (alphactrl->data.empty())
|
||||||
continue;
|
continue;
|
||||||
osg::ref_ptr<AlphaController> osgctrl(new AlphaController(alphactrl->data.getPtr()));
|
osg::ref_ptr<AlphaController> osgctrl(new AlphaController(alphactrl->data.getPtr(), baseMaterial));
|
||||||
setupController(alphactrl, osgctrl, animflags);
|
setupController(alphactrl, osgctrl, animflags);
|
||||||
composite->addController(osgctrl);
|
composite->addController(osgctrl);
|
||||||
}
|
}
|
||||||
|
|
@ -799,7 +807,7 @@ namespace NifOsg
|
||||||
if (matctrl->data.empty())
|
if (matctrl->data.empty())
|
||||||
continue;
|
continue;
|
||||||
auto targetColor = static_cast<MaterialColorController::TargetColor>(matctrl->targetColor);
|
auto targetColor = static_cast<MaterialColorController::TargetColor>(matctrl->targetColor);
|
||||||
osg::ref_ptr<MaterialColorController> osgctrl(new MaterialColorController(matctrl->data.getPtr(), targetColor));
|
osg::ref_ptr<MaterialColorController> osgctrl(new MaterialColorController(matctrl->data.getPtr(), targetColor, baseMaterial));
|
||||||
setupController(matctrl, osgctrl, animflags);
|
setupController(matctrl, osgctrl, animflags);
|
||||||
composite->addController(osgctrl);
|
composite->addController(osgctrl);
|
||||||
}
|
}
|
||||||
|
|
@ -1767,7 +1775,7 @@ namespace NifOsg
|
||||||
if (!matprop->controller.empty())
|
if (!matprop->controller.empty())
|
||||||
{
|
{
|
||||||
hasMatCtrl = true;
|
hasMatCtrl = true;
|
||||||
handleMaterialControllers(matprop, composite, animflags);
|
handleMaterialControllers(matprop, composite, animflags, mat);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -2,30 +2,38 @@
|
||||||
|
|
||||||
#include <osg/Node>
|
#include <osg/Node>
|
||||||
#include <osg/NodeVisitor>
|
#include <osg/NodeVisitor>
|
||||||
|
#include <osgUtil/CullVisitor>
|
||||||
|
|
||||||
namespace SceneUtil
|
namespace SceneUtil
|
||||||
{
|
{
|
||||||
|
|
||||||
void StateSetUpdater::operator()(osg::Node* node, osg::NodeVisitor* nv)
|
void StateSetUpdater::operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||||
{
|
{
|
||||||
|
bool isCullVisitor = nv->getVisitorType() == osg::NodeVisitor::CULL_VISITOR;
|
||||||
if (!mStateSets[0])
|
if (!mStateSets[0])
|
||||||
{
|
{
|
||||||
// first time setup
|
for (int i=0; i<2; ++i)
|
||||||
osg::StateSet* src = node->getOrCreateStateSet();
|
|
||||||
for (int i=0; i<2; ++i) // Using SHALLOW_COPY for StateAttributes, if users want to modify it is their responsibility to set a non-shared one first
|
|
||||||
// This can be done conveniently in user implementations of the setDefaults() method
|
|
||||||
{
|
{
|
||||||
mStateSets[i] = new osg::StateSet(*src, osg::CopyOp::SHALLOW_COPY);
|
if (!isCullVisitor)
|
||||||
|
mStateSets[i] = new osg::StateSet(*node->getOrCreateStateSet(), osg::CopyOp::SHALLOW_COPY); // Using SHALLOW_COPY for StateAttributes, if users want to modify it is their responsibility to set a non-shared one first in setDefaults
|
||||||
|
else
|
||||||
|
mStateSets[i] = new osg::StateSet;
|
||||||
setDefaults(mStateSets[i]);
|
setDefaults(mStateSets[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::StateSet* stateset = mStateSets[nv->getTraversalNumber()%2];
|
osg::StateSet* stateset = mStateSets[nv->getTraversalNumber()%2];
|
||||||
node->setStateSet(stateset);
|
|
||||||
|
|
||||||
apply(stateset, nv);
|
apply(stateset, nv);
|
||||||
|
|
||||||
|
if (!isCullVisitor)
|
||||||
|
node->setStateSet(stateset);
|
||||||
|
else
|
||||||
|
static_cast<osgUtil::CullVisitor*>(nv)->pushStateSet(stateset);
|
||||||
|
|
||||||
traverse(node, nv);
|
traverse(node, nv);
|
||||||
|
|
||||||
|
if (isCullVisitor)
|
||||||
|
static_cast<osgUtil::CullVisitor*>(nv)->popStateSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
void StateSetUpdater::reset()
|
void StateSetUpdater::reset()
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ namespace SceneUtil
|
||||||
/// traversals run in parallel can yield up to 200% framerates.
|
/// traversals run in parallel can yield up to 200% framerates.
|
||||||
/// @par Race conditions are prevented using a "double buffering" scheme - we have two StateSets that take turns,
|
/// @par Race conditions are prevented using a "double buffering" scheme - we have two StateSets that take turns,
|
||||||
/// one StateSet we can write to, the second one is currently in use by the draw traversal of the last frame.
|
/// one StateSet we can write to, the second one is currently in use by the draw traversal of the last frame.
|
||||||
/// @par Must be set as UpdateCallback on a Node.
|
/// @par Must be set as UpdateCallback or CullCallback on a Node. If set as a CullCallback, the StateSetUpdater operates on an empty StateSet, otherwise it operates on a clone of the node's existing StateSet.
|
||||||
/// @note Do not add the same StateSetUpdater to multiple nodes.
|
/// @note Do not add the same StateSetUpdater to multiple nodes.
|
||||||
/// @note Do not add multiple StateSetControllers on the same Node as they will conflict - instead use the CompositeStateSetUpdater.
|
/// @note Do not add multiple StateSetControllers on the same Node as they will conflict - instead use the CompositeStateSetUpdater.
|
||||||
class StateSetUpdater : public osg::NodeCallback
|
class StateSetUpdater : public osg::NodeCallback
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue