2022-04-04 20:51:23 +00:00
|
|
|
#include "multiview.hpp"
|
|
|
|
|
|
|
|
#include <osg/DisplaySettings>
|
|
|
|
#include <osg/Texture2D>
|
|
|
|
#include <osg/Texture2DArray>
|
|
|
|
#include <osg/Texture2DMultisample>
|
|
|
|
#include <osg/io_utils>
|
|
|
|
|
|
|
|
#include <osgUtil/CullVisitor>
|
|
|
|
#include <osgUtil/RenderStage>
|
|
|
|
|
|
|
|
#include <osgViewer/Renderer>
|
|
|
|
#include <osgViewer/Viewer>
|
|
|
|
|
|
|
|
#include <map>
|
|
|
|
#include <string>
|
|
|
|
|
2022-10-12 23:49:24 +00:00
|
|
|
#include <components/sceneutil/color.hpp>
|
2022-04-04 20:51:23 +00:00
|
|
|
#include <components/sceneutil/mwshadowtechnique.hpp>
|
|
|
|
|
|
|
|
#include <components/settings/settings.hpp>
|
|
|
|
|
|
|
|
#include "frustum.hpp"
|
|
|
|
|
|
|
|
namespace Stereo
|
|
|
|
{
|
2022-07-11 13:59:56 +00:00
|
|
|
struct MultiviewFrustumCallback final : public Stereo::InitialFrustumCallback
|
2022-04-04 20:51:23 +00:00
|
|
|
{
|
2022-07-11 13:59:56 +00:00
|
|
|
MultiviewFrustumCallback(StereoFrustumManager* sfm, osg::Camera* camera)
|
|
|
|
: Stereo::InitialFrustumCallback(camera)
|
|
|
|
, mSfm(sfm)
|
2022-04-04 20:51:23 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2022-07-11 13:59:56 +00:00
|
|
|
void setInitialFrustum(
|
|
|
|
osg::CullStack& cullStack, osg::BoundingBoxd& bb, bool& nearCulling, bool& farCulling) const override
|
2022-04-04 20:51:23 +00:00
|
|
|
{
|
|
|
|
auto cm = cullStack.getCullingMode();
|
2022-07-11 13:59:56 +00:00
|
|
|
nearCulling = !!(cm & osg::CullSettings::NEAR_PLANE_CULLING);
|
|
|
|
farCulling = !!(cm & osg::CullSettings::FAR_PLANE_CULLING);
|
|
|
|
bb = mSfm->boundingBox();
|
2022-04-04 20:51:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
StereoFrustumManager* mSfm;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ShadowFrustumCallback final : public SceneUtil::MWShadowTechnique::CustomFrustumCallback
|
|
|
|
{
|
|
|
|
ShadowFrustumCallback(StereoFrustumManager* parent)
|
|
|
|
: mParent(parent)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void operator()(osgUtil::CullVisitor& cv, osg::BoundingBoxd& customClipSpace,
|
|
|
|
osgUtil::CullVisitor*& sharedFrustumHint) override
|
|
|
|
{
|
|
|
|
mParent->customFrustumCallback(cv, customClipSpace, sharedFrustumHint);
|
|
|
|
}
|
|
|
|
|
|
|
|
StereoFrustumManager* mParent;
|
|
|
|
};
|
|
|
|
|
|
|
|
void joinBoundingBoxes(
|
|
|
|
const osg::Matrix& masterProjection, const osg::Matrix& slaveProjection, osg::BoundingBoxd& bb)
|
|
|
|
{
|
|
|
|
static const std::array<osg::Vec3d, 8> clipCorners = { {
|
|
|
|
{ -1.0, -1.0, -1.0 },
|
|
|
|
{ 1.0, -1.0, -1.0 },
|
|
|
|
{ 1.0, -1.0, 1.0 },
|
|
|
|
{ -1.0, -1.0, 1.0 },
|
|
|
|
{ -1.0, 1.0, -1.0 },
|
|
|
|
{ 1.0, 1.0, -1.0 },
|
|
|
|
{ 1.0, 1.0, 1.0 },
|
2022-09-13 22:08:19 +00:00
|
|
|
{ -1.0, 1.0, 1.0 },
|
2022-04-04 20:51:23 +00:00
|
|
|
} };
|
|
|
|
|
|
|
|
osg::Matrix slaveClipToView;
|
|
|
|
slaveClipToView.invert(slaveProjection);
|
|
|
|
|
|
|
|
for (const auto& clipCorner : clipCorners)
|
|
|
|
{
|
|
|
|
auto masterViewVertice = clipCorner * slaveClipToView;
|
|
|
|
auto masterClipVertice = masterViewVertice * masterProjection;
|
|
|
|
bb.expandBy(masterClipVertice);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
StereoFrustumManager::StereoFrustumManager(osg::Camera* camera)
|
|
|
|
: mCamera(camera)
|
|
|
|
, mShadowTechnique(nullptr)
|
|
|
|
, mShadowFrustumCallback(nullptr)
|
|
|
|
{
|
2022-07-11 13:59:56 +00:00
|
|
|
if (Stereo::getMultiview())
|
2022-04-04 20:51:23 +00:00
|
|
|
{
|
2022-07-11 13:59:56 +00:00
|
|
|
mMultiviewFrustumCallback = std::make_unique<MultiviewFrustumCallback>(this, camera);
|
2022-04-04 20:51:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (Settings::Manager::getBool("shared shadow maps", "Stereo"))
|
|
|
|
{
|
|
|
|
mShadowFrustumCallback = new ShadowFrustumCallback(this);
|
|
|
|
auto* renderer = static_cast<osgViewer::Renderer*>(mCamera->getRenderer());
|
|
|
|
for (auto* sceneView : { renderer->getSceneView(0), renderer->getSceneView(1) })
|
|
|
|
{
|
|
|
|
mSharedFrustums[sceneView->getCullVisitorRight()] = sceneView->getCullVisitorLeft();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
StereoFrustumManager::~StereoFrustumManager()
|
|
|
|
{
|
|
|
|
if (mShadowTechnique)
|
|
|
|
mShadowTechnique->setCustomFrustumCallback(nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void StereoFrustumManager::setShadowTechnique(SceneUtil::MWShadowTechnique* shadowTechnique)
|
|
|
|
{
|
|
|
|
if (mShadowTechnique)
|
|
|
|
mShadowTechnique->setCustomFrustumCallback(nullptr);
|
|
|
|
mShadowTechnique = shadowTechnique;
|
|
|
|
if (mShadowTechnique)
|
|
|
|
mShadowTechnique->setCustomFrustumCallback(mShadowFrustumCallback);
|
|
|
|
}
|
|
|
|
|
|
|
|
void StereoFrustumManager::customFrustumCallback(
|
|
|
|
osgUtil::CullVisitor& cv, osg::BoundingBoxd& customClipSpace, osgUtil::CullVisitor*& sharedFrustumHint)
|
|
|
|
{
|
|
|
|
auto it = mSharedFrustums.find(&cv);
|
|
|
|
if (it != mSharedFrustums.end())
|
|
|
|
{
|
|
|
|
sharedFrustumHint = it->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
customClipSpace = mBoundingBox;
|
|
|
|
}
|
|
|
|
|
|
|
|
void StereoFrustumManager::update(std::array<osg::Matrix, 2> projections)
|
|
|
|
{
|
|
|
|
mBoundingBox.init();
|
|
|
|
for (auto& projection : projections)
|
|
|
|
joinBoundingBoxes(mCamera->getProjectionMatrix(), projection, mBoundingBox);
|
|
|
|
}
|
|
|
|
}
|