mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-03-16 16:20:53 +00:00
Merge branch 'multiview-refactor' into 'master'
[Multiview] refactoring See merge request OpenMW/openmw!2122
This commit is contained in:
commit
54db3a97bb
@ -25,6 +25,7 @@
|
||||
#include <components/settings/settings.hpp>
|
||||
#include <components/sceneutil/nodecallback.hpp>
|
||||
#include <components/sceneutil/depth.hpp>
|
||||
#include <components/stereo/multiview.hpp>
|
||||
|
||||
#include "../mwbase/world.hpp"
|
||||
#include "../mwworld/class.hpp"
|
||||
@ -179,20 +180,6 @@ namespace MWRender
|
||||
camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);
|
||||
SceneUtil::setCameraClearDepth(camera);
|
||||
|
||||
#ifdef OSG_HAS_MULTIVIEW
|
||||
if (shouldDoTextureArray())
|
||||
{
|
||||
auto* viewUniform = new osg::Uniform(osg::Uniform::FLOAT_MAT4, "viewMatrixMultiView", 2);
|
||||
auto* projUniform = new osg::Uniform(osg::Uniform::FLOAT_MAT4, "projectionMatrixMultiView", 2);
|
||||
viewUniform->setElement(0, osg::Matrix::identity());
|
||||
viewUniform->setElement(1, osg::Matrix::identity());
|
||||
projUniform->setElement(0, mPerspectiveMatrix);
|
||||
projUniform->setElement(1, mPerspectiveMatrix);
|
||||
mGroup->getOrCreateStateSet()->addUniform(viewUniform, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
|
||||
mGroup->getOrCreateStateSet()->addUniform(projUniform, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
|
||||
}
|
||||
#endif
|
||||
|
||||
camera->setNodeMask(Mask_RenderToTexture);
|
||||
camera->addChild(mGroup);
|
||||
};
|
||||
@ -202,6 +189,9 @@ namespace MWRender
|
||||
if(mCameraStateset)
|
||||
camera->setStateSet(mCameraStateset);
|
||||
camera->setViewMatrix(mViewMatrix);
|
||||
|
||||
if (shouldDoTextureArray())
|
||||
Stereo::setMultiviewMatrices(mGroup->getOrCreateStateSet(), { mPerspectiveMatrix, mPerspectiveMatrix });
|
||||
};
|
||||
|
||||
void addChild(osg::Node* node)
|
||||
|
@ -702,16 +702,7 @@ void LocalMapRenderToTexture::setDefaults(osg::Camera* camera)
|
||||
stateset->addUniform(new osg::Uniform("projectionMatrix", static_cast<osg::Matrixf>(mProjectionMatrix)), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
|
||||
|
||||
if (Stereo::getMultiview())
|
||||
{
|
||||
auto* viewUniform = new osg::Uniform(osg::Uniform::FLOAT_MAT4, "viewMatrixMultiView", 2);
|
||||
auto* projUniform = new osg::Uniform(osg::Uniform::FLOAT_MAT4, "projectionMatrixMultiView", 2);
|
||||
viewUniform->setElement(0, osg::Matrix::identity());
|
||||
viewUniform->setElement(1, osg::Matrix::identity());
|
||||
projUniform->setElement(0, mProjectionMatrix);
|
||||
projUniform->setElement(1, mProjectionMatrix);
|
||||
stateset->addUniform(viewUniform, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
|
||||
stateset->addUniform(projUniform, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
|
||||
}
|
||||
Stereo::setMultiviewMatrices(stateset, { mProjectionMatrix, mProjectionMatrix });
|
||||
|
||||
// assign large value to effectively turn off fog
|
||||
// shaders don't respect glDisable(GL_FOG)
|
||||
|
@ -67,25 +67,8 @@ namespace MWRender
|
||||
|
||||
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");
|
||||
}
|
||||
osg::ref_ptr<osg::Texture> clone = static_cast<osg::Texture*>(tex->clone(osg::CopyOp::SHALLOW_COPY));
|
||||
fbo->setAttachment(component, Stereo::createMultiviewCompatibleAttachment(clone));
|
||||
}
|
||||
|
||||
void PingPongCanvas::drawImplementation(osg::RenderInfo& renderInfo) const
|
||||
|
@ -9,10 +9,6 @@
|
||||
#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>
|
||||
@ -75,53 +71,6 @@ namespace
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
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;
|
||||
case GL_TEXTURE_2D_MULTISAMPLE:
|
||||
static_cast<osg::Texture2DMultisample*>(tex)->setTextureSize(w, h);
|
||||
break;
|
||||
#ifdef OSG_HAS_MULTIVIEW
|
||||
case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
|
||||
static_cast<osg::Texture2DMultisampleArray*>(tex)->setTextureSize(w, h, 2);
|
||||
break;
|
||||
#endif
|
||||
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,
|
||||
@ -136,35 +85,7 @@ namespace
|
||||
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);
|
||||
auto texture = Stereo::createMultiviewCompatibleTexture(width, height, samples);
|
||||
texture->setSourceFormat(template_->getSourceFormat());
|
||||
texture->setSourceType(template_->getSourceType());
|
||||
texture->setInternalFormat(template_->getInternalFormat());
|
||||
@ -173,7 +94,7 @@ namespace
|
||||
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;
|
||||
return Stereo::createMultiviewCompatibleAttachment(texture);
|
||||
}
|
||||
}
|
||||
|
||||
@ -547,15 +468,15 @@ namespace MWRender
|
||||
if (!tex)
|
||||
continue;
|
||||
|
||||
setTextureSize(tex, width, height);
|
||||
Stereo::setMultiviewCompatibleTextureSize(tex, width, height);
|
||||
tex->dirtyTextureObject();
|
||||
}
|
||||
|
||||
fbos[FBO_Primary] = new osg::FrameBufferObject;
|
||||
setAttachment(fbos[FBO_Primary], osg::Camera::COLOR_BUFFER0, textures[Tex_Scene]);
|
||||
fbos[FBO_Primary]->setAttachment(osg::Camera::COLOR_BUFFER0, Stereo::createMultiviewCompatibleAttachment(textures[Tex_Scene]));
|
||||
if (mNormals && mNormalsSupported)
|
||||
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_Primary]->setAttachment(osg::Camera::COLOR_BUFFER1, Stereo::createMultiviewCompatibleAttachment(textures[Tex_Normal]));
|
||||
fbos[FBO_Primary]->setAttachment(osg::Camera::PACKED_DEPTH_STENCIL_BUFFER, Stereo::createMultiviewCompatibleAttachment(textures[Tex_Depth]));
|
||||
|
||||
fbos[FBO_FirstPerson] = new osg::FrameBufferObject;
|
||||
|
||||
@ -581,20 +502,20 @@ namespace MWRender
|
||||
fbos[FBO_FirstPerson]->setAttachment(osg::FrameBufferObject::BufferComponent::COLOR_BUFFER0, colorRB);
|
||||
|
||||
fbos[FBO_Intercept] = new osg::FrameBufferObject;
|
||||
setAttachment(fbos[FBO_Intercept], osg::FrameBufferObject::BufferComponent::COLOR_BUFFER0, textures[Tex_Scene]);
|
||||
setAttachment(fbos[FBO_Intercept], osg::FrameBufferObject::BufferComponent::COLOR_BUFFER1, textures[Tex_Normal]);
|
||||
fbos[FBO_Intercept]->setAttachment(osg::FrameBufferObject::BufferComponent::COLOR_BUFFER0, Stereo::createMultiviewCompatibleAttachment(textures[Tex_Scene]));
|
||||
fbos[FBO_Intercept]->setAttachment(osg::FrameBufferObject::BufferComponent::COLOR_BUFFER1, Stereo::createMultiviewCompatibleAttachment(textures[Tex_Normal]));
|
||||
}
|
||||
else
|
||||
{
|
||||
setAttachment(fbos[FBO_FirstPerson], osg::FrameBufferObject::BufferComponent::COLOR_BUFFER0, textures[Tex_Scene]);
|
||||
fbos[FBO_FirstPerson]->setAttachment(osg::FrameBufferObject::BufferComponent::COLOR_BUFFER0, Stereo::createMultiviewCompatibleAttachment(textures[Tex_Scene]));
|
||||
if (mNormals && mNormalsSupported)
|
||||
setAttachment(fbos[FBO_FirstPerson], osg::FrameBufferObject::BufferComponent::COLOR_BUFFER1, textures[Tex_Normal]);
|
||||
fbos[FBO_FirstPerson]->setAttachment(osg::FrameBufferObject::BufferComponent::COLOR_BUFFER1, Stereo::createMultiviewCompatibleAttachment(textures[Tex_Normal]));
|
||||
}
|
||||
|
||||
if (textures[Tex_OpaqueDepth])
|
||||
{
|
||||
fbos[FBO_OpaqueDepth] = new osg::FrameBufferObject;
|
||||
setAttachment(fbos[FBO_OpaqueDepth], osg::FrameBufferObject::BufferComponent::PACKED_DEPTH_STENCIL_BUFFER, textures[Tex_OpaqueDepth]);
|
||||
fbos[FBO_OpaqueDepth]->setAttachment(osg::FrameBufferObject::BufferComponent::PACKED_DEPTH_STENCIL_BUFFER, Stereo::createMultiviewCompatibleAttachment(textures[Tex_OpaqueDepth]));
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
@ -799,7 +720,7 @@ namespace MWRender
|
||||
else
|
||||
texture = new osg::Texture2D;
|
||||
}
|
||||
setTextureSize(texture, width, height);
|
||||
Stereo::setMultiviewCompatibleTextureSize(texture, width, height);
|
||||
texture->setSourceFormat(GL_RGBA);
|
||||
texture->setSourceType(GL_UNSIGNED_BYTE);
|
||||
texture->setInternalFormat(GL_RGBA);
|
||||
|
@ -615,9 +615,7 @@ namespace MWRender
|
||||
protected:
|
||||
void setDefaults(osg::StateSet* stateset) override
|
||||
{
|
||||
if (Stereo::getMultiview())
|
||||
stateset->addUniform(new osg::Uniform(osg::Uniform::FLOAT_MAT4, "projectionMatrixMultiView", 2), osg::StateAttribute::OVERRIDE);
|
||||
else
|
||||
if (!Stereo::getMultiview())
|
||||
stateset->addUniform(new osg::Uniform(osg::Uniform::FLOAT_MAT4, "projectionMatrix"), osg::StateAttribute::OVERRIDE);
|
||||
|
||||
}
|
||||
@ -626,7 +624,7 @@ namespace MWRender
|
||||
{
|
||||
if (Stereo::getMultiview())
|
||||
{
|
||||
auto* projectionMatrixMultiViewUniform = stateset->getUniform("projectionMatrixMultiView");
|
||||
std::array<osg::Matrix, 2> projectionMatrices;
|
||||
auto& sm = Stereo::Manager::instance();
|
||||
|
||||
for (int view : {0, 1})
|
||||
@ -636,8 +634,10 @@ namespace MWRender
|
||||
for (int col : {0, 1, 2})
|
||||
viewOffsetMatrix(3, col) = 0;
|
||||
|
||||
projectionMatrixMultiViewUniform->setElement(view, viewOffsetMatrix * projectionMatrix);
|
||||
projectionMatrices[view] = viewOffsetMatrix * projectionMatrix;
|
||||
}
|
||||
|
||||
Stereo::setMultiviewMatrices(stateset, projectionMatrices);
|
||||
}
|
||||
}
|
||||
void applyLeft(osg::StateSet* stateset, osgUtil::CullVisitor* /*cv*/) override
|
||||
|
@ -4,10 +4,6 @@
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/Texture2DArray>
|
||||
|
||||
#ifdef OSG_HAS_MULTIVIEW
|
||||
#include <osg/Texture2DMultisampleArray>
|
||||
#endif
|
||||
|
||||
#include <osgUtil/RenderStage>
|
||||
|
||||
#include <components/shader/shadermanager.hpp>
|
||||
@ -70,14 +66,11 @@ namespace MWRender
|
||||
|
||||
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);
|
||||
if (!mMultiviewResolve[frameId])
|
||||
{
|
||||
mMultiviewResolve[frameId] = std::make_unique<Stereo::MultiviewFramebufferResolve>(msaaFbo ? msaaFbo : fbo, opaqueFbo, GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
mMultiviewResolve[frameId]->resolveImplementation(state);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -107,42 +100,8 @@ namespace MWRender
|
||||
|
||||
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));
|
||||
if (mMultiviewResolve[frameId])
|
||||
mMultiviewResolve[frameId]->dirty();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -15,6 +15,11 @@ namespace Shader
|
||||
class ShaderManager;
|
||||
}
|
||||
|
||||
namespace Stereo
|
||||
{
|
||||
class MultiviewFramebufferResolve;
|
||||
}
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
class TransparentDepthBinCallback : public osgUtil::RenderBin::DrawCallback
|
||||
@ -24,16 +29,12 @@ namespace MWRender
|
||||
|
||||
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;
|
||||
std::array<std::unique_ptr<Stereo::MultiviewFramebufferResolve>, 2> mMultiviewResolve;
|
||||
|
||||
private:
|
||||
osg::ref_ptr<osg::StateSet> mStateSet;
|
||||
|
@ -200,21 +200,20 @@ namespace SceneUtil
|
||||
if (camera->getBufferAttachmentMap().count(osg::Camera::PACKED_DEPTH_STENCIL_BUFFER))
|
||||
vdd->mDepthTexture = camera->getBufferAttachmentMap()[osg::Camera::PACKED_DEPTH_STENCIL_BUFFER]._texture;
|
||||
|
||||
#ifdef OSG_HAS_MULTIVIEW
|
||||
if (shouldDoTextureArray())
|
||||
{
|
||||
// Create any buffer attachments not added in setDefaults
|
||||
if (camera->getBufferAttachmentMap().count(osg::Camera::COLOR_BUFFER) == 0)
|
||||
{
|
||||
vdd->mColorTexture = createTextureArray(mColorBufferInternalFormat);
|
||||
camera->attach(osg::Camera::COLOR_BUFFER, vdd->mColorTexture, 0, osg::Camera::FACE_CONTROLLED_BY_MULTIVIEW_SHADER, mGenerateMipmaps, mSamples);
|
||||
SceneUtil::attachAlphaToCoverageFriendlyFramebufferToCamera(camera, osg::Camera::COLOR_BUFFER, vdd->mColorTexture, 0, osg::Camera::FACE_CONTROLLED_BY_MULTIVIEW_SHADER, mGenerateMipmaps);
|
||||
camera->attach(osg::Camera::COLOR_BUFFER, vdd->mColorTexture, 0, Stereo::osgFaceControlledByMultiviewShader(), mGenerateMipmaps, mSamples);
|
||||
SceneUtil::attachAlphaToCoverageFriendlyFramebufferToCamera(camera, osg::Camera::COLOR_BUFFER, vdd->mColorTexture, 0, Stereo::osgFaceControlledByMultiviewShader(), mGenerateMipmaps);
|
||||
}
|
||||
|
||||
if (camera->getBufferAttachmentMap().count(osg::Camera::PACKED_DEPTH_STENCIL_BUFFER) == 0)
|
||||
{
|
||||
vdd->mDepthTexture = createTextureArray(mDepthBufferInternalFormat);
|
||||
camera->attach(osg::Camera::PACKED_DEPTH_STENCIL_BUFFER, vdd->mDepthTexture, 0, osg::Camera::FACE_CONTROLLED_BY_MULTIVIEW_SHADER, false, mSamples);
|
||||
camera->attach(osg::Camera::PACKED_DEPTH_STENCIL_BUFFER, vdd->mDepthTexture, 0, Stereo::osgFaceControlledByMultiviewShader(), false, mSamples);
|
||||
}
|
||||
|
||||
if (shouldDoTextureView())
|
||||
@ -226,7 +225,6 @@ namespace SceneUtil
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// Create any buffer attachments not added in setDefaults
|
||||
if (camera->getBufferAttachmentMap().count(osg::Camera::COLOR_BUFFER) == 0)
|
||||
|
@ -27,31 +27,32 @@
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include <components/stereo/multiview.hpp>
|
||||
|
||||
#include <components/misc/stringops.hpp>
|
||||
#include "frustum.hpp"
|
||||
|
||||
namespace Stereo
|
||||
{
|
||||
#ifdef OSG_HAS_MULTIVIEW
|
||||
struct MultiviewFrustumCallback final : public osg::CullSettings::InitialFrustumCallback
|
||||
struct MultiviewFrustumCallback final : public Stereo::InitialFrustumCallback
|
||||
{
|
||||
MultiviewFrustumCallback(StereoFrustumManager* sfm)
|
||||
: mSfm(sfm)
|
||||
MultiviewFrustumCallback(StereoFrustumManager* sfm, osg::Camera* camera)
|
||||
: Stereo::InitialFrustumCallback(camera)
|
||||
, mSfm(sfm)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void setInitialFrustum(osg::CullStack& cullStack, osg::Polytope& frustum) const override
|
||||
void setInitialFrustum(osg::CullStack& cullStack, osg::BoundingBoxd& bb, bool& nearCulling, bool& farCulling) const override
|
||||
{
|
||||
auto cm = cullStack.getCullingMode();
|
||||
bool nearCulling = !!(cm & osg::CullSettings::NEAR_PLANE_CULLING);
|
||||
bool farCulling = !!(cm & osg::CullSettings::FAR_PLANE_CULLING);
|
||||
frustum.setToBoundingBox(mSfm->boundingBox(), nearCulling, farCulling);
|
||||
nearCulling = !!(cm & osg::CullSettings::NEAR_PLANE_CULLING);
|
||||
farCulling = !!(cm & osg::CullSettings::FAR_PLANE_CULLING);
|
||||
bb = mSfm->boundingBox();
|
||||
}
|
||||
|
||||
StereoFrustumManager* mSfm;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct ShadowFrustumCallback final : public SceneUtil::MWShadowTechnique::CustomFrustumCallback
|
||||
{
|
||||
@ -95,14 +96,10 @@ namespace Stereo
|
||||
: mCamera(camera)
|
||||
, mShadowTechnique(nullptr)
|
||||
, mShadowFrustumCallback(nullptr)
|
||||
, mMultiview(Stereo::getMultiview())
|
||||
{
|
||||
if (mMultiview)
|
||||
if (Stereo::getMultiview())
|
||||
{
|
||||
#ifdef OSG_HAS_MULTIVIEW
|
||||
mMultiviewFrustumCallback = new MultiviewFrustumCallback(this);
|
||||
mCamera->setInitialFrustumCallback(mMultiviewFrustumCallback);
|
||||
#endif
|
||||
mMultiviewFrustumCallback = std::make_unique<MultiviewFrustumCallback>(this, camera);
|
||||
}
|
||||
|
||||
if (Settings::Manager::getBool("shared shadow maps", "Stereo"))
|
||||
@ -118,13 +115,6 @@ namespace Stereo
|
||||
|
||||
StereoFrustumManager::~StereoFrustumManager()
|
||||
{
|
||||
if (mMultiview)
|
||||
{
|
||||
#ifdef OSG_HAS_MULTIVIEW
|
||||
mCamera->setInitialFrustumCallback(nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (mShadowTechnique)
|
||||
mShadowTechnique->setCustomFrustumCallback(nullptr);
|
||||
}
|
||||
|
@ -38,10 +38,7 @@ namespace SceneUtil
|
||||
|
||||
namespace Stereo
|
||||
{
|
||||
#ifdef OSG_HAS_MULTIVIEW
|
||||
struct MultiviewFrustumCallback;
|
||||
#endif
|
||||
|
||||
struct ShadowFrustumCallback;
|
||||
|
||||
void joinBoundingBoxes(const osg::Matrix& masterProjection, const osg::Matrix& slaveProjection, osg::BoundingBoxd& bb);
|
||||
@ -64,13 +61,10 @@ namespace Stereo
|
||||
osg::ref_ptr<osg::Camera> mCamera;
|
||||
osg::ref_ptr<SceneUtil::MWShadowTechnique> mShadowTechnique;
|
||||
osg::ref_ptr<ShadowFrustumCallback> mShadowFrustumCallback;
|
||||
bool mMultiview;
|
||||
std::map< osgUtil::CullVisitor*, osgUtil::CullVisitor*> mSharedFrustums;
|
||||
osg::BoundingBoxd mBoundingBox;
|
||||
|
||||
#ifdef OSG_HAS_MULTIVIEW
|
||||
osg::ref_ptr<MultiviewFrustumCallback> mMultiviewFrustumCallback;
|
||||
#endif
|
||||
std::unique_ptr<MultiviewFrustumCallback> mMultiviewFrustumCallback;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <osg/FrameBufferObject>
|
||||
#include <osg/GLExtensions>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/Texture2DMultisample>
|
||||
#include <osg/Texture2DArray>
|
||||
#include <osgUtil/RenderStage>
|
||||
#include <osgUtil/CullVisitor>
|
||||
@ -337,6 +338,133 @@ namespace Stereo
|
||||
#endif
|
||||
}
|
||||
|
||||
void setMultiviewMatrices(osg::StateSet* stateset, const std::array<osg::Matrix, 2>& projection, bool createInverseMatrices)
|
||||
{
|
||||
auto* projUniform = stateset->getUniform("projectionMatrixMultiView");
|
||||
if (!projUniform)
|
||||
{
|
||||
projUniform = new osg::Uniform(osg::Uniform::FLOAT_MAT4, "projectionMatrixMultiView", 2);
|
||||
stateset->addUniform(projUniform, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
|
||||
}
|
||||
|
||||
projUniform->setElement(0, projection[0]);
|
||||
projUniform->setElement(1, projection[1]);
|
||||
|
||||
if (createInverseMatrices)
|
||||
{
|
||||
auto* invUniform = stateset->getUniform("invProjectionMatrixMultiView");
|
||||
if (!invUniform)
|
||||
{
|
||||
invUniform = new osg::Uniform(osg::Uniform::FLOAT_MAT4, "invProjectionMatrixMultiView", 2);
|
||||
stateset->addUniform(invUniform, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
|
||||
}
|
||||
|
||||
invUniform->setElement(0, osg::Matrix::inverse(projection[0]));
|
||||
invUniform->setElement(1, osg::Matrix::inverse(projection[1]));
|
||||
}
|
||||
}
|
||||
|
||||
void setMultiviewCompatibleTextureSize(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;
|
||||
case GL_TEXTURE_2D_MULTISAMPLE:
|
||||
static_cast<osg::Texture2DMultisample*>(tex)->setTextureSize(w, h);
|
||||
break;
|
||||
#ifdef OSG_HAS_MULTIVIEW
|
||||
case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
|
||||
static_cast<osg::Texture2DMultisampleArray*>(tex)->setTextureSize(w, h, 2);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
throw std::logic_error("Invalid texture type received");
|
||||
}
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Texture> createMultiviewCompatibleTexture(int width, int height, int samples)
|
||||
{
|
||||
#ifdef OSG_HAS_MULTIVIEW
|
||||
if (Stereo::getMultiview())
|
||||
{
|
||||
if (samples > 1)
|
||||
{
|
||||
auto tex = new osg::Texture2DMultisampleArray();
|
||||
tex->setTextureSize(width, height, 2);
|
||||
tex->setNumSamples(samples);
|
||||
return tex;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto tex = new osg::Texture2DArray();
|
||||
tex->setTextureSize(width, height, 2);
|
||||
return tex;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (samples > 1)
|
||||
{
|
||||
auto tex = new osg::Texture2DMultisample();
|
||||
tex->setTextureSize(width, height);
|
||||
tex->setNumSamples(samples);
|
||||
return tex;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto tex = new osg::Texture2D();
|
||||
tex->setTextureSize(width, height);
|
||||
return tex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
osg::FrameBufferAttachment createMultiviewCompatibleAttachment(osg::Texture* tex)
|
||||
{
|
||||
switch (tex->getTextureTarget())
|
||||
{
|
||||
case GL_TEXTURE_2D:
|
||||
{
|
||||
auto* tex2d = static_cast<osg::Texture2D*>(tex);
|
||||
return osg::FrameBufferAttachment(tex2d);
|
||||
}
|
||||
case GL_TEXTURE_2D_MULTISAMPLE:
|
||||
{
|
||||
auto* tex2dMsaa = static_cast<osg::Texture2DMultisample*>(tex);
|
||||
return osg::FrameBufferAttachment(tex2dMsaa);
|
||||
}
|
||||
#ifdef OSG_HAS_MULTIVIEW
|
||||
case GL_TEXTURE_2D_ARRAY:
|
||||
{
|
||||
auto* tex2dArray = static_cast<osg::Texture2DArray*>(tex);
|
||||
return osg::FrameBufferAttachment(tex2dArray, osg::Camera::FACE_CONTROLLED_BY_MULTIVIEW_SHADER, 0);
|
||||
}
|
||||
case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
|
||||
{
|
||||
auto* tex2dMsaaArray = static_cast<osg::Texture2DMultisampleArray*>(tex);
|
||||
return osg::FrameBufferAttachment(tex2dMsaaArray, osg::Camera::FACE_CONTROLLED_BY_MULTIVIEW_SHADER, 0);
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
throw std::logic_error("Invalid texture type received");
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int osgFaceControlledByMultiviewShader()
|
||||
{
|
||||
#ifdef OSG_HAS_MULTIVIEW
|
||||
return osg::Camera::FACE_CONTROLLED_BY_MULTIVIEW_SHADER;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
class UpdateRenderStagesCallback : public SceneUtil::NodeCallback<UpdateRenderStagesCallback, osg::Node*, osgUtil::CullVisitor*>
|
||||
{
|
||||
public:
|
||||
@ -558,4 +686,111 @@ namespace Stereo
|
||||
textureArray->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE);
|
||||
return textureArray;
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
MultiviewFramebufferResolve::MultiviewFramebufferResolve(osg::FrameBufferObject* msaaFbo, osg::FrameBufferObject* resolveFbo, GLbitfield blitMask)
|
||||
: mResolveFbo(resolveFbo)
|
||||
, mMsaaFbo(msaaFbo)
|
||||
, mBlitMask(blitMask)
|
||||
{
|
||||
}
|
||||
|
||||
void MultiviewFramebufferResolve::resolveImplementation(osg::State& state)
|
||||
{
|
||||
if (mDirtyLayers)
|
||||
setupLayers();
|
||||
|
||||
osg::GLExtensions* ext = state.get<osg::GLExtensions>();
|
||||
|
||||
for (int view : {0, 1})
|
||||
{
|
||||
mResolveLayers[view]->apply(state, osg::FrameBufferObject::BindTarget::DRAW_FRAMEBUFFER);
|
||||
mMsaaLayers[view]->apply(state, osg::FrameBufferObject::BindTarget::READ_FRAMEBUFFER);
|
||||
ext->glBlitFramebuffer(0, 0, mWidth, mHeight, 0, 0, mWidth, mHeight, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
|
||||
}
|
||||
}
|
||||
void MultiviewFramebufferResolve::setupLayers()
|
||||
{
|
||||
mDirtyLayers = false;
|
||||
std::vector<osg::FrameBufferObject::BufferComponent> components;
|
||||
if (mBlitMask & GL_DEPTH_BUFFER_BIT)
|
||||
components.push_back(osg::FrameBufferObject::BufferComponent::PACKED_DEPTH_STENCIL_BUFFER);
|
||||
if (mBlitMask & GL_COLOR_BUFFER_BIT)
|
||||
components.push_back(osg::FrameBufferObject::BufferComponent::COLOR_BUFFER);
|
||||
|
||||
mMsaaLayers = { new osg::FrameBufferObject, new osg::FrameBufferObject };
|
||||
mResolveLayers = { new osg::FrameBufferObject, new osg::FrameBufferObject };
|
||||
for (auto component : components)
|
||||
{
|
||||
const auto& msaaAttachment = mMsaaFbo->getAttachment(component);
|
||||
mMsaaLayers[0]->setAttachment(component, makeSingleLayerAttachmentFromMultilayerAttachment(msaaAttachment, 0));
|
||||
mMsaaLayers[1]->setAttachment(component, makeSingleLayerAttachmentFromMultilayerAttachment(msaaAttachment, 1));
|
||||
|
||||
const auto& resolveAttachment = mResolveFbo->getAttachment(component);
|
||||
mResolveLayers[0]->setAttachment(component, makeSingleLayerAttachmentFromMultilayerAttachment(resolveAttachment, 0));
|
||||
mResolveLayers[1]->setAttachment(component, makeSingleLayerAttachmentFromMultilayerAttachment(resolveAttachment, 1));
|
||||
|
||||
mWidth = msaaAttachment.getTexture()->getTextureWidth();
|
||||
mHeight = msaaAttachment.getTexture()->getTextureHeight();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef OSG_HAS_MULTIVIEW
|
||||
namespace
|
||||
{
|
||||
struct MultiviewFrustumCallback final : public osg::CullSettings::InitialFrustumCallback
|
||||
{
|
||||
MultiviewFrustumCallback(Stereo::InitialFrustumCallback* ifc)
|
||||
: mIfc(ifc)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void setInitialFrustum(osg::CullStack& cullStack, osg::Polytope& frustum) const override
|
||||
{
|
||||
bool nearCulling = false;
|
||||
bool farCulling = false;
|
||||
osg::BoundingBoxd bb;
|
||||
mIfc->setInitialFrustum(cullStack, bb, nearCulling, farCulling);
|
||||
frustum.setToBoundingBox(bb, nearCulling, farCulling);
|
||||
}
|
||||
|
||||
Stereo::InitialFrustumCallback* mIfc;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
InitialFrustumCallback::InitialFrustumCallback(osg::Camera* camera)
|
||||
: mCamera(camera)
|
||||
{
|
||||
#ifdef OSG_HAS_MULTIVIEW
|
||||
camera->setInitialFrustumCallback(new MultiviewFrustumCallback(this));
|
||||
#endif
|
||||
}
|
||||
|
||||
InitialFrustumCallback::~InitialFrustumCallback()
|
||||
{
|
||||
#ifdef OSG_HAS_MULTIVIEW
|
||||
osg::ref_ptr<osg::Camera> camera;
|
||||
if(mCamera.lock(camera))
|
||||
camera->setInitialFrustumCallback(nullptr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <osg/ref_ptr>
|
||||
#include <osg/GL>
|
||||
#include <osg/Camera>
|
||||
#include <osg/FrameBufferObject>
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
@ -40,9 +41,6 @@ namespace Stereo
|
||||
//! Creates a Texture2D as a texture view into a Texture2DArray
|
||||
osg::ref_ptr<osg::Texture2D> createTextureView_Texture2DFromTexture2DArray(osg::Texture2DArray* textureArray, int layer);
|
||||
|
||||
//! Sets up a draw callback on the render stage that performs the MSAA resolve operation
|
||||
void setMultiviewMSAAResolveCallback(osgUtil::RenderStage* renderStage);
|
||||
|
||||
//! Class that manages the specifics of GL_OVR_Multiview aware framebuffers, separating the layers into separate framebuffers, and disabling
|
||||
class MultiviewFramebuffer
|
||||
{
|
||||
@ -86,6 +84,61 @@ namespace Stereo
|
||||
std::array<osg::ref_ptr<osg::Texture2D>, 2> mDepthTexture;
|
||||
};
|
||||
|
||||
//! Sets up a draw callback on the render stage that performs the MSAA resolve operation
|
||||
void setMultiviewMSAAResolveCallback(osgUtil::RenderStage* renderStage);
|
||||
|
||||
//! Sets up or updates multiview matrices for the given stateset
|
||||
void setMultiviewMatrices(osg::StateSet* stateset, const std::array<osg::Matrix, 2>& projection, bool createInverseMatrices = false);
|
||||
|
||||
//! Sets the width/height of a texture by first down-casting it to the appropriate type. Sets depth to 2 always for Texture2DArray and Texture2DMultisampleArray.
|
||||
void setMultiviewCompatibleTextureSize(osg::Texture* tex, int w, int h);
|
||||
|
||||
//! Creates a texture (Texture2D, Texture2DMultisample, Texture2DArray, or Texture2DMultisampleArray) based on multiview settings and sample count.
|
||||
osg::ref_ptr<osg::Texture> createMultiviewCompatibleTexture(int width, int height, int samples);
|
||||
|
||||
//! Returns a framebuffer attachment from the texture, returning a multiview attachment if the texture is one of Texture2DArray or Texture2DMultisampleArray
|
||||
osg::FrameBufferAttachment createMultiviewCompatibleAttachment(osg::Texture* tex);
|
||||
|
||||
//! If OSG has multiview, returns the magic number used to tell OSG to create a multiview attachment. Otherwise returns 0.
|
||||
unsigned int osgFaceControlledByMultiviewShader();
|
||||
|
||||
//! Implements resolving a multisamples multiview framebuffer. Does not automatically reflect changes to the fbo attachments, must call dirty() when the fbo attachments change.
|
||||
class MultiviewFramebufferResolve
|
||||
{
|
||||
public:
|
||||
MultiviewFramebufferResolve(osg::FrameBufferObject* msaaFbo, osg::FrameBufferObject* resolveFbo, GLbitfield blitMask);
|
||||
|
||||
void resolveImplementation(osg::State& state);
|
||||
|
||||
void dirty() { mDirtyLayers = true; }
|
||||
|
||||
const osg::FrameBufferObject* resolveFbo() const { return mResolveFbo; };
|
||||
const osg::FrameBufferObject* msaaFbo() const { return mMsaaFbo; };
|
||||
|
||||
private:
|
||||
void setupLayers();
|
||||
|
||||
osg::ref_ptr<osg::FrameBufferObject> mResolveFbo;
|
||||
std::array<osg::ref_ptr<osg::FrameBufferObject>, 2> mResolveLayers{};
|
||||
osg::ref_ptr<osg::FrameBufferObject> mMsaaFbo;
|
||||
std::array<osg::ref_ptr<osg::FrameBufferObject>, 2> mMsaaLayers{};
|
||||
|
||||
GLbitfield mBlitMask;
|
||||
bool mDirtyLayers = true;
|
||||
int mWidth = -1;
|
||||
int mHeight = -1;
|
||||
};
|
||||
|
||||
//! Wrapper for osg::CullSettings::InitialFrustumCallback, to avoid exposing osg multiview interfaces outside of multiview.cpp
|
||||
struct InitialFrustumCallback
|
||||
{
|
||||
InitialFrustumCallback(osg::Camera* camera);
|
||||
virtual ~InitialFrustumCallback();
|
||||
|
||||
virtual void setInitialFrustum(osg::CullStack& cullStack, osg::BoundingBoxd& bb, bool& nearCulling, bool& farCulling) const = 0;
|
||||
|
||||
osg::observer_ptr<osg::Camera> mCamera;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -97,7 +97,6 @@ namespace Stereo
|
||||
protected:
|
||||
virtual void setDefaults(osg::StateSet* stateset)
|
||||
{
|
||||
stateset->addUniform(new osg::Uniform(osg::Uniform::FLOAT_MAT4, "projectionMatrixMultiView", 2));
|
||||
stateset->addUniform(new osg::Uniform(osg::Uniform::FLOAT_MAT4, "invProjectionMatrixMultiView", 2));
|
||||
}
|
||||
|
||||
@ -195,8 +194,8 @@ namespace Stereo
|
||||
mEyeResolutionOverride = eyeResolution;
|
||||
mEyeResolutionOverriden = true;
|
||||
|
||||
if (mMultiviewFramebuffer)
|
||||
updateStereoFramebuffer();
|
||||
//if (mMultiviewFramebuffer)
|
||||
// updateStereoFramebuffer();
|
||||
}
|
||||
|
||||
void Manager::screenResolutionChanged()
|
||||
@ -302,14 +301,14 @@ 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();
|
||||
//auto samples = Settings::Manager::getInt("antialiasing", "Video");
|
||||
//auto eyeRes = eyeResolution();
|
||||
|
||||
//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 = 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);
|
||||
}
|
||||
|
||||
@ -376,17 +375,12 @@ namespace Stereo
|
||||
|
||||
void Manager::updateMultiviewStateset(osg::StateSet* stateset)
|
||||
{
|
||||
// Update stereo uniforms
|
||||
auto * projectionMatrixMultiViewUniform = stateset->getUniform("projectionMatrixMultiView");
|
||||
auto * invProjectionMatrixMultiViewUniform = stateset->getUniform("invProjectionMatrixMultiView");
|
||||
std::array<osg::Matrix, 2> projectionMatrices;
|
||||
|
||||
for (int view : {0, 1})
|
||||
{
|
||||
auto projectionMatrix = computeEyeViewOffset(view) * computeEyeProjection(view, SceneUtil::AutoDepth::isReversed());
|
||||
auto invProjectionMatrix = osg::Matrix::inverse(projectionMatrix);
|
||||
projectionMatrixMultiViewUniform->setElement(view, projectionMatrix);
|
||||
invProjectionMatrixMultiViewUniform->setElement(view, invProjectionMatrix);
|
||||
}
|
||||
projectionMatrices[view] = computeEyeViewOffset(view) * computeEyeProjection(view, SceneUtil::AutoDepth::isReversed());
|
||||
|
||||
Stereo::setMultiviewMatrices(stateset, projectionMatrices, true);
|
||||
}
|
||||
|
||||
void Manager::setUpdateViewCallback(std::shared_ptr<UpdateViewCallback> cb)
|
||||
|
Loading…
x
Reference in New Issue
Block a user