diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index a0704a59a..b2fa87310 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -1275,15 +1275,26 @@ namespace MWRender material->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4f(1,1,1,1)); stateset->setAttributeAndModes(material, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE); - stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); - stateset->setRenderBinMode(osg::StateSet::OVERRIDE_RENDERBIN_DETAILS); - stateset->setNestRenderBins(false); mObjectRoot->setStateSet(stateset); } else { mObjectRoot->setStateSet(NULL); } + + 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) diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 94b792c0d..1e46cc71a 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -307,6 +307,9 @@ protected: void addGlow(osg::ref_ptr node, osg::Vec4f glowColor); + /// Set the render bin for this animation's object root. May be customized by subclasses. + virtual void setRenderBin(); + public: Animation(const MWWorld::Ptr &ptr, osg::ref_ptr parentNode, Resource::ResourceSystem* resourceSystem); diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 99ee886e1..cba6c5696 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -2,6 +2,9 @@ #include #include +#include + +#include #include @@ -28,6 +31,7 @@ #include "camera.hpp" #include "rotatecontroller.hpp" +#include "renderbin.hpp" namespace { @@ -303,6 +307,50 @@ void NpcAnimation::setViewMode(NpcAnimation::ViewMode viewMode) mViewMode = viewMode; rebuild(); + + setRenderBin(); +} + +/// @brief A RenderBin callback to clear the depth buffer before rendering. +class DepthClearCallback : public osgUtil::RenderBin::DrawCallback +{ +public: + DepthClearCallback() + { + mDepth = new osg::Depth; + mDepth->setWriteMask(true); + } + + virtual void drawImplementation(osgUtil::RenderBin* bin, osg::RenderInfo& renderInfo, osgUtil::RenderLeaf*& previous) + { + renderInfo.getState()->applyAttribute(mDepth); + + glClear(GL_DEPTH_BUFFER_BIT); + + bin->drawImplementation(renderInfo, previous); + } + + osg::ref_ptr mDepth; +}; + +void NpcAnimation::setRenderBin() +{ + if (mViewMode == VM_FirstPerson) + { + static bool prototypeAdded = false; + if (!prototypeAdded) + { + osg::ref_ptr depthClearBin (new osgUtil::RenderBin); + depthClearBin->setDrawCallback(new DepthClearCallback); + osgUtil::RenderBin::addRenderBinPrototype("DepthClear", depthClearBin); + prototypeAdded = true; + } + + osg::StateSet* stateset = mObjectRoot->getOrCreateStateSet(); + stateset->setRenderBinDetails(RenderBin_FirstPerson, "DepthClear", osg::StateSet::OVERRIDE_RENDERBIN_DETAILS); + } + else + Animation::setRenderBin(); } void NpcAnimation::rebuild() diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index 06f40f847..b4272226d 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -81,6 +81,8 @@ private: void addPartGroup(int group, int priority, const std::vector &parts, bool enchantedGlow=false, osg::Vec4f* glowColor=NULL); + virtual void setRenderBin(); + osg::ref_ptr mFirstPersonNeckController; protected: diff --git a/apps/openmw/mwrender/renderbin.hpp b/apps/openmw/mwrender/renderbin.hpp index 63ccdd259..c14f61142 100644 --- a/apps/openmw/mwrender/renderbin.hpp +++ b/apps/openmw/mwrender/renderbin.hpp @@ -5,14 +5,15 @@ namespace MWRender { /// Defines the render bin numbers used in the OpenMW scene graph. The bin with the lowest number is rendered first. - /// Beware of RenderBin nesting, in most cases you will want to use setNestRenderBins(false). enum RenderBins { RenderBin_Sky = -1, - RenderBin_Default = 0, + RenderBin_Default = 0, // osg::StateSet::OPAQUE_BIN RenderBin_Water = 9, - RenderBin_OcclusionQuery = 10, - RenderBin_SunGlare = 11 + RenderBin_DepthSorted = 10, // osg::StateSet::TRANSPARENT_BIN + RenderBin_OcclusionQuery = 11, + RenderBin_FirstPerson = 12, + RenderBin_SunGlare = 13 }; }