1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-29 09:32:45 +00:00
OpenMW/apps/openmw/mwrender/transparentpass.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

144 lines
5.7 KiB
C++
Raw Normal View History

2022-05-13 18:58:00 -07:00
#include "transparentpass.hpp"
#include <osg/AlphaFunc>
2022-05-13 18:58:00 -07:00
#include <osg/BlendFunc>
#include <osg/Material>
2022-05-13 18:58:00 -07:00
#include <osg/Texture2D>
2022-06-21 15:55:06 +00:00
#include <osg/Texture2DArray>
2022-05-13 18:58:00 -07:00
#include <osgUtil/RenderStage>
#include <components/sceneutil/depth.hpp>
2022-05-13 18:58:00 -07:00
#include <components/shader/shadermanager.hpp>
2022-06-21 15:55:06 +00:00
#include <components/stereo/multiview.hpp>
#include <components/stereo/stereomanager.hpp>
2022-05-13 18:58:00 -07:00
#include "vismask.hpp"
2022-05-13 18:58:00 -07:00
namespace MWRender
{
TransparentDepthBinCallback::TransparentDepthBinCallback(Shader::ShaderManager& shaderManager, bool postPass)
: mStateSet(new osg::StateSet)
, mPostPass(postPass)
2022-09-22 21:26:05 +03:00
{
2022-05-13 18:58:00 -07:00
osg::ref_ptr<osg::Image> image = new osg::Image;
image->allocateImage(1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE);
image->setColor(osg::Vec4(1, 1, 1, 1), 0, 0);
2022-09-22 21:26:05 +03:00
2022-05-13 18:58:00 -07:00
osg::ref_ptr<osg::Texture2D> dummyTexture = new osg::Texture2D(image);
dummyTexture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
dummyTexture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
2022-09-22 21:26:05 +03:00
2022-05-13 18:58:00 -07:00
constexpr osg::StateAttribute::OverrideValue modeOff = osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE;
constexpr osg::StateAttribute::OverrideValue modeOn = osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE;
2022-09-22 21:26:05 +03:00
2022-05-13 18:58:00 -07:00
mStateSet->setTextureAttributeAndModes(0, dummyTexture);
2022-09-22 21:26:05 +03:00
2022-06-21 15:55:06 +00:00
Shader::ShaderManager::DefineMap defines;
Stereo::shaderStereoDefines(defines);
2022-09-22 21:26:05 +03:00
2022-05-13 18:58:00 -07:00
mStateSet->setAttributeAndModes(new osg::BlendFunc, modeOff);
2023-02-25 11:03:39 -08:00
mStateSet->setAttributeAndModes(shaderManager.getProgram("depthclipped", defines), modeOn);
mStateSet->setAttributeAndModes(new SceneUtil::AutoDepth, modeOn);
2022-09-22 21:26:05 +03:00
2022-05-13 18:58:00 -07:00
for (unsigned int unit = 1; unit < 8; ++unit)
mStateSet->setTextureMode(unit, GL_TEXTURE_2D, modeOff);
2022-09-22 21:26:05 +03:00
}
2022-05-13 18:58:00 -07:00
void TransparentDepthBinCallback::drawImplementation(
osgUtil::RenderBin* bin, osg::RenderInfo& renderInfo, osgUtil::RenderLeaf*& previous)
2022-09-22 21:26:05 +03:00
{
2022-05-13 18:58:00 -07:00
osg::State& state = *renderInfo.getState();
osg::GLExtensions* ext = state.get<osg::GLExtensions>();
2022-09-22 21:26:05 +03:00
2022-05-13 18:58:00 -07:00
bool validFbo = false;
unsigned int frameId = state.getFrameStamp()->getFrameNumber() % 2;
2022-09-22 21:26:05 +03:00
2022-05-13 18:58:00 -07:00
const auto& fbo = mFbo[frameId];
const auto& msaaFbo = mMsaaFbo[frameId];
const auto& opaqueFbo = mOpaqueFbo[frameId];
2022-09-22 21:26:05 +03:00
2022-05-13 18:58:00 -07:00
if (bin->getStage()->getMultisampleResolveFramebufferObject()
&& bin->getStage()->getMultisampleResolveFramebufferObject() == fbo)
validFbo = true;
else if (bin->getStage()->getFrameBufferObject()
&& (bin->getStage()->getFrameBufferObject() == fbo || bin->getStage()->getFrameBufferObject() == msaaFbo))
validFbo = true;
2022-09-22 21:26:05 +03:00
2022-05-13 18:58:00 -07:00
if (!validFbo)
{
2022-06-21 15:55:06 +00:00
bin->drawImplementation(renderInfo, previous);
2022-05-13 18:58:00 -07:00
return;
}
const osg::Texture* tex
= opaqueFbo->getAttachment(osg::FrameBufferObject::BufferComponent::PACKED_DEPTH_STENCIL_BUFFER)
.getTexture();
if (Stereo::getMultiview())
2022-09-22 21:26:05 +03:00
{
2022-05-13 18:58:00 -07:00
if (!mMultiviewResolve[frameId])
{
mMultiviewResolve[frameId] = std::make_unique<Stereo::MultiviewFramebufferResolve>(
msaaFbo ? msaaFbo : fbo, opaqueFbo, GL_DEPTH_BUFFER_BIT);
}
else
{
mMultiviewResolve[frameId]->setResolveFbo(opaqueFbo);
mMultiviewResolve[frameId]->setMsaaFbo(msaaFbo ? msaaFbo : fbo);
}
mMultiviewResolve[frameId]->resolveImplementation(state);
2022-09-22 21:26:05 +03:00
}
else
{
2022-05-13 18:58:00 -07:00
opaqueFbo->apply(state, osg::FrameBufferObject::DRAW_FRAMEBUFFER);
2022-06-21 15:55:06 +00:00
ext->glBlitFramebuffer(0, 0, tex->getTextureWidth(), tex->getTextureHeight(), 0, 0, tex->getTextureWidth(),
tex->getTextureHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
2022-09-22 21:26:05 +03:00
}
2022-05-13 18:58:00 -07:00
msaaFbo ? msaaFbo->apply(state, osg::FrameBufferObject::DRAW_FRAMEBUFFER)
: fbo->apply(state, osg::FrameBufferObject::DRAW_FRAMEBUFFER);
// draws scene into primary attachments
bin->drawImplementation(renderInfo, previous);
2022-05-13 18:58:00 -07:00
if (!mPostPass)
return;
2022-05-13 18:58:00 -07:00
opaqueFbo->apply(state, osg::FrameBufferObject::DRAW_FRAMEBUFFER);
// 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--;
2022-05-13 18:58:00 -07:00
unsigned int insertStateSetPosition = state.getStateSetStackSize() - numToPop;
state.insertStateSet(insertStateSetPosition, mStateSet);
for (auto rit = bin->getRenderLeafList().begin(); rit != bin->getRenderLeafList().end(); rit++)
2022-09-22 21:26:05 +03:00
{
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::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;
}
2022-06-21 15:55:06 +00:00
rl->render(renderInfo, previous);
previous = rl;
2022-05-13 18:58:00 -07:00
}
state.removeStateSet(insertStateSetPosition);
2022-09-22 21:26:05 +03:00
msaaFbo ? msaaFbo->apply(state, osg::FrameBufferObject::DRAW_FRAMEBUFFER)
: fbo->apply(state, osg::FrameBufferObject::DRAW_FRAMEBUFFER);
2022-06-21 15:55:06 +00:00
state.checkGLErrors("after TransparentDepthBinCallback::drawImplementation");
2022-09-22 21:26:05 +03:00
}
2022-06-21 15:55:06 +00:00
}