mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-16 18:59:57 +00:00
Merge branch 'postprocessor-stereo' into 'master'
[Postprocessing] Stereo integration See merge request OpenMW/openmw!1988
This commit is contained in:
commit
feef257584
29 changed files with 578 additions and 179 deletions
|
@ -361,6 +361,8 @@ public:
|
|||
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
bin->drawImplementation(renderInfo, previous);
|
||||
}
|
||||
|
||||
state->checkGLErrors("after DepthClearCallback::drawImplementation");
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Depth> mDepth;
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
#include <components/shader/shadermanager.hpp>
|
||||
#include <components/debug/debuglog.hpp>
|
||||
#include <components/stereo/stereomanager.hpp>
|
||||
#include <components/stereo/multiview.hpp>
|
||||
|
||||
#include <osg/Texture2DArray>
|
||||
|
||||
#include "postprocessor.hpp"
|
||||
|
||||
|
@ -9,6 +13,7 @@ namespace MWRender
|
|||
{
|
||||
PingPongCanvas::PingPongCanvas(Shader::ShaderManager& shaderManager)
|
||||
: mFallbackStateSet(new osg::StateSet)
|
||||
, mMultiviewResolveStateSet(new osg::StateSet)
|
||||
{
|
||||
setUseDisplayList(false);
|
||||
setUseVertexBufferObjects(true);
|
||||
|
@ -25,12 +30,21 @@ namespace MWRender
|
|||
mHDRDriver = HDRDriver(shaderManager);
|
||||
mHDRDriver.disable();
|
||||
|
||||
auto fallbackVertex = shaderManager.getShader("fullscreen_tri_vertex.glsl", {}, osg::Shader::VERTEX);
|
||||
auto fallbackFragment = shaderManager.getShader("fullscreen_tri_fragment.glsl", {}, osg::Shader::FRAGMENT);
|
||||
Shader::ShaderManager::DefineMap defines;
|
||||
Stereo::Manager::instance().shaderStereoDefines(defines);
|
||||
|
||||
auto fallbackVertex = shaderManager.getShader("fullscreen_tri_vertex.glsl", defines, osg::Shader::VERTEX);
|
||||
auto fallbackFragment = shaderManager.getShader("fullscreen_tri_fragment.glsl", defines, osg::Shader::FRAGMENT);
|
||||
mFallbackProgram = shaderManager.getProgram(fallbackVertex, fallbackFragment);
|
||||
|
||||
mFallbackStateSet->setAttributeAndModes(mFallbackProgram);
|
||||
mFallbackStateSet->addUniform(new osg::Uniform("omw_SamplerLastShader", 0));
|
||||
|
||||
auto multiviewResolveVertex = shaderManager.getShader("multiview_resolve_vertex.glsl", {}, osg::Shader::VERTEX);
|
||||
auto multiviewResolveFragment = shaderManager.getShader("multiview_resolve_fragment.glsl", {}, osg::Shader::FRAGMENT);
|
||||
mMultiviewResolveProgram = shaderManager.getProgram(multiviewResolveVertex, multiviewResolveFragment);
|
||||
mMultiviewResolveStateSet->setAttributeAndModes(mMultiviewResolveProgram);
|
||||
mMultiviewResolveStateSet->addUniform(new osg::Uniform("omw_SamplerLastShader", 0));
|
||||
}
|
||||
|
||||
void PingPongCanvas::setCurrentFrameData(size_t frameId, fx::DispatchArray&& data)
|
||||
|
@ -51,6 +65,29 @@ namespace MWRender
|
|||
osg::Geometry::drawImplementation(renderInfo);
|
||||
}
|
||||
|
||||
static void attachCloneOfTemplate(osg::FrameBufferObject* fbo, osg::Camera::BufferComponent component, osg::Texture* tex)
|
||||
{
|
||||
switch (tex->getTextureTarget())
|
||||
{
|
||||
case GL_TEXTURE_2D:
|
||||
{
|
||||
auto* tex2d = new osg::Texture2D(*static_cast<osg::Texture2D*>(tex));
|
||||
fbo->setAttachment(component, osg::FrameBufferAttachment(tex2d));
|
||||
}
|
||||
break;
|
||||
case GL_TEXTURE_2D_ARRAY:
|
||||
{
|
||||
#ifdef OSG_HAS_MULTIVIEW
|
||||
auto* tex2dArray = new osg::Texture2DArray(*static_cast<osg::Texture2DArray*>(tex));
|
||||
fbo->setAttachment(component, osg::FrameBufferAttachment(tex2dArray, osg::Camera::FACE_CONTROLLED_BY_MULTIVIEW_SHADER, 0));
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw std::logic_error("Invalid texture type received");
|
||||
}
|
||||
}
|
||||
|
||||
void PingPongCanvas::drawImplementation(osg::RenderInfo& renderInfo) const
|
||||
{
|
||||
osg::State& state = *renderInfo.getState();
|
||||
|
@ -76,7 +113,7 @@ namespace MWRender
|
|||
filtered.push_back(i);
|
||||
}
|
||||
|
||||
auto* viewport = state.getCurrentViewport();
|
||||
auto* resolveViewport = state.getCurrentViewport();
|
||||
|
||||
if (filtered.empty() || !bufferData.postprocessing)
|
||||
{
|
||||
|
@ -94,7 +131,7 @@ namespace MWRender
|
|||
state.pushStateSet(mFallbackStateSet);
|
||||
state.apply();
|
||||
state.applyTextureAttribute(0, bufferData.sceneTex);
|
||||
viewport->apply(state);
|
||||
resolveViewport->apply(state);
|
||||
|
||||
drawGeometry(renderInfo);
|
||||
state.popStateSet();
|
||||
|
@ -108,14 +145,30 @@ namespace MWRender
|
|||
for (auto& fbo : mFbos)
|
||||
{
|
||||
fbo = new osg::FrameBufferObject;
|
||||
fbo->setAttachment(osg::FrameBufferObject::BufferComponent::COLOR_BUFFER0, osg::FrameBufferAttachment(new osg::Texture2D(*bufferData.sceneTexLDR)));
|
||||
attachCloneOfTemplate(fbo, osg::FrameBufferObject::BufferComponent::COLOR_BUFFER0, bufferData.sceneTexLDR);
|
||||
fbo->apply(state);
|
||||
glClearColor(0.5, 0.5, 0.5, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
if (Stereo::getMultiview())
|
||||
{
|
||||
mMultiviewResolveFramebuffer = new osg::FrameBufferObject();
|
||||
attachCloneOfTemplate(mMultiviewResolveFramebuffer, osg::FrameBufferObject::BufferComponent::COLOR_BUFFER0, bufferData.sceneTexLDR);
|
||||
mMultiviewResolveFramebuffer->apply(state);
|
||||
glClearColor(0.5, 0.5, 0.5, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
mMultiviewResolveStateSet->setTextureAttribute(PostProcessor::Unit_LastShader, (osg::Texture*)mMultiviewResolveFramebuffer->getAttachment(osg::Camera::COLOR_BUFFER0).getTexture());
|
||||
}
|
||||
|
||||
mHDRDriver.dirty(bufferData.sceneTex->getTextureWidth(), bufferData.sceneTex->getTextureHeight());
|
||||
|
||||
if (Stereo::getStereo())
|
||||
mRenderViewport = new osg::Viewport(0, 0, bufferData.sceneTex->getTextureWidth(), bufferData.sceneTex->getTextureHeight());
|
||||
else
|
||||
mRenderViewport = nullptr;
|
||||
|
||||
bufferData.dirty = false;
|
||||
}
|
||||
|
||||
|
@ -148,6 +201,11 @@ namespace MWRender
|
|||
destinationFbo->apply(state, osg::FrameBufferObject::DRAW_FRAMEBUFFER);
|
||||
lastApplied = destinationHandle;
|
||||
}
|
||||
else if (Stereo::getMultiview())
|
||||
{
|
||||
mMultiviewResolveFramebuffer->apply(state, osg::FrameBufferObject::DRAW_FRAMEBUFFER);
|
||||
lastApplied = mMultiviewResolveFramebuffer->getHandle(cid);
|
||||
}
|
||||
else
|
||||
{
|
||||
ext->glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, 0);
|
||||
|
@ -173,19 +231,22 @@ namespace MWRender
|
|||
|
||||
for (size_t passIndex = 0; passIndex < node.mPasses.size(); ++passIndex)
|
||||
{
|
||||
if (mRenderViewport)
|
||||
mRenderViewport->apply(state);
|
||||
const auto& pass = node.mPasses[passIndex];
|
||||
|
||||
bool lastPass = passIndex == node.mPasses.size() - 1;
|
||||
|
||||
//VR-TODO: This won't actually work for tex2darrays
|
||||
if (lastShader == 0)
|
||||
pass.mStateSet->setTextureAttribute(PostProcessor::Unit_LastShader, bufferData.sceneTex);
|
||||
else
|
||||
pass.mStateSet->setTextureAttribute(PostProcessor::Unit_LastShader, (osg::Texture2D*)mFbos[lastShader - GL_COLOR_ATTACHMENT0_EXT]->getAttachment(osg::Camera::COLOR_BUFFER0).getTexture());
|
||||
pass.mStateSet->setTextureAttribute(PostProcessor::Unit_LastShader, (osg::Texture*)mFbos[lastShader - GL_COLOR_ATTACHMENT0_EXT]->getAttachment(osg::Camera::COLOR_BUFFER0).getTexture());
|
||||
|
||||
if (lastDraw == 0)
|
||||
pass.mStateSet->setTextureAttribute(PostProcessor::Unit_LastPass, bufferData.sceneTex);
|
||||
else
|
||||
pass.mStateSet->setTextureAttribute(PostProcessor::Unit_LastPass, (osg::Texture2D*)mFbos[lastDraw - GL_COLOR_ATTACHMENT0_EXT]->getAttachment(osg::Camera::COLOR_BUFFER0).getTexture());
|
||||
pass.mStateSet->setTextureAttribute(PostProcessor::Unit_LastPass, (osg::Texture*)mFbos[lastDraw - GL_COLOR_ATTACHMENT0_EXT]->getAttachment(osg::Camera::COLOR_BUFFER0).getTexture());
|
||||
|
||||
if (pass.mRenderTarget)
|
||||
{
|
||||
|
@ -203,6 +264,10 @@ namespace MWRender
|
|||
else if (pass.mResolve && index == filtered.back())
|
||||
{
|
||||
bindDestinationFbo();
|
||||
if (!destinationFbo && !Stereo::getMultiview())
|
||||
{
|
||||
resolveViewport->apply(state);
|
||||
}
|
||||
}
|
||||
else if (lastPass)
|
||||
{
|
||||
|
@ -237,6 +302,21 @@ namespace MWRender
|
|||
state.popStateSet();
|
||||
}
|
||||
|
||||
if (Stereo::getMultiview() && mMultiviewResolveProgram)
|
||||
{
|
||||
ext->glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, 0);
|
||||
lastApplied = 0;
|
||||
|
||||
resolveViewport->apply(state);
|
||||
state.pushStateSet(mMultiviewResolveStateSet);
|
||||
state.apply();
|
||||
|
||||
drawGeometry(renderInfo);
|
||||
|
||||
state.popStateSet();
|
||||
state.apply();
|
||||
}
|
||||
|
||||
if (lastApplied != destinationHandle)
|
||||
{
|
||||
bindDestinationFbo();
|
||||
|
|
|
@ -38,11 +38,11 @@ namespace MWRender
|
|||
|
||||
void setSceneTexture(size_t frameId, osg::ref_ptr<osg::Texture> tex) { mBufferData[frameId].sceneTex = tex; }
|
||||
|
||||
void setLDRSceneTexture(size_t frameId, osg::ref_ptr<osg::Texture2D> tex) { mBufferData[frameId].sceneTexLDR = tex; }
|
||||
void setLDRSceneTexture(size_t frameId, osg::ref_ptr<osg::Texture> tex) { mBufferData[frameId].sceneTexLDR = tex; }
|
||||
|
||||
void setDepthTexture(size_t frameId, osg::ref_ptr<osg::Texture> tex) { mBufferData[frameId].depthTex = tex; }
|
||||
|
||||
void setNormalsTexture(size_t frameId, osg::ref_ptr<osg::Texture2D> tex) { mBufferData[frameId].normalsTex = tex; }
|
||||
void setNormalsTexture(size_t frameId, osg::ref_ptr<osg::Texture> tex) { mBufferData[frameId].normalsTex = tex; }
|
||||
|
||||
void setHDR(size_t frameId, bool hdr) { mBufferData[frameId].hdr = hdr; }
|
||||
|
||||
|
@ -58,7 +58,10 @@ namespace MWRender
|
|||
mutable HDRDriver mHDRDriver;
|
||||
|
||||
osg::ref_ptr<osg::Program> mFallbackProgram;
|
||||
osg::ref_ptr<osg::Program> mMultiviewResolveProgram;
|
||||
osg::ref_ptr<osg::StateSet> mFallbackStateSet;
|
||||
osg::ref_ptr<osg::StateSet> mMultiviewResolveStateSet;
|
||||
mutable osg::ref_ptr<osg::FrameBufferObject> mMultiviewResolveFramebuffer;
|
||||
|
||||
struct BufferData
|
||||
{
|
||||
|
@ -73,12 +76,13 @@ namespace MWRender
|
|||
|
||||
osg::ref_ptr<osg::Texture> sceneTex;
|
||||
osg::ref_ptr<osg::Texture> depthTex;
|
||||
osg::ref_ptr<osg::Texture2D> sceneTexLDR;
|
||||
osg::ref_ptr<osg::Texture2D> normalsTex;
|
||||
osg::ref_ptr<osg::Texture> sceneTexLDR;
|
||||
osg::ref_ptr<osg::Texture> normalsTex;
|
||||
};
|
||||
|
||||
mutable std::array<BufferData, 2> mBufferData;
|
||||
mutable std::array<osg::ref_ptr<osg::FrameBufferObject>, 3> mFbos;
|
||||
mutable osg::ref_ptr<osg::Viewport> mRenderViewport;
|
||||
|
||||
mutable bool mLoggedLastError = false;
|
||||
};
|
||||
|
|
|
@ -4,11 +4,31 @@
|
|||
#include <osg/FrameBufferObject>
|
||||
#include <osgUtil/CullVisitor>
|
||||
|
||||
#include <components/stereo/stereomanager.hpp>
|
||||
#include <components/stereo/multiview.hpp>
|
||||
|
||||
#include "postprocessor.hpp"
|
||||
#include "pingpongcanvas.hpp"
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
PingPongCull::PingPongCull(PostProcessor* pp)
|
||||
: mViewportStateset(nullptr)
|
||||
, mPostProcessor(pp)
|
||||
{
|
||||
if (Stereo::getStereo())
|
||||
{
|
||||
mViewportStateset = new osg::StateSet();
|
||||
mViewport = new osg::Viewport(0, 0, pp->renderWidth(), pp->renderHeight());
|
||||
mViewportStateset->setAttribute(mViewport);
|
||||
}
|
||||
}
|
||||
|
||||
PingPongCull::~PingPongCull()
|
||||
{
|
||||
// Instantiate osg::ref_ptr<> destructor
|
||||
}
|
||||
|
||||
void PingPongCull::operator()(osg::Node* node, osgUtil::CullVisitor* cv)
|
||||
{
|
||||
osgUtil::RenderStage* renderStage = cv->getCurrentRenderStage();
|
||||
|
@ -17,10 +37,19 @@ namespace MWRender
|
|||
|
||||
MWRender::PostProcessor* postProcessor = dynamic_cast<MWRender::PostProcessor*>(cv->getCurrentCamera()->getUserData());
|
||||
|
||||
if (Stereo::getStereo())
|
||||
{
|
||||
auto& sm = Stereo::Manager::instance();
|
||||
auto view = sm.getEye(cv);
|
||||
int index = view == Stereo::Eye::Right ? 1 : 0;
|
||||
auto projectionMatrix = sm.computeEyeViewOffset(index) * sm.computeEyeProjection(index, true);
|
||||
postProcessor->getStateUpdater()->setProjectionMatrix(projectionMatrix);
|
||||
}
|
||||
|
||||
postProcessor->getStateUpdater()->setViewMatrix(cv->getCurrentCamera()->getViewMatrix());
|
||||
postProcessor->getStateUpdater()->setInvViewMatrix(cv->getCurrentCamera()->getInverseViewMatrix());
|
||||
postProcessor->getStateUpdater()->setPrevViewMatrix(mLastViewMatrix);
|
||||
mLastViewMatrix = cv->getCurrentCamera()->getViewMatrix();
|
||||
postProcessor->getStateUpdater()->setPrevViewMatrix(mLastViewMatrix[0]);
|
||||
mLastViewMatrix[0] = cv->getCurrentCamera()->getViewMatrix();
|
||||
|
||||
postProcessor->getStateUpdater()->setEyePos(cv->getEyePoint());
|
||||
postProcessor->getStateUpdater()->setEyeVec(cv->getLookVectorLocal());
|
||||
|
||||
|
@ -28,11 +57,8 @@ namespace MWRender
|
|||
{
|
||||
renderStage->setMultisampleResolveFramebufferObject(nullptr);
|
||||
renderStage->setFrameBufferObject(nullptr);
|
||||
traverse(node, cv);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!postProcessor->getFbo(PostProcessor::FBO_Multisample, frameId))
|
||||
else if (!postProcessor->getFbo(PostProcessor::FBO_Multisample, frameId))
|
||||
{
|
||||
renderStage->setFrameBufferObject(postProcessor->getFbo(PostProcessor::FBO_Primary, frameId));
|
||||
}
|
||||
|
@ -42,6 +68,15 @@ namespace MWRender
|
|||
renderStage->setFrameBufferObject(postProcessor->getFbo(PostProcessor::FBO_Multisample, frameId));
|
||||
}
|
||||
|
||||
traverse(node, cv);
|
||||
if (mViewportStateset)
|
||||
{
|
||||
mViewport->setViewport(0, 0, mPostProcessor->renderWidth(), mPostProcessor->renderHeight());
|
||||
renderStage->setViewport(mViewport);
|
||||
cv->pushStateSet(mViewportStateset.get());
|
||||
traverse(node, cv);
|
||||
cv->popStateSet();
|
||||
}
|
||||
else
|
||||
traverse(node, cv);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,15 +7,27 @@
|
|||
|
||||
#include "postprocessor.hpp"
|
||||
|
||||
namespace osg
|
||||
{
|
||||
class StateSet;
|
||||
class Viewport;
|
||||
}
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
class PostProcessor;
|
||||
class PingPongCull : public SceneUtil::NodeCallback<PingPongCull, osg::Node*, osgUtil::CullVisitor*>
|
||||
{
|
||||
public:
|
||||
PingPongCull(PostProcessor* pp);
|
||||
~PingPongCull();
|
||||
|
||||
void operator()(osg::Node* node, osgUtil::CullVisitor* nv);
|
||||
private:
|
||||
osg::Matrixf mLastViewMatrix;
|
||||
std::array<osg::Matrixf, 2> mLastViewMatrix;
|
||||
osg::ref_ptr<osg::StateSet> mViewportStateset;
|
||||
osg::ref_ptr<osg::Viewport> mViewport;
|
||||
PostProcessor* mPostProcessor;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -5,9 +5,14 @@
|
|||
|
||||
#include <osg/Texture1D>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/Texture2DMultisample>
|
||||
#include <osg/Texture3D>
|
||||
#include <osg/Texture2DArray>
|
||||
|
||||
#ifdef OSG_HAS_MULTIVIEW
|
||||
#include <osg/Texture2DMultisampleArray>
|
||||
#endif
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
#include <components/sceneutil/depth.hpp>
|
||||
#include <components/sceneutil/color.hpp>
|
||||
|
@ -66,9 +71,102 @@ namespace
|
|||
|
||||
cv->pushStateSet(stateset);
|
||||
traverse(camera, cv);
|
||||
cv->popViewport();
|
||||
cv->popStateSet();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static void setTextureSize(osg::Texture* tex, int w, int h)
|
||||
{
|
||||
switch (tex->getTextureTarget())
|
||||
{
|
||||
case GL_TEXTURE_2D:
|
||||
static_cast<osg::Texture2D*>(tex)->setTextureSize(w, h);
|
||||
break;
|
||||
case GL_TEXTURE_2D_ARRAY:
|
||||
static_cast<osg::Texture2DArray*>(tex)->setTextureSize(w, h, 2);
|
||||
break;
|
||||
default:
|
||||
throw std::logic_error("Invalid texture type received");
|
||||
}
|
||||
}
|
||||
|
||||
static void setAttachment(osg::FrameBufferObject* fbo, osg::Camera::BufferComponent component, osg::Texture* tex)
|
||||
{
|
||||
switch (tex->getTextureTarget())
|
||||
{
|
||||
case GL_TEXTURE_2D:
|
||||
{
|
||||
auto* tex2d = static_cast<osg::Texture2D*>(tex);
|
||||
fbo->setAttachment(component, osg::FrameBufferAttachment(tex2d));
|
||||
}
|
||||
break;
|
||||
case GL_TEXTURE_2D_ARRAY:
|
||||
{
|
||||
#ifdef OSG_HAS_MULTIVIEW
|
||||
auto* tex2dArray = static_cast<osg::Texture2DArray*>(tex);
|
||||
fbo->setAttachment(component, osg::FrameBufferAttachment(tex2dArray, osg::Camera::FACE_CONTROLLED_BY_MULTIVIEW_SHADER, 0));
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw std::logic_error("Invalid texture type received");
|
||||
}
|
||||
}
|
||||
|
||||
enum class Usage
|
||||
{
|
||||
RENDER_BUFFER,
|
||||
TEXTURE,
|
||||
};
|
||||
|
||||
static osg::FrameBufferAttachment createFrameBufferAttachmentFromTemplate(Usage usage, int width, int height, osg::Texture* template_, int samples)
|
||||
{
|
||||
if (usage == Usage::RENDER_BUFFER && !Stereo::getMultiview())
|
||||
{
|
||||
osg::ref_ptr<osg::RenderBuffer> attachment = new osg::RenderBuffer(width, height, template_->getInternalFormat(), samples);
|
||||
return osg::FrameBufferAttachment(attachment);
|
||||
}
|
||||
|
||||
osg::FrameBufferAttachment attachment;
|
||||
|
||||
#ifdef OSG_HAS_MULTIVIEW
|
||||
if (Stereo::getMultiview())
|
||||
{
|
||||
if (samples > 1)
|
||||
{
|
||||
attachment = osg::FrameBufferAttachment(new osg::Texture2DMultisampleArray(), osg::Camera::FACE_CONTROLLED_BY_MULTIVIEW_SHADER, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
attachment = osg::FrameBufferAttachment(new osg::Texture2DArray(), osg::Camera::FACE_CONTROLLED_BY_MULTIVIEW_SHADER, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (samples > 1)
|
||||
{
|
||||
attachment = osg::FrameBufferAttachment(new osg::Texture2DMultisample());
|
||||
}
|
||||
else
|
||||
{
|
||||
attachment = osg::FrameBufferAttachment(new osg::Texture2D());
|
||||
}
|
||||
}
|
||||
|
||||
osg::Texture* texture = attachment.getTexture();
|
||||
setTextureSize(texture, width, height);
|
||||
texture->setSourceFormat(template_->getSourceFormat());
|
||||
texture->setSourceType(template_->getSourceType());
|
||||
texture->setInternalFormat(template_->getInternalFormat());
|
||||
texture->setFilter(osg::Texture2D::MIN_FILTER, template_->getFilter(osg::Texture2D::MIN_FILTER));
|
||||
texture->setFilter(osg::Texture2D::MAG_FILTER, template_->getFilter(osg::Texture2D::MAG_FILTER));
|
||||
texture->setWrap(osg::Texture::WRAP_S, template_->getWrap(osg::Texture2D::WRAP_S));
|
||||
texture->setWrap(osg::Texture::WRAP_T, template_->getWrap(osg::Texture2D::WRAP_T));
|
||||
|
||||
return attachment;
|
||||
}
|
||||
}
|
||||
|
||||
namespace MWRender
|
||||
|
@ -99,7 +197,7 @@ namespace MWRender
|
|||
, mPrevPassLights(false)
|
||||
, mMainTemplate(new osg::Texture2D)
|
||||
{
|
||||
mSoftParticles = Settings::Manager::getBool("soft particles", "Shaders") && !Stereo::getStereo() && !Stereo::getMultiview();
|
||||
mSoftParticles = Settings::Manager::getBool("soft particles", "Shaders");
|
||||
mUsePostProcessing = Settings::Manager::getBool("enabled", "Post Processing");
|
||||
|
||||
osg::GraphicsContext* gc = viewer->getCamera()->getGraphicsContext();
|
||||
|
@ -121,14 +219,21 @@ namespace MWRender
|
|||
Log(Debug::Error) << "'glDisablei' unsupported, pass normals will not be available to shaders.";
|
||||
|
||||
if (mSoftParticles)
|
||||
{
|
||||
for (int i = 0; i < 2; ++i)
|
||||
mTextures[i][Tex_OpaqueDepth] = new osg::Texture2D;
|
||||
{
|
||||
if (Stereo::getMultiview())
|
||||
mTextures[i][Tex_OpaqueDepth] = new osg::Texture2DArray;
|
||||
else
|
||||
mTextures[i][Tex_OpaqueDepth] = new osg::Texture2D;
|
||||
}
|
||||
}
|
||||
|
||||
mGLSLVersion = ext->glslLanguageVersion * 100;
|
||||
mUBO = ext && ext->isUniformBufferObjectSupported && mGLSLVersion >= 330;
|
||||
mStateUpdater = new fx::StateUpdater(mUBO);
|
||||
|
||||
if (!SceneUtil::AutoDepth::isReversed() && !mSoftParticles && !mUsePostProcessing && !Stereo::getStereo() && !Stereo::getMultiview())
|
||||
if (!SceneUtil::AutoDepth::isReversed() && !mSoftParticles && !mUsePostProcessing)
|
||||
return;
|
||||
|
||||
enable(mUsePostProcessing);
|
||||
|
@ -142,11 +247,18 @@ namespace MWRender
|
|||
|
||||
void PostProcessor::resize()
|
||||
{
|
||||
mHUDCamera->resize(mWidth, mHeight);
|
||||
mViewer->getCamera()->resize(mWidth, mHeight);
|
||||
if (Stereo::getStereo())
|
||||
Stereo::Manager::instance().screenResolutionChanged();
|
||||
|
||||
auto width = renderWidth();
|
||||
auto height = renderHeight();
|
||||
for (auto& technique : mTechniques)
|
||||
{
|
||||
for (auto& [name, rt] : technique->getRenderTargetsMap())
|
||||
{
|
||||
const auto [w, h] = rt.mSize.get(mWidth, mHeight);
|
||||
const auto [w, h] = rt.mSize.get(width, height);
|
||||
rt.mTarget->setTextureSize(w, h);
|
||||
}
|
||||
}
|
||||
|
@ -156,10 +268,8 @@ namespace MWRender
|
|||
createTexturesAndCamera(frameId);
|
||||
createObjectsForFrame(frameId);
|
||||
|
||||
mHUDCamera->resize(mWidth, mHeight);
|
||||
mViewer->getCamera()->resize(mWidth, mHeight);
|
||||
mRendering.updateProjectionMatrix();
|
||||
mRendering.setScreenRes(mWidth, mHeight);
|
||||
mRendering.setScreenRes(width, height);
|
||||
|
||||
dirtyTechniques();
|
||||
|
||||
|
@ -168,8 +278,6 @@ namespace MWRender
|
|||
mDirty = true;
|
||||
mDirtyFrameId = !frameId;
|
||||
|
||||
if (Stereo::getStereo())
|
||||
Stereo::Manager::instance().screenResolutionChanged();
|
||||
}
|
||||
|
||||
void PostProcessor::populateTechniqueFiles()
|
||||
|
@ -191,7 +299,7 @@ namespace MWRender
|
|||
mReload = true;
|
||||
mEnabled = true;
|
||||
bool postPass = Settings::Manager::getBool("transparent postpass", "Post Processing");
|
||||
mUsePostProcessing = usePostProcessing && !Stereo::getStereo() && !Stereo::getMultiview();
|
||||
mUsePostProcessing = usePostProcessing;
|
||||
|
||||
mDisableDepthPasses = !mSoftParticles && !postPass;
|
||||
|
||||
|
@ -199,7 +307,7 @@ namespace MWRender
|
|||
mDisableDepthPasses = true;
|
||||
#endif
|
||||
|
||||
if (!mDisableDepthPasses && !Stereo::getStereo() && !Stereo::getMultiview())
|
||||
if (!mDisableDepthPasses)
|
||||
{
|
||||
mTransparentDepthPostPass = new TransparentDepthBinCallback(mRendering.getResourceSystem()->getSceneManager()->getShaderManager(), postPass);
|
||||
osgUtil::RenderBin::getRenderBinPrototype("DepthSortedBin")->setDrawCallback(mTransparentDepthPostPass);
|
||||
|
@ -240,7 +348,7 @@ namespace MWRender
|
|||
if (!mSoftParticles)
|
||||
osgUtil::RenderBin::getRenderBinPrototype("DepthSortedBin")->setDrawCallback(nullptr);
|
||||
|
||||
if (!SceneUtil::AutoDepth::isReversed() && !mSoftParticles && !Stereo::getStereo() && !Stereo::getMultiview())
|
||||
if (!SceneUtil::AutoDepth::isReversed() && !mSoftParticles)
|
||||
{
|
||||
removeChild(mHUDCamera);
|
||||
setCullCallback(nullptr);
|
||||
|
@ -289,25 +397,7 @@ namespace MWRender
|
|||
mPingPongCanvas->setMask(frameId, mUnderwater, mExteriorFlag);
|
||||
mPingPongCanvas->setHDR(frameId, getHDR());
|
||||
|
||||
if (Stereo::getStereo())
|
||||
{
|
||||
auto& sm = Stereo::Manager::instance();
|
||||
|
||||
int index = sm.getEye(cv) == Stereo::Eye::Left ? 0 : 1;
|
||||
|
||||
mPingPongCanvas->setSceneTexture(frameId, sm.multiviewFramebuffer()->layerColorBuffer(index));
|
||||
mPingPongCanvas->setDepthTexture(frameId, sm.multiviewFramebuffer()->layerDepthBuffer(index));
|
||||
}
|
||||
else if (Stereo::getMultiview())
|
||||
{
|
||||
auto& sm = Stereo::Manager::instance();
|
||||
|
||||
mPingPongCanvas->setSceneTexture(frameId, sm.multiviewFramebuffer()->multiviewColorBuffer());
|
||||
mPingPongCanvas->setDepthTexture(frameId, sm.multiviewFramebuffer()->multiviewDepthBuffer());
|
||||
}
|
||||
else
|
||||
{
|
||||
mPingPongCanvas->setSceneTexture(frameId, getTexture(Tex_Scene, frameId));
|
||||
mPingPongCanvas->setSceneTexture(frameId, getTexture(Tex_Scene, frameId));
|
||||
if (mDisableDepthPasses)
|
||||
mPingPongCanvas->setDepthTexture(frameId, getTexture(Tex_Depth, frameId));
|
||||
else
|
||||
|
@ -315,12 +405,12 @@ namespace MWRender
|
|||
|
||||
mPingPongCanvas->setLDRSceneTexture(frameId, getTexture(Tex_Scene_LDR, frameId));
|
||||
|
||||
if (mTransparentDepthPostPass)
|
||||
{
|
||||
mTransparentDepthPostPass->mFbo[frameId] = mFbos[frameId][FBO_Primary];
|
||||
mTransparentDepthPostPass->mMsaaFbo[frameId] = mFbos[frameId][FBO_Multisample];
|
||||
mTransparentDepthPostPass->mOpaqueFbo[frameId] = mFbos[frameId][FBO_OpaqueDepth];
|
||||
}
|
||||
if (mTransparentDepthPostPass)
|
||||
{
|
||||
mTransparentDepthPostPass->mFbo[frameId] = mFbos[frameId][FBO_Primary];
|
||||
mTransparentDepthPostPass->mMsaaFbo[frameId] = mFbos[frameId][FBO_Multisample];
|
||||
mTransparentDepthPostPass->mOpaqueFbo[frameId] = mFbos[frameId][FBO_OpaqueDepth];
|
||||
mTransparentDepthPostPass->dirtyFrame(frameId);
|
||||
}
|
||||
|
||||
size_t frame = cv->getTraversalNumber();
|
||||
|
@ -331,7 +421,6 @@ namespace MWRender
|
|||
if (frame != mLastFrameNumber)
|
||||
{
|
||||
mLastFrameNumber = frame;
|
||||
|
||||
auto stamp = cv->getFrameStamp();
|
||||
|
||||
mStateUpdater->setSimulationTime(static_cast<float>(stamp->getSimulationTime()));
|
||||
|
@ -440,29 +529,29 @@ namespace MWRender
|
|||
|
||||
void PostProcessor::createObjectsForFrame(size_t frameId)
|
||||
{
|
||||
if (Stereo::getStereo() || Stereo::getMultiview())
|
||||
return;
|
||||
|
||||
auto& fbos = mFbos[frameId];
|
||||
auto& textures = mTextures[frameId];
|
||||
auto width = renderWidth();
|
||||
auto height = renderHeight();
|
||||
|
||||
for (auto& tex : textures)
|
||||
{
|
||||
if (!tex)
|
||||
continue;
|
||||
|
||||
tex->setTextureSize(mWidth, mHeight);
|
||||
setTextureSize(tex, width, height);
|
||||
tex->dirtyTextureObject();
|
||||
}
|
||||
|
||||
fbos[FBO_Primary] = new osg::FrameBufferObject;
|
||||
fbos[FBO_Primary]->setAttachment(osg::Camera::COLOR_BUFFER0, osg::FrameBufferAttachment(textures[Tex_Scene]));
|
||||
setAttachment(fbos[FBO_Primary], osg::Camera::COLOR_BUFFER0, textures[Tex_Scene]);
|
||||
if (mNormals && mNormalsSupported)
|
||||
fbos[FBO_Primary]->setAttachment(osg::Camera::COLOR_BUFFER1, osg::FrameBufferAttachment(textures[Tex_Normal]));
|
||||
fbos[FBO_Primary]->setAttachment(osg::Camera::PACKED_DEPTH_STENCIL_BUFFER, osg::FrameBufferAttachment(textures[Tex_Depth]));
|
||||
setAttachment(fbos[FBO_Primary], osg::Camera::COLOR_BUFFER1, textures[Tex_Normal]);
|
||||
setAttachment(fbos[FBO_Primary], osg::Camera::PACKED_DEPTH_STENCIL_BUFFER, textures[Tex_Depth]);
|
||||
|
||||
fbos[FBO_FirstPerson] = new osg::FrameBufferObject;
|
||||
osg::ref_ptr<osg::RenderBuffer> fpDepthRb = new osg::RenderBuffer(mWidth, mHeight, textures[Tex_Depth]->getInternalFormat(), mSamples > 1 ? mSamples : 0);
|
||||
|
||||
auto fpDepthRb = createFrameBufferAttachmentFromTemplate(Usage::RENDER_BUFFER, width, height, textures[Tex_Depth], mSamples);
|
||||
fbos[FBO_FirstPerson]->setAttachment(osg::FrameBufferObject::BufferComponent::PACKED_DEPTH_STENCIL_BUFFER, osg::FrameBufferAttachment(fpDepthRb));
|
||||
|
||||
// When MSAA is enabled we must first render to a render buffer, then
|
||||
|
@ -471,33 +560,33 @@ namespace MWRender
|
|||
if (mSamples > 1)
|
||||
{
|
||||
fbos[FBO_Multisample] = new osg::FrameBufferObject;
|
||||
osg::ref_ptr<osg::RenderBuffer> colorRB = new osg::RenderBuffer(mWidth, mHeight, textures[Tex_Scene]->getInternalFormat(), mSamples);
|
||||
auto colorRB = createFrameBufferAttachmentFromTemplate(Usage::RENDER_BUFFER, width, height, textures[Tex_Scene], mSamples);
|
||||
if (mNormals && mNormalsSupported)
|
||||
{
|
||||
osg::ref_ptr<osg::RenderBuffer> normalRB = new osg::RenderBuffer(mWidth, mHeight, textures[Tex_Normal]->getInternalFormat(), mSamples);
|
||||
fbos[FBO_Multisample]->setAttachment(osg::FrameBufferObject::BufferComponent::COLOR_BUFFER1, osg::FrameBufferAttachment(normalRB));
|
||||
fbos[FBO_FirstPerson]->setAttachment(osg::FrameBufferObject::BufferComponent::COLOR_BUFFER1, osg::FrameBufferAttachment(normalRB));
|
||||
auto normalRB = createFrameBufferAttachmentFromTemplate(Usage::RENDER_BUFFER, width, height, textures[Tex_Normal], mSamples);
|
||||
fbos[FBO_Multisample]->setAttachment(osg::FrameBufferObject::BufferComponent::COLOR_BUFFER1, normalRB);
|
||||
fbos[FBO_FirstPerson]->setAttachment(osg::FrameBufferObject::BufferComponent::COLOR_BUFFER1, normalRB);
|
||||
}
|
||||
osg::ref_ptr<osg::RenderBuffer> depthRB = new osg::RenderBuffer(mWidth, mHeight, textures[Tex_Depth]->getInternalFormat(), mSamples);
|
||||
fbos[FBO_Multisample]->setAttachment(osg::FrameBufferObject::BufferComponent::COLOR_BUFFER0, osg::FrameBufferAttachment(colorRB));
|
||||
fbos[FBO_Multisample]->setAttachment(osg::FrameBufferObject::BufferComponent::PACKED_DEPTH_STENCIL_BUFFER, osg::FrameBufferAttachment(depthRB));
|
||||
fbos[FBO_FirstPerson]->setAttachment(osg::FrameBufferObject::BufferComponent::COLOR_BUFFER0, osg::FrameBufferAttachment(colorRB));
|
||||
auto depthRB = createFrameBufferAttachmentFromTemplate(Usage::RENDER_BUFFER, width, height, textures[Tex_Depth], mSamples);
|
||||
fbos[FBO_Multisample]->setAttachment(osg::FrameBufferObject::BufferComponent::COLOR_BUFFER0, colorRB);
|
||||
fbos[FBO_Multisample]->setAttachment(osg::FrameBufferObject::BufferComponent::PACKED_DEPTH_STENCIL_BUFFER, depthRB);
|
||||
fbos[FBO_FirstPerson]->setAttachment(osg::FrameBufferObject::BufferComponent::COLOR_BUFFER0, colorRB);
|
||||
|
||||
fbos[FBO_Intercept] = new osg::FrameBufferObject;
|
||||
fbos[FBO_Intercept]->setAttachment(osg::FrameBufferObject::BufferComponent::COLOR_BUFFER0, osg::FrameBufferAttachment(textures[Tex_Scene]));
|
||||
fbos[FBO_Intercept]->setAttachment(osg::FrameBufferObject::BufferComponent::COLOR_BUFFER1, osg::FrameBufferAttachment(textures[Tex_Normal]));
|
||||
setAttachment(fbos[FBO_Intercept], osg::FrameBufferObject::BufferComponent::COLOR_BUFFER0, textures[Tex_Scene]);
|
||||
setAttachment(fbos[FBO_Intercept], osg::FrameBufferObject::BufferComponent::COLOR_BUFFER1, textures[Tex_Normal]);
|
||||
}
|
||||
else
|
||||
{
|
||||
fbos[FBO_FirstPerson]->setAttachment(osg::FrameBufferObject::BufferComponent::COLOR_BUFFER0, osg::FrameBufferAttachment(textures[Tex_Scene]));
|
||||
setAttachment(fbos[FBO_FirstPerson], osg::FrameBufferObject::BufferComponent::COLOR_BUFFER0, textures[Tex_Scene]);
|
||||
if (mNormals && mNormalsSupported)
|
||||
fbos[FBO_FirstPerson]->setAttachment(osg::FrameBufferObject::BufferComponent::COLOR_BUFFER1, osg::FrameBufferAttachment(textures[Tex_Normal]));
|
||||
setAttachment(fbos[FBO_FirstPerson], osg::FrameBufferObject::BufferComponent::COLOR_BUFFER1, textures[Tex_Normal]);
|
||||
}
|
||||
|
||||
if (textures[Tex_OpaqueDepth])
|
||||
{
|
||||
fbos[FBO_OpaqueDepth] = new osg::FrameBufferObject;
|
||||
fbos[FBO_OpaqueDepth]->setAttachment(osg::FrameBufferObject::BufferComponent::PACKED_DEPTH_STENCIL_BUFFER, osg::FrameBufferAttachment(textures[Tex_OpaqueDepth]));
|
||||
setAttachment(fbos[FBO_OpaqueDepth], osg::FrameBufferObject::BufferComponent::PACKED_DEPTH_STENCIL_BUFFER, textures[Tex_OpaqueDepth]);
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
@ -600,7 +689,7 @@ namespace MWRender
|
|||
{
|
||||
const auto& rt = technique->getRenderTargetsMap()[pass->getTarget()];
|
||||
|
||||
const auto [w, h] = rt.mSize.get(mWidth, mHeight);
|
||||
const auto [w, h] = rt.mSize.get(renderWidth(), renderHeight());
|
||||
|
||||
subPass.mRenderTexture = new osg::Texture2D(*rt.mTarget);
|
||||
renderTargetCache[rt.mTarget] = subPass.mRenderTexture;
|
||||
|
@ -690,11 +779,19 @@ namespace MWRender
|
|||
{
|
||||
auto& textures = mTextures[frameId];
|
||||
|
||||
auto width = renderWidth();
|
||||
auto height = renderHeight();
|
||||
|
||||
for (auto& texture : textures)
|
||||
{
|
||||
if (!texture)
|
||||
texture = new osg::Texture2D;
|
||||
texture->setTextureSize(mWidth, mHeight);
|
||||
{
|
||||
if (Stereo::getMultiview())
|
||||
texture = new osg::Texture2DArray;
|
||||
else
|
||||
texture = new osg::Texture2D;
|
||||
}
|
||||
setTextureSize(texture, width, height);
|
||||
texture->setSourceFormat(GL_RGBA);
|
||||
texture->setSourceType(GL_UNSIGNED_BYTE);
|
||||
texture->setInternalFormat(GL_RGBA);
|
||||
|
@ -719,7 +816,7 @@ namespace MWRender
|
|||
textures[Tex_Scene]->setWrap(osg::Texture::WRAP_T, mMainTemplate->getWrap(osg::Texture2D::WRAP_T));
|
||||
}
|
||||
|
||||
auto setupDepth = [] (osg::Texture2D* tex) {
|
||||
auto setupDepth = [] (osg::Texture* tex) {
|
||||
tex->setSourceFormat(GL_DEPTH_STENCIL_EXT);
|
||||
tex->setSourceType(SceneUtil::AutoDepth::depthSourceType());
|
||||
tex->setInternalFormat(SceneUtil::AutoDepth::depthInternalFormat());
|
||||
|
@ -750,11 +847,10 @@ namespace MWRender
|
|||
mHUDCamera->setViewport(0, 0, mWidth, mHeight);
|
||||
|
||||
mViewer->getCamera()->removeCullCallback(mPingPongCull);
|
||||
mPingPongCull = new PingPongCull;
|
||||
mPingPongCull = new PingPongCull(this);
|
||||
mViewer->getCamera()->addCullCallback(mPingPongCull);
|
||||
|
||||
mPingPongCanvas = new PingPongCanvas(mRendering.getResourceSystem()->getSceneManager()->getShaderManager());
|
||||
|
||||
mHUDCamera->addChild(mPingPongCanvas);
|
||||
mHUDCamera->setNodeMask(Mask_RenderToTexture);
|
||||
|
||||
|
@ -778,7 +874,7 @@ namespace MWRender
|
|||
if (Misc::StringUtils::ciEqual(technique->getName(), name))
|
||||
return technique;
|
||||
|
||||
auto technique = std::make_shared<fx::Technique>(*mVFS, *mRendering.getResourceSystem()->getImageManager(), name, mWidth, mHeight, mUBO, mNormalsSupported);
|
||||
auto technique = std::make_shared<fx::Technique>(*mVFS, *mRendering.getResourceSystem()->getImageManager(), name, renderWidth(), renderHeight(), mUBO, mNormalsSupported);
|
||||
|
||||
technique->compile();
|
||||
|
||||
|
@ -854,5 +950,19 @@ namespace MWRender
|
|||
if (technique->getDynamic())
|
||||
disableTechnique(technique);
|
||||
}
|
||||
|
||||
int PostProcessor::renderWidth() const
|
||||
{
|
||||
if (Stereo::getStereo())
|
||||
return Stereo::Manager::instance().eyeResolution().x();
|
||||
return mWidth;
|
||||
}
|
||||
|
||||
int PostProcessor::renderHeight() const
|
||||
{
|
||||
if (Stereo::getStereo())
|
||||
return Stereo::Manager::instance().eyeResolution().y();
|
||||
return mHeight;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ namespace MWRender
|
|||
{
|
||||
public:
|
||||
using FBOArray = std::array<osg::ref_ptr<osg::FrameBufferObject>, 5>;
|
||||
using TextureArray = std::array<osg::ref_ptr<osg::Texture2D>, 5>;
|
||||
using TextureArray = std::array<osg::ref_ptr<osg::Texture>, 5>;
|
||||
using TechniqueList = std::vector<std::shared_ptr<fx::Technique>>;
|
||||
|
||||
enum TextureIndex
|
||||
|
@ -94,7 +94,7 @@ namespace MWRender
|
|||
|
||||
osg::ref_ptr<osg::FrameBufferObject> getFbo(FBOIndex index, unsigned int frameId) { return mFbos[frameId][index]; }
|
||||
|
||||
osg::ref_ptr<osg::Texture2D> getTexture(TextureIndex index, unsigned int frameId) { return mTextures[frameId][index]; }
|
||||
osg::ref_ptr<osg::Texture> getTexture(TextureIndex index, unsigned int frameId) { return mTextures[frameId][index]; }
|
||||
|
||||
osg::ref_ptr<osg::FrameBufferObject> getPrimaryFbo(unsigned int frameId) { return mFbos[frameId][FBO_Multisample] ? mFbos[frameId][FBO_Multisample] : mFbos[frameId][FBO_Primary]; }
|
||||
|
||||
|
@ -177,6 +177,9 @@ namespace MWRender
|
|||
|
||||
void disableDynamicShaders();
|
||||
|
||||
int renderWidth() const;
|
||||
int renderHeight() const;
|
||||
|
||||
private:
|
||||
|
||||
void populateTechniqueFiles();
|
||||
|
@ -242,7 +245,7 @@ namespace MWRender
|
|||
bool mUBO;
|
||||
int mGLSLVersion;
|
||||
|
||||
osg::ref_ptr<osg::Texture2D> mMainTemplate;
|
||||
osg::ref_ptr<osg::Texture> mMainTemplate;
|
||||
|
||||
osg::ref_ptr<fx::StateUpdater> mStateUpdater;
|
||||
osg::ref_ptr<PingPongCull> mPingPongCull;
|
||||
|
|
|
@ -110,14 +110,14 @@ namespace MWRender
|
|||
{
|
||||
auto* uProjectionMatrix = stateset->getUniform("projectionMatrix");
|
||||
if (uProjectionMatrix)
|
||||
uProjectionMatrix->set(Stereo::Manager::instance().computeEyeProjection(0, SceneUtil::AutoDepth::isReversed()));
|
||||
uProjectionMatrix->set(Stereo::Manager::instance().computeEyeViewOffset(0) * Stereo::Manager::instance().computeEyeProjection(0, SceneUtil::AutoDepth::isReversed()));
|
||||
}
|
||||
|
||||
void applyRight(osg::StateSet* stateset, osgUtil::CullVisitor* nv) override
|
||||
{
|
||||
auto* uProjectionMatrix = stateset->getUniform("projectionMatrix");
|
||||
if (uProjectionMatrix)
|
||||
uProjectionMatrix->set(Stereo::Manager::instance().computeEyeProjection(1, SceneUtil::AutoDepth::isReversed()));
|
||||
uProjectionMatrix->set(Stereo::Manager::instance().computeEyeViewOffset(1) * Stereo::Manager::instance().computeEyeProjection(1, SceneUtil::AutoDepth::isReversed()));
|
||||
}
|
||||
|
||||
void setProjectionMatrix(const osg::Matrixf& projectionMatrix)
|
||||
|
|
|
@ -109,9 +109,7 @@ namespace MWRender
|
|||
size_t frameId = renderInfo.getState()->getFrameStamp()->getFrameNumber() % 2;
|
||||
osg::FrameBufferObject* fbo = nullptr;
|
||||
|
||||
if (Stereo::getStereo())
|
||||
fbo = Stereo::Manager::instance().multiviewFramebuffer()->layerFbo(0);
|
||||
else if (postProcessor && postProcessor->getFbo(PostProcessor::FBO_Primary, frameId))
|
||||
if (postProcessor && postProcessor->getFbo(PostProcessor::FBO_Primary, frameId))
|
||||
fbo = postProcessor->getFbo(PostProcessor::FBO_Primary, frameId);
|
||||
|
||||
if (fbo)
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include <components/misc/rng.hpp>
|
||||
#include <components/stereo/stereomanager.hpp>
|
||||
#include <components/stereo/multiview.hpp>
|
||||
|
||||
#include <components/resource/scenemanager.hpp>
|
||||
#include <components/resource/imagemanager.hpp>
|
||||
|
@ -604,33 +605,63 @@ namespace MWRender
|
|||
}
|
||||
|
||||
|
||||
class SkyMultiviewStatesetUpdater: public SceneUtil::StateSetUpdater
|
||||
class SkyStereoStatesetUpdater : public SceneUtil::StateSetUpdater
|
||||
{
|
||||
public:
|
||||
SkyMultiviewStatesetUpdater()
|
||||
SkyStereoStatesetUpdater()
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void setDefaults(osg::StateSet* stateset)
|
||||
void setDefaults(osg::StateSet* stateset) override
|
||||
{
|
||||
stateset->addUniform(new osg::Uniform(osg::Uniform::FLOAT_MAT4, "viewMatrixMultiView", 2), osg::StateAttribute::OVERRIDE);
|
||||
if (Stereo::getMultiview())
|
||||
stateset->addUniform(new osg::Uniform(osg::Uniform::FLOAT_MAT4, "projectionMatrixMultiView", 2), osg::StateAttribute::OVERRIDE);
|
||||
else
|
||||
stateset->addUniform(new osg::Uniform(osg::Uniform::FLOAT_MAT4, "projectionMatrix"), osg::StateAttribute::OVERRIDE);
|
||||
|
||||
}
|
||||
|
||||
virtual void apply(osg::StateSet* stateset, osg::NodeVisitor* /*nv*/)
|
||||
void apply(osg::StateSet* stateset, osg::NodeVisitor* /*nv*/) override
|
||||
{
|
||||
auto* viewMatrixMultiViewUniform = stateset->getUniform("viewMatrixMultiView");
|
||||
auto& sm = Stereo::Manager::instance();
|
||||
|
||||
for (int view : {0, 1})
|
||||
if (Stereo::getMultiview())
|
||||
{
|
||||
auto viewOffsetMatrix = sm.computeEyeViewOffset(view);
|
||||
for (int col : {0, 1, 2})
|
||||
viewOffsetMatrix(3, col) = 0;
|
||||
auto* projectionMatrixMultiViewUniform = stateset->getUniform("projectionMatrixMultiView");
|
||||
auto& sm = Stereo::Manager::instance();
|
||||
|
||||
viewMatrixMultiViewUniform->setElement(view, viewOffsetMatrix);
|
||||
for (int view : {0, 1})
|
||||
{
|
||||
auto projectionMatrix = sm.computeEyeProjection(view, true);
|
||||
auto viewOffsetMatrix = sm.computeEyeViewOffset(view);
|
||||
for (int col : {0, 1, 2})
|
||||
viewOffsetMatrix(3, col) = 0;
|
||||
|
||||
projectionMatrixMultiViewUniform->setElement(view, viewOffsetMatrix * projectionMatrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
void applyLeft(osg::StateSet* stateset, osgUtil::CullVisitor* /*cv*/) override
|
||||
{
|
||||
auto& sm = Stereo::Manager::instance();
|
||||
auto* projectionMatrixUniform = stateset->getUniform("projectionMatrix");
|
||||
auto projectionMatrix = sm.computeEyeProjection(0, true);
|
||||
auto viewOffsetMatrix = sm.computeEyeViewOffset(0);
|
||||
for (int col : {0, 1, 2})
|
||||
viewOffsetMatrix(3, col) = 0;
|
||||
|
||||
projectionMatrixUniform->set(viewOffsetMatrix * projectionMatrix);
|
||||
}
|
||||
void applyRight(osg::StateSet* stateset, osgUtil::CullVisitor* /*cv*/) override
|
||||
{
|
||||
auto& sm = Stereo::Manager::instance();
|
||||
auto* projectionMatrixUniform = stateset->getUniform("projectionMatrix");
|
||||
auto projectionMatrix = sm.computeEyeProjection(1, true);
|
||||
auto viewOffsetMatrix = sm.computeEyeViewOffset(1);
|
||||
for (int col : {0, 1, 2})
|
||||
viewOffsetMatrix(3, col) = 0;
|
||||
|
||||
projectionMatrixUniform->set(viewOffsetMatrix * projectionMatrix);
|
||||
}
|
||||
|
||||
private:
|
||||
};
|
||||
|
@ -643,7 +674,8 @@ namespace MWRender
|
|||
setCullingActive(false);
|
||||
|
||||
addCullCallback(new CameraRelativeTransformCullCallback);
|
||||
addCullCallback(new SkyMultiviewStatesetUpdater);
|
||||
if (Stereo::getStereo())
|
||||
addCullCallback(new SkyStereoStatesetUpdater);
|
||||
}
|
||||
|
||||
CameraRelativeTransform::CameraRelativeTransform(const CameraRelativeTransform& copy, const osg::CopyOp& copyop)
|
||||
|
|
|
@ -2,10 +2,17 @@
|
|||
|
||||
#include <osg/BlendFunc>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/Texture2DArray>
|
||||
|
||||
#ifdef OSG_HAS_MULTIVIEW
|
||||
#include <osg/Texture2DMultisampleArray>
|
||||
#endif
|
||||
|
||||
#include <osgUtil/RenderStage>
|
||||
|
||||
#include <components/shader/shadermanager.hpp>
|
||||
#include <components/stereo/multiview.hpp>
|
||||
#include <components/stereo/stereomanager.hpp>
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
|
@ -24,8 +31,10 @@ namespace MWRender
|
|||
|
||||
mStateSet->setTextureAttributeAndModes(0, dummyTexture);
|
||||
|
||||
osg::ref_ptr<osg::Shader> vertex = shaderManager.getShader("blended_depth_postpass_vertex.glsl", {}, osg::Shader::VERTEX);
|
||||
osg::ref_ptr<osg::Shader> fragment = shaderManager.getShader("blended_depth_postpass_fragment.glsl", {}, osg::Shader::FRAGMENT);
|
||||
Shader::ShaderManager::DefineMap defines;
|
||||
Stereo::Manager::instance().shaderStereoDefines(defines);
|
||||
osg::ref_ptr<osg::Shader> vertex = shaderManager.getShader("blended_depth_postpass_vertex.glsl", defines, osg::Shader::VERTEX);
|
||||
osg::ref_ptr<osg::Shader> fragment = shaderManager.getShader("blended_depth_postpass_fragment.glsl", defines, osg::Shader::FRAGMENT);
|
||||
|
||||
mStateSet->setAttributeAndModes(new osg::BlendFunc, modeOff);
|
||||
mStateSet->setAttributeAndModes(shaderManager.getProgram(vertex, fragment), modeOn);
|
||||
|
@ -59,9 +68,22 @@ namespace MWRender
|
|||
|
||||
const osg::Texture* tex = opaqueFbo->getAttachment(osg::FrameBufferObject::BufferComponent::PACKED_DEPTH_STENCIL_BUFFER).getTexture();
|
||||
|
||||
opaqueFbo->apply(state, osg::FrameBufferObject::DRAW_FRAMEBUFFER);
|
||||
|
||||
ext->glBlitFramebuffer(0, 0, tex->getTextureWidth(), tex->getTextureHeight(), 0, 0, tex->getTextureWidth(), tex->getTextureHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
|
||||
if (Stereo::getMultiview())
|
||||
{
|
||||
if (!mMultiviewDepthResolveLeftSource[frameId])
|
||||
setupMultiviewDepthResolveBuffers(frameId);
|
||||
mMultiviewDepthResolveLeftTarget[frameId]->apply(state, osg::FrameBufferObject::BindTarget::DRAW_FRAMEBUFFER);
|
||||
mMultiviewDepthResolveLeftSource[frameId]->apply(state, osg::FrameBufferObject::BindTarget::READ_FRAMEBUFFER);
|
||||
ext->glBlitFramebuffer(0, 0, tex->getTextureWidth(), tex->getTextureHeight(), 0, 0, tex->getTextureWidth(), tex->getTextureHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
|
||||
mMultiviewDepthResolveRightTarget[frameId]->apply(state, osg::FrameBufferObject::BindTarget::DRAW_FRAMEBUFFER);
|
||||
mMultiviewDepthResolveRightSource[frameId]->apply(state, osg::FrameBufferObject::BindTarget::READ_FRAMEBUFFER);
|
||||
ext->glBlitFramebuffer(0, 0, tex->getTextureWidth(), tex->getTextureHeight(), 0, 0, tex->getTextureWidth(), tex->getTextureHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
|
||||
}
|
||||
else
|
||||
{
|
||||
opaqueFbo->apply(state, osg::FrameBufferObject::DRAW_FRAMEBUFFER);
|
||||
ext->glBlitFramebuffer(0, 0, tex->getTextureWidth(), tex->getTextureHeight(), 0, 0, tex->getTextureWidth(), tex->getTextureHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
|
||||
}
|
||||
|
||||
msaaFbo ? msaaFbo->apply(state, osg::FrameBufferObject::DRAW_FRAMEBUFFER) : fbo->apply(state, osg::FrameBufferObject::DRAW_FRAMEBUFFER);
|
||||
|
||||
|
@ -80,6 +102,47 @@ namespace MWRender
|
|||
bin->setStateSet(restore);
|
||||
|
||||
msaaFbo ? msaaFbo->apply(state, osg::FrameBufferObject::DRAW_FRAMEBUFFER) : fbo->apply(state, osg::FrameBufferObject::DRAW_FRAMEBUFFER);
|
||||
state.checkGLErrors("after TransparentDepthBinCallback::drawImplementation");
|
||||
}
|
||||
|
||||
void TransparentDepthBinCallback::dirtyFrame(int frameId)
|
||||
{
|
||||
mMultiviewDepthResolveLeftSource[frameId] = mMultiviewDepthResolveRightSource[frameId] = nullptr;
|
||||
mMultiviewDepthResolveLeftTarget[frameId] = mMultiviewDepthResolveRightTarget[frameId] = nullptr;
|
||||
}
|
||||
|
||||
osg::FrameBufferAttachment makeSingleLayerAttachmentFromMultilayerAttachment(osg::FrameBufferAttachment attachment, int layer)
|
||||
{
|
||||
osg::Texture* tex = attachment.getTexture();
|
||||
|
||||
if (tex->getTextureTarget() == GL_TEXTURE_2D_ARRAY)
|
||||
return osg::FrameBufferAttachment(static_cast<osg::Texture2DArray*>(tex), layer, 0);
|
||||
|
||||
#ifdef OSG_HAS_MULTIVIEW
|
||||
if (tex->getTextureTarget() == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)
|
||||
return osg::FrameBufferAttachment(static_cast<osg::Texture2DMultisampleArray*>(tex), layer, 0);
|
||||
#endif
|
||||
|
||||
Log(Debug::Error) << "Attempted to extract a layer from an unlayered texture";
|
||||
|
||||
return osg::FrameBufferAttachment();
|
||||
}
|
||||
|
||||
void TransparentDepthBinCallback::setupMultiviewDepthResolveBuffers(int frameId)
|
||||
{
|
||||
const osg::FrameBufferObject::BufferComponent component = osg::FrameBufferObject::BufferComponent::PACKED_DEPTH_STENCIL_BUFFER;
|
||||
const auto& sourceFbo = mMsaaFbo[frameId] ? mMsaaFbo[frameId] : mFbo[frameId];
|
||||
const auto& sourceAttachment = sourceFbo->getAttachment(component);
|
||||
mMultiviewDepthResolveLeftSource[frameId] = new osg::FrameBufferObject;
|
||||
mMultiviewDepthResolveLeftSource[frameId]->setAttachment(component, makeSingleLayerAttachmentFromMultilayerAttachment(sourceAttachment, 0));
|
||||
mMultiviewDepthResolveRightSource[frameId] = new osg::FrameBufferObject;
|
||||
mMultiviewDepthResolveRightSource[frameId]->setAttachment(component, makeSingleLayerAttachmentFromMultilayerAttachment(sourceAttachment, 1));
|
||||
const auto& targetFbo = mOpaqueFbo[frameId];
|
||||
const auto& targetAttachment = targetFbo->getAttachment(component);
|
||||
mMultiviewDepthResolveLeftTarget[frameId] = new osg::FrameBufferObject;
|
||||
mMultiviewDepthResolveLeftTarget[frameId]->setAttachment(component, makeSingleLayerAttachmentFromMultilayerAttachment(targetAttachment, 0));
|
||||
mMultiviewDepthResolveRightTarget[frameId] = new osg::FrameBufferObject;
|
||||
mMultiviewDepthResolveRightTarget[frameId]->setAttachment(component, makeSingleLayerAttachmentFromMultilayerAttachment(targetAttachment, 1));
|
||||
}
|
||||
|
||||
}
|
|
@ -23,11 +23,18 @@ namespace MWRender
|
|||
TransparentDepthBinCallback(Shader::ShaderManager& shaderManager, bool postPass);
|
||||
|
||||
void drawImplementation(osgUtil::RenderBin* bin, osg::RenderInfo& renderInfo, osgUtil::RenderLeaf*& previous) override;
|
||||
void dirtyFrame(int frameId);
|
||||
void setupMultiviewDepthResolveBuffers(int frameId);
|
||||
|
||||
std::array<osg::ref_ptr<osg::FrameBufferObject>, 2> mFbo;
|
||||
std::array<osg::ref_ptr<osg::FrameBufferObject>, 2> mMsaaFbo;
|
||||
std::array<osg::ref_ptr<osg::FrameBufferObject>, 2> mOpaqueFbo;
|
||||
|
||||
std::array<osg::ref_ptr<osg::FrameBufferObject>, 2> mMultiviewDepthResolveLeftSource;
|
||||
std::array<osg::ref_ptr<osg::FrameBufferObject>, 2> mMultiviewDepthResolveRightSource;
|
||||
std::array<osg::ref_ptr<osg::FrameBufferObject>, 2> mMultiviewDepthResolveLeftTarget;
|
||||
std::array<osg::ref_ptr<osg::FrameBufferObject>, 2> mMultiviewDepthResolveRightTarget;
|
||||
|
||||
private:
|
||||
osg::ref_ptr<osg::StateSet> mStateSet;
|
||||
bool mPostPass;
|
||||
|
|
|
@ -82,18 +82,23 @@ namespace Debug
|
|||
break;
|
||||
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
|
||||
typeStr = "DEPRECATED_BEHAVIOR";
|
||||
logSeverity = Warning;
|
||||
break;
|
||||
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
|
||||
typeStr = "UNDEFINED_BEHAVIOR";
|
||||
logSeverity = Warning;
|
||||
break;
|
||||
case GL_DEBUG_TYPE_PORTABILITY:
|
||||
typeStr = "PORTABILITY";
|
||||
logSeverity = Debug;
|
||||
break;
|
||||
case GL_DEBUG_TYPE_PERFORMANCE:
|
||||
typeStr = "PERFORMANCE";
|
||||
logSeverity = Debug;
|
||||
break;
|
||||
case GL_DEBUG_TYPE_OTHER:
|
||||
typeStr = "OTHER";
|
||||
logSeverity = Debug;
|
||||
break;
|
||||
default:
|
||||
typeStr = "UNDEFINED";
|
||||
|
|
|
@ -29,6 +29,19 @@ namespace
|
|||
#endif
|
||||
omw_Out vec2 omw_TexCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
omw_Position = vec4(omw_Vertex.xy, 0.0, 1.0);
|
||||
omw_TexCoord = omw_Position.xy * 0.5 + 0.5;
|
||||
})GLSL";
|
||||
|
||||
constexpr char s_DefaultVertexMultiview[] = R"GLSL(
|
||||
layout(num_views = 2) in;
|
||||
#if OMW_USE_BINDINGS
|
||||
omw_In vec2 omw_Vertex;
|
||||
#endif
|
||||
omw_Out vec2 omw_TexCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
omw_Position = vec4(omw_Vertex.xy, 0.0, 1.0);
|
||||
|
@ -81,6 +94,11 @@ uniform @builtinSampler omw_SamplerNormals;
|
|||
uniform vec4 omw_PointLights[@pointLightCount];
|
||||
uniform int omw_PointLightsCount;
|
||||
|
||||
#if OMW_MULTIVIEW
|
||||
uniform mat4 projectionMatrixMultiView[2];
|
||||
uniform mat4 invProjectionMatrixMultiView[2];
|
||||
#endif
|
||||
|
||||
int omw_GetPointLightCount()
|
||||
{
|
||||
return omw_PointLightsCount;
|
||||
|
@ -112,6 +130,25 @@ float omw_GetPointLightRadius(int index)
|
|||
uniform _omw_data omw;
|
||||
#endif
|
||||
|
||||
|
||||
mat4 omw_ProjectionMatrix()
|
||||
{
|
||||
#if OMW_MULTIVIEW
|
||||
return projectionMatrixMultiView[gl_ViewID_OVR];
|
||||
#else
|
||||
return omw.projectionMatrix;
|
||||
#endif
|
||||
}
|
||||
|
||||
mat4 omw_InvProjectionMatrix()
|
||||
{
|
||||
#if OMW_MULTIVIEW
|
||||
return invProjectionMatrixMultiView[gl_ViewID_OVR];
|
||||
#else
|
||||
return omw.invProjectionMatrix;
|
||||
#endif
|
||||
}
|
||||
|
||||
float omw_GetDepth(vec2 uv)
|
||||
{
|
||||
#if OMW_MULTIVIEW
|
||||
|
@ -266,7 +303,7 @@ float omw_GetPointLightRadius(int index)
|
|||
if (mType == Type::Pixel)
|
||||
{
|
||||
if (!mVertex)
|
||||
mVertex = new osg::Shader(osg::Shader::VERTEX, s_DefaultVertex);
|
||||
mVertex = new osg::Shader(osg::Shader::VERTEX, Stereo::getMultiview() ? s_DefaultVertexMultiview : s_DefaultVertex);
|
||||
|
||||
mVertex->setShaderSource(getPassHeader(technique, preamble).append(mVertex->getShaderSource()));
|
||||
mFragment->setShaderSource(getPassHeader(technique, preamble, true).append(mFragment->getShaderSource()));
|
||||
|
|
|
@ -20,9 +20,11 @@ namespace fx
|
|||
mData.get<InvProjectionMatrix>() = osg::Matrixf::inverse(matrix);
|
||||
}
|
||||
|
||||
void setViewMatrix(const osg::Matrixf& matrix) { mData.get<ViewMatrix>() = matrix; }
|
||||
|
||||
void setInvViewMatrix(const osg::Matrixf& matrix) { mData.get<InvViewMatrix>() = matrix; }
|
||||
void setViewMatrix(const osg::Matrixf& matrix)
|
||||
{
|
||||
mData.get<ViewMatrix>() = matrix;
|
||||
mData.get<InvViewMatrix>() = osg::Matrixf::inverse(matrix);
|
||||
}
|
||||
|
||||
void setPrevViewMatrix(const osg::Matrixf& matrix) { mData.get<PrevViewMatrix>() = matrix;}
|
||||
|
||||
|
|
|
@ -456,7 +456,7 @@ namespace Resource
|
|||
mConvertAlphaTestToAlphaToCoverage = convert;
|
||||
}
|
||||
|
||||
void SceneManager::setOpaqueDepthTex(osg::ref_ptr<osg::Texture2D> texturePing, osg::ref_ptr<osg::Texture2D> texturePong)
|
||||
void SceneManager::setOpaqueDepthTex(osg::ref_ptr<osg::Texture> texturePing, osg::ref_ptr<osg::Texture> texturePong)
|
||||
{
|
||||
mOpaqueDepthTex = { texturePing, texturePong };
|
||||
}
|
||||
|
|
|
@ -109,7 +109,7 @@ namespace Resource
|
|||
void setSupportedLightingMethods(const SceneUtil::LightManager::SupportedMethods& supported);
|
||||
bool isSupportedLightingMethod(SceneUtil::LightingMethod method) const;
|
||||
|
||||
void setOpaqueDepthTex(osg::ref_ptr<osg::Texture2D> texturePing, osg::ref_ptr<osg::Texture2D> texturePong);
|
||||
void setOpaqueDepthTex(osg::ref_ptr<osg::Texture> texturePing, osg::ref_ptr<osg::Texture> texturePong);
|
||||
|
||||
enum class UBOBinding
|
||||
{
|
||||
|
@ -213,7 +213,7 @@ namespace Resource
|
|||
SceneUtil::LightManager::SupportedMethods mSupportedLightingMethods;
|
||||
bool mConvertAlphaTestToAlphaToCoverage;
|
||||
bool mSupportsNormalsRT;
|
||||
std::array<osg::ref_ptr<osg::Texture2D>, 2> mOpaqueDepthTex;
|
||||
std::array<osg::ref_ptr<osg::Texture>, 2> mOpaqueDepthTex;
|
||||
|
||||
osg::ref_ptr<Resource::SharedStateManager> mSharedStateManager;
|
||||
mutable std::mutex mSharedStateMutex;
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace
|
|||
OpaqueDepthAttribute(const OpaqueDepthAttribute& copy, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY)
|
||||
: osg::StateAttribute(copy, copyop), mTextures(copy.mTextures), mUnit(copy.mUnit) {}
|
||||
|
||||
void setTexturesAndUnit(const std::array<osg::ref_ptr<osg::Texture2D>, 2>& textures, int unit)
|
||||
void setTexturesAndUnit(const std::array<osg::ref_ptr<osg::Texture>, 2>& textures, int unit)
|
||||
{
|
||||
mTextures = textures;
|
||||
mUnit = unit;
|
||||
|
@ -69,7 +69,7 @@ namespace
|
|||
}
|
||||
|
||||
private:
|
||||
mutable std::array<osg::ref_ptr<osg::Texture2D>, 2> mTextures;
|
||||
mutable std::array<osg::ref_ptr<osg::Texture>, 2> mTextures;
|
||||
int mUnit;
|
||||
};
|
||||
}
|
||||
|
@ -982,7 +982,7 @@ namespace Shader
|
|||
mConvertAlphaTestToAlphaToCoverage = convert;
|
||||
}
|
||||
|
||||
void ShaderVisitor::setOpaqueDepthTex(osg::ref_ptr<osg::Texture2D> texturePing, osg::ref_ptr<osg::Texture2D> texturePong)
|
||||
void ShaderVisitor::setOpaqueDepthTex(osg::ref_ptr<osg::Texture> texturePing, osg::ref_ptr<osg::Texture> texturePong)
|
||||
{
|
||||
mOpaqueDepthTex = { texturePing, texturePong };
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ namespace Shader
|
|||
|
||||
void setConvertAlphaTestToAlphaToCoverage(bool convert);
|
||||
|
||||
void setOpaqueDepthTex(osg::ref_ptr<osg::Texture2D> texturePing, osg::ref_ptr<osg::Texture2D> texturePong);
|
||||
void setOpaqueDepthTex(osg::ref_ptr<osg::Texture> texturePing, osg::ref_ptr<osg::Texture> texturePong);
|
||||
|
||||
void setSupportsNormalsRT(bool supports) { mSupportsNormalsRT = supports; }
|
||||
|
||||
|
@ -122,7 +122,7 @@ namespace Shader
|
|||
bool adjustGeometry(osg::Geometry& sourceGeometry, const ShaderRequirements& reqs);
|
||||
|
||||
osg::ref_ptr<const osg::Program> mProgramTemplate;
|
||||
std::array<osg::ref_ptr<osg::Texture2D>, 2> mOpaqueDepthTex;
|
||||
std::array<osg::ref_ptr<osg::Texture>, 2> mOpaqueDepthTex;
|
||||
};
|
||||
|
||||
class ReinstateRemovedStateVisitor : public osg::NodeVisitor
|
||||
|
|
|
@ -72,7 +72,7 @@ namespace Stereo
|
|||
osg::Matrix dummy;
|
||||
auto* uProjectionMatrix = stateset->getUniform("projectionMatrix");
|
||||
if (uProjectionMatrix)
|
||||
uProjectionMatrix->set(mManager->computeEyeProjection(0, SceneUtil::AutoDepth::isReversed()));
|
||||
uProjectionMatrix->set(mManager->computeEyeViewOffset(0) * mManager->computeEyeProjection(0, SceneUtil::AutoDepth::isReversed()));
|
||||
}
|
||||
|
||||
void applyRight(osg::StateSet* stateset, osgUtil::CullVisitor* nv) override
|
||||
|
@ -80,7 +80,7 @@ namespace Stereo
|
|||
osg::Matrix dummy;
|
||||
auto* uProjectionMatrix = stateset->getUniform("projectionMatrix");
|
||||
if (uProjectionMatrix)
|
||||
uProjectionMatrix->set(mManager->computeEyeProjection(1, SceneUtil::AutoDepth::isReversed()));
|
||||
uProjectionMatrix->set(mManager->computeEyeViewOffset(1) * mManager->computeEyeProjection(1, SceneUtil::AutoDepth::isReversed()));
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -99,8 +99,8 @@ namespace Stereo
|
|||
protected:
|
||||
virtual void setDefaults(osg::StateSet* stateset)
|
||||
{
|
||||
stateset->addUniform(new osg::Uniform(osg::Uniform::FLOAT_MAT4, "viewMatrixMultiView", 2));
|
||||
stateset->addUniform(new osg::Uniform(osg::Uniform::FLOAT_MAT4, "projectionMatrixMultiView", 2));
|
||||
stateset->addUniform(new osg::Uniform(osg::Uniform::FLOAT_MAT4, "invProjectionMatrixMultiView", 2));
|
||||
}
|
||||
|
||||
virtual void apply(osg::StateSet* stateset, osg::NodeVisitor* /*nv*/)
|
||||
|
@ -248,25 +248,23 @@ namespace Stereo
|
|||
osg::Matrixd computeLeftEyeProjection(const osg::Matrixd& projection) const override
|
||||
{
|
||||
(void)projection;
|
||||
return mManager->computeEyeProjection(0, false);
|
||||
return mManager->computeEyeViewOffset(0) * mManager->computeEyeProjection(0, false);
|
||||
}
|
||||
|
||||
osg::Matrixd computeLeftEyeView(const osg::Matrixd& view) const override
|
||||
{
|
||||
(void)view;
|
||||
return mManager->computeEyeView(0);
|
||||
return view;
|
||||
}
|
||||
|
||||
osg::Matrixd computeRightEyeProjection(const osg::Matrixd& projection) const override
|
||||
{
|
||||
(void)projection;
|
||||
return mManager->computeEyeProjection(1, false);
|
||||
return mManager->computeEyeViewOffset(1) * mManager->computeEyeProjection(1, false);
|
||||
}
|
||||
|
||||
osg::Matrixd computeRightEyeView(const osg::Matrixd& view) const override
|
||||
{
|
||||
(void)view;
|
||||
return mManager->computeEyeView(1);
|
||||
return view;
|
||||
}
|
||||
|
||||
Manager* mManager;
|
||||
|
@ -305,15 +303,16 @@ namespace Stereo
|
|||
|
||||
void Manager::updateStereoFramebuffer()
|
||||
{
|
||||
//VR-TODO: in VR, still need to have this framebuffer attached before the postprocessor is created
|
||||
auto samples = Settings::Manager::getInt("antialiasing", "Video");
|
||||
auto eyeRes = eyeResolution();
|
||||
|
||||
if (mMultiviewFramebuffer)
|
||||
mMultiviewFramebuffer->detachFrom(mMainCamera);
|
||||
//if (mMultiviewFramebuffer)
|
||||
// mMultiviewFramebuffer->detachFrom(mMainCamera);
|
||||
mMultiviewFramebuffer = std::make_shared<MultiviewFramebuffer>(static_cast<int>(eyeRes.x()), static_cast<int>(eyeRes.y()), samples);
|
||||
mMultiviewFramebuffer->attachColorComponent(SceneUtil::Color::colorSourceFormat(), SceneUtil::Color::colorSourceType(), SceneUtil::Color::colorInternalFormat());
|
||||
mMultiviewFramebuffer->attachDepthComponent(SceneUtil::AutoDepth::depthSourceFormat(), SceneUtil::AutoDepth::depthSourceType(), SceneUtil::AutoDepth::depthInternalFormat());
|
||||
mMultiviewFramebuffer->attachTo(mMainCamera);
|
||||
//mMultiviewFramebuffer->attachTo(mMainCamera);
|
||||
}
|
||||
|
||||
void Manager::update()
|
||||
|
@ -328,17 +327,14 @@ namespace Stereo
|
|||
if (mUpdateViewCallback)
|
||||
{
|
||||
mUpdateViewCallback->updateView(mView[0], mView[1]);
|
||||
auto viewMatrix = mMainCamera->getViewMatrix();
|
||||
mViewOffsetMatrix[0] = mView[0].viewMatrix(true);
|
||||
mViewOffsetMatrix[1] = mView[1].viewMatrix(true);
|
||||
mViewMatrix[0] = viewMatrix * mViewOffsetMatrix[0];
|
||||
mViewMatrix[1] = viewMatrix * mViewOffsetMatrix[1];
|
||||
mProjectionMatrix[0] = mView[0].perspectiveMatrix(near_, far_, false);
|
||||
mProjectionMatrix[1] = mView[1].perspectiveMatrix(near_, far_, false);
|
||||
if (SceneUtil::AutoDepth::isReversed())
|
||||
{
|
||||
mProjectionMatrixReverseZ[0] = mView[0].perspectiveMatrix(near_, far_, true);
|
||||
mProjectionMatrixReverseZ[1] = mView[1].perspectiveMatrix(near_, far_, true);
|
||||
mProjectionMatrixReverseZ[1] = mView[1].perspectiveMatrix(near_, far_, true);
|
||||
}
|
||||
|
||||
View masterView;
|
||||
|
@ -353,10 +349,8 @@ namespace Stereo
|
|||
{
|
||||
auto* ds = osg::DisplaySettings::instance().get();
|
||||
auto viewMatrix = mMainCamera->getViewMatrix();
|
||||
mViewMatrix[0] = ds->computeLeftEyeViewImplementation(viewMatrix);
|
||||
mViewMatrix[1] = ds->computeRightEyeViewImplementation(viewMatrix);
|
||||
mViewOffsetMatrix[0] = osg::Matrix::inverse(viewMatrix) * mViewMatrix[0];
|
||||
mViewOffsetMatrix[1] = osg::Matrix::inverse(viewMatrix) * mViewMatrix[1];
|
||||
mViewOffsetMatrix[0] = osg::Matrix::inverse(viewMatrix) * ds->computeLeftEyeViewImplementation(viewMatrix);
|
||||
mViewOffsetMatrix[1] = osg::Matrix::inverse(viewMatrix) * ds->computeRightEyeViewImplementation(viewMatrix);
|
||||
mProjectionMatrix[0] = ds->computeLeftEyeProjectionImplementation(projectionMatrix);
|
||||
mProjectionMatrix[1] = ds->computeRightEyeProjectionImplementation(projectionMatrix);
|
||||
if (SceneUtil::AutoDepth::isReversed())
|
||||
|
@ -376,13 +370,15 @@ namespace Stereo
|
|||
void Manager::updateMultiviewStateset(osg::StateSet* stateset)
|
||||
{
|
||||
// Update stereo uniforms
|
||||
auto * viewMatrixMultiViewUniform = stateset->getUniform("viewMatrixMultiView");
|
||||
auto * projectionMatrixMultiViewUniform = stateset->getUniform("projectionMatrixMultiView");
|
||||
auto * invProjectionMatrixMultiViewUniform = stateset->getUniform("invProjectionMatrixMultiView");
|
||||
|
||||
for (int view : {0, 1})
|
||||
{
|
||||
viewMatrixMultiViewUniform->setElement(view, mViewOffsetMatrix[view]);
|
||||
projectionMatrixMultiViewUniform->setElement(view, computeEyeProjection(view, SceneUtil::AutoDepth::isReversed()));
|
||||
auto projectionMatrix = computeEyeViewOffset(view) * computeEyeProjection(view, SceneUtil::AutoDepth::isReversed());
|
||||
auto invProjectionMatrix = osg::Matrix::inverse(projectionMatrix);
|
||||
projectionMatrixMultiViewUniform->setElement(view, projectionMatrix);
|
||||
invProjectionMatrixMultiViewUniform->setElement(view, invProjectionMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -401,11 +397,6 @@ namespace Stereo
|
|||
return reverseZ ? mProjectionMatrixReverseZ[view] : mProjectionMatrix[view];
|
||||
}
|
||||
|
||||
osg::Matrixd Manager::computeEyeView(int view) const
|
||||
{
|
||||
return mViewMatrix[view];
|
||||
}
|
||||
|
||||
osg::Matrixd Manager::computeEyeViewOffset(int view) const
|
||||
{
|
||||
return mViewOffsetMatrix[view];
|
||||
|
|
|
@ -68,7 +68,6 @@ namespace Stereo
|
|||
void setCullCallback(osg::ref_ptr<osg::NodeCallback> cb);
|
||||
|
||||
osg::Matrixd computeEyeProjection(int view, bool reverseZ) const;
|
||||
osg::Matrixd computeEyeView(int view) const;
|
||||
osg::Matrixd computeEyeViewOffset(int view) const;
|
||||
|
||||
//! Sets up any definitions necessary for stereo rendering
|
||||
|
@ -116,7 +115,6 @@ namespace Stereo
|
|||
osg::Vec2i mEyeResolutionOverride;
|
||||
|
||||
std::array<View, 2> mView;
|
||||
std::array<osg::Matrix, 2> mViewMatrix;
|
||||
std::array<osg::Matrix, 2> mViewOffsetMatrix;
|
||||
std::array<osg::Matrix, 2> mProjectionMatrix;
|
||||
std::array<osg::Matrix, 2> mProjectionMatrixReverseZ;
|
||||
|
|
|
@ -34,6 +34,8 @@ set(SHADER_FILES
|
|||
shadowcasting_vertex.glsl
|
||||
shadowcasting_fragment.glsl
|
||||
vertexcolors.glsl
|
||||
multiview_resolve_vertex.glsl
|
||||
multiview_resolve_fragment.glsl
|
||||
nv_default_vertex.glsl
|
||||
nv_default_fragment.glsl
|
||||
nv_nolighting_vertex.glsl
|
||||
|
|
|
@ -5,11 +5,12 @@ uniform mat4 projectionMatrix;
|
|||
varying vec2 diffuseMapUV;
|
||||
varying float alphaPassthrough;
|
||||
|
||||
#include "openmw_vertex.h.glsl"
|
||||
#include "vertexcolors.glsl"
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projectionMatrix * (gl_ModelViewMatrix * gl_Vertex);
|
||||
gl_Position = mw_modelToClip(gl_Vertex);
|
||||
|
||||
if (colorMode == 2)
|
||||
alphaPassthrough = gl_Color.a;
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
varying vec2 uv;
|
||||
|
||||
#include "openmw_vertex.h.glsl"
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(gl_Vertex.xy, 0.0, 1.0);
|
||||
|
|
18
files/shaders/multiview_resolve_fragment.glsl
Normal file
18
files/shaders/multiview_resolve_fragment.glsl
Normal file
|
@ -0,0 +1,18 @@
|
|||
#version 120
|
||||
#extension GL_EXT_texture_array : require
|
||||
|
||||
varying vec2 uv;
|
||||
uniform sampler2DArray omw_SamplerLastShader;
|
||||
|
||||
void main()
|
||||
{
|
||||
int view = 0;
|
||||
vec3 uvz = vec3(uv.x * 2., uv.y, 0);
|
||||
if(uvz.x > 1.)
|
||||
{
|
||||
uvz.x -= 1.;
|
||||
uvz.z = 1;
|
||||
}
|
||||
|
||||
gl_FragColor = texture2DArray(omw_SamplerLastShader, uvz);
|
||||
}
|
9
files/shaders/multiview_resolve_vertex.glsl
Normal file
9
files/shaders/multiview_resolve_vertex.glsl
Normal file
|
@ -0,0 +1,9 @@
|
|||
#version 120
|
||||
|
||||
varying vec2 uv;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(gl_Vertex.xy, 0.0, 1.0);
|
||||
uv = gl_Position.xy * 0.5 + 0.5;
|
||||
}
|
|
@ -18,8 +18,3 @@ vec4 mw_viewToClip(vec4 pos)
|
|||
{
|
||||
return projectionMatrix * pos;
|
||||
}
|
||||
|
||||
vec4 mw_viewStereoAdjust(vec4 pos)
|
||||
{
|
||||
return pos;
|
||||
}
|
||||
|
|
|
@ -4,4 +4,3 @@
|
|||
vec4 mw_modelToClip(vec4 pos);
|
||||
vec4 mw_modelToView(vec4 pos);
|
||||
vec4 mw_viewToClip(vec4 pos);
|
||||
vec4 mw_viewStereoAdjust(vec4 pos);
|
|
@ -8,24 +8,18 @@ layout(num_views = @numViews) in;
|
|||
#include "openmw_vertex.h.glsl"
|
||||
|
||||
uniform mat4 projectionMatrixMultiView[@numViews];
|
||||
uniform mat4 viewMatrixMultiView[@numViews];
|
||||
|
||||
vec4 mw_modelToClip(vec4 pos)
|
||||
{
|
||||
return projectionMatrixMultiView[gl_ViewID_OVR] * mw_modelToView(pos);
|
||||
return mw_viewToClip(mw_modelToView(pos));
|
||||
}
|
||||
|
||||
vec4 mw_modelToView(vec4 pos)
|
||||
{
|
||||
return viewMatrixMultiView[gl_ViewID_OVR] * gl_ModelViewMatrix * pos;
|
||||
return gl_ModelViewMatrix * pos;
|
||||
}
|
||||
|
||||
vec4 mw_viewToClip(vec4 pos)
|
||||
{
|
||||
return projectionMatrixMultiView[gl_ViewID_OVR] * viewMatrixMultiView[gl_ViewID_OVR] * pos;
|
||||
}
|
||||
|
||||
vec4 mw_viewStereoAdjust(vec4 pos)
|
||||
{
|
||||
return viewMatrixMultiView[gl_ViewID_OVR] * pos;
|
||||
return projectionMatrixMultiView[gl_ViewID_OVR] * pos;
|
||||
}
|
Loading…
Reference in a new issue