From 066185fbcf84e696a957336d48572275abbedba6 Mon Sep 17 00:00:00 2001
From: "glassmancody.info" <glassmancody.info@gmail.com>
Date: Sat, 30 Jul 2022 14:37:49 -0700
Subject: [PATCH] override depth write flag from object paging in transparent
 post-pass

---
 apps/openmw/mwrender/animation.cpp       | 19 ++++++++++++
 apps/openmw/mwrender/transparentpass.cpp | 39 +++++++++++++++++++++---
 2 files changed, 53 insertions(+), 5 deletions(-)

diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp
index 0933bf4e9e..9d910c00f9 100644
--- a/apps/openmw/mwrender/animation.cpp
+++ b/apps/openmw/mwrender/animation.cpp
@@ -51,6 +51,22 @@
 
 namespace
 {
+    class MarkDrawablesVisitor : public osg::NodeVisitor
+    {
+    public:
+        MarkDrawablesVisitor(osg::Node::NodeMask mask)
+            : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
+            , mMask(mask)
+        { }
+
+        void apply(osg::Drawable& drawable) override
+        {
+            drawable.setNodeMask(mMask);
+        }
+
+    private:
+        osg::Node::NodeMask mMask = 0;
+    };
 
     /// Removes all particle systems and related nodes in a subgraph.
     class RemoveParticlesVisitor : public osg::NodeVisitor
@@ -1555,6 +1571,9 @@ namespace MWRender
 
         node->setNodeMask(Mask_Effect);
 
+        MarkDrawablesVisitor markVisitor(Mask_Effect);
+        node->accept(markVisitor);
+
         params.mMaxControllerLength = findMaxLengthVisitor.getMaxLength();
         params.mLoop = loop;
         params.mEffectId = effectId;
diff --git a/apps/openmw/mwrender/transparentpass.cpp b/apps/openmw/mwrender/transparentpass.cpp
index 239a11821b..facd271643 100644
--- a/apps/openmw/mwrender/transparentpass.cpp
+++ b/apps/openmw/mwrender/transparentpass.cpp
@@ -3,6 +3,8 @@
 #include <osg/BlendFunc>
 #include <osg/Texture2D>
 #include <osg/Texture2DArray>
+#include <osg/Material>
+#include <osg/AlphaFunc>
 
 #include <osgUtil/RenderStage>
 
@@ -10,6 +12,8 @@
 #include <components/stereo/multiview.hpp>
 #include <components/stereo/stereomanager.hpp>
 
+#include "vismask.hpp"
+
 namespace MWRender
 {
         TransparentDepthBinCallback::TransparentDepthBinCallback(Shader::ShaderManager& shaderManager, bool postPass)
@@ -34,6 +38,7 @@ namespace MWRender
 
             mStateSet->setAttributeAndModes(new osg::BlendFunc, modeOff);
             mStateSet->setAttributeAndModes(shaderManager.getProgram(vertex, fragment), modeOn);
+            mStateSet->setAttributeAndModes(new SceneUtil::AutoDepth, modeOn);
 
             for (unsigned int unit = 1; unit < 8; ++unit)
                 mStateSet->setTextureMode(unit, GL_TEXTURE_2D, modeOff);
@@ -88,11 +93,35 @@ namespace MWRender
 
             opaqueFbo->apply(state, osg::FrameBufferObject::DRAW_FRAMEBUFFER);
 
-            osg::ref_ptr<osg::StateSet> restore = bin->getStateSet();
-            bin->setStateSet(mStateSet);
-            // draws transparent post-pass to populate a postprocess friendly depth texture with alpha-clipped geometry
-            bin->drawImplementation(renderInfo, previous);
-            bin->setStateSet(restore);
+            // draw transparent post-pass to populate a postprocess friendly depth texture with alpha-clipped geometry
+
+            unsigned int numToPop = previous ? osgUtil::StateGraph::numToPop(previous->_parent) : 0;
+            if (numToPop > 1)
+                 numToPop--;
+            unsigned int insertStateSetPosition = state.getStateSetStackSize() - numToPop;
+
+            state.insertStateSet(insertStateSetPosition, mStateSet);
+            for(auto rit = bin->getRenderLeafList().begin(); rit != bin->getRenderLeafList().end(); rit++)
+            {
+                osgUtil::RenderLeaf* rl = *rit;
+                const osg::StateSet* ss = rl->_parent->getStateSet();
+
+                if (rl->_drawable->getNodeMask() == Mask_ParticleSystem || rl->_drawable->getNodeMask() == Mask_Effect)
+                    continue;
+
+                if (ss->getAttribute(osg::StateAttribute::ALPHAFUNC))
+                    continue;
+
+                if (ss->getAttribute(osg::StateAttribute::MATERIAL)) {
+                    const osg::Material* mat = static_cast<const osg::Material*>(ss->getAttribute(osg::StateAttribute::MATERIAL));
+                    if (mat->getDiffuse(osg::Material::FRONT).a() < 0.5)
+                        continue;
+                }
+
+                rl->render(renderInfo,previous);
+                previous = rl;
+            }
+            state.removeStateSet(insertStateSetPosition);
 
             msaaFbo ? msaaFbo->apply(state, osg::FrameBufferObject::DRAW_FRAMEBUFFER) : fbo->apply(state, osg::FrameBufferObject::DRAW_FRAMEBUFFER);
             state.checkGLErrors("after TransparentDepthBinCallback::drawImplementation");