initial reverse-z depth implementation

This commit is contained in:
glassmancody.info 2021-06-01 12:15:25 -07:00
parent 10d100f205
commit 70fac33940
46 changed files with 614 additions and 92 deletions

View file

@ -23,10 +23,13 @@
#include <osg/Geometry>
#include <osg/io_utils>
#include <osg/Depth>
#include <osg/ClipControl>
#include <sstream>
#include "shadowsbin.hpp"
#include <components/sceneutil/util.hpp>
namespace {
using namespace osgShadow;
@ -347,6 +350,11 @@ void VDSMCameraCullCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
_projectionMatrix = cv->getProjectionMatrix();
}
bool isOrthographicViewFrustum(const osg::Matrix& m)
{
return m(0,3)==0.0 && m(1,3)==0.0 && m(2,3)==0.0;
}
} // namespace
MWShadowTechnique::ComputeLightSpaceBounds::ComputeLightSpaceBounds(osg::Viewport* viewport, const osg::Matrixd& projectionMatrix, osg::Matrixd& viewMatrix) :
@ -890,6 +898,16 @@ void SceneUtil::MWShadowTechnique::disableFrontFaceCulling()
}
}
void SceneUtil::MWShadowTechnique::enableReverseZ()
{
_reverseZ = true;
}
void SceneUtil::MWShadowTechnique::disableReverseZ()
{
_reverseZ = false;
}
void SceneUtil::MWShadowTechnique::setupCastingShader(Shader::ShaderManager & shaderManager)
{
// This can't be part of the constructor as OSG mandates that there be a trivial constructor available
@ -970,6 +988,9 @@ void MWShadowTechnique::cull(osgUtil::CullVisitor& cv)
return;
}
osg::Matrix shadowProj;
cv.getCurrentCamera()->getUserValue("shadowProj", shadowProj);
ViewDependentData* vdd = getViewDependentData(&cv);
if (!vdd)
@ -985,34 +1006,41 @@ void MWShadowTechnique::cull(osgUtil::CullVisitor& cv)
osg::CullSettings::ComputeNearFarMode cachedNearFarMode = cv.getComputeNearFarMode();
osg::RefMatrix& viewProjectionMatrix = *cv.getProjectionMatrix();
// check whether this main views projection is perspective or orthographic
bool orthographicViewFrustum = viewProjectionMatrix(0,3)==0.0 &&
viewProjectionMatrix(1,3)==0.0 &&
viewProjectionMatrix(2,3)==0.0;
double minZNear = 0.0;
double maxZFar = dbl_max;
bool orthographicViewFrustum;
if (cachedNearFarMode==osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR)
if (_reverseZ)
{
double left, right, top, bottom;
if (orthographicViewFrustum)
{
viewProjectionMatrix.getOrtho(left, right, bottom, top, minZNear, maxZFar);
}
else
{
viewProjectionMatrix.getFrustum(left, right, bottom, top, minZNear, maxZFar);
}
OSG_INFO<<"minZNear="<<minZNear<<", maxZFar="<<maxZFar<<std::endl;
cv.getCurrentCamera()->getUserValue("near", minZNear);
cv.getCurrentCamera()->getUserValue("far", maxZFar);
orthographicViewFrustum = isOrthographicViewFrustum(shadowProj);
}
// set the compute near/far mode to the highest quality setting to ensure we push the near plan out as far as possible
if (settings->getComputeNearFarModeOverride()!=osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR)
else
{
cv.setComputeNearFarMode(settings->getComputeNearFarModeOverride());
osg::RefMatrix& viewProjectionMatrix = *cv.getProjectionMatrix();
// check whether this main views projection is perspective or orthographic
orthographicViewFrustum = isOrthographicViewFrustum(viewProjectionMatrix);
if (cachedNearFarMode==osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR)
{
double left, right, top, bottom;
if (orthographicViewFrustum)
{
viewProjectionMatrix.getOrtho(left, right, bottom, top, minZNear, maxZFar);
}
else
{
viewProjectionMatrix.getFrustum(left, right, bottom, top, minZNear, maxZFar);
}
}
// set the compute near/far mode to the highest quality setting to ensure we push the near plan out as far as possible
if (settings->getComputeNearFarModeOverride()!=osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR)
{
cv.setComputeNearFarMode(settings->getComputeNearFarModeOverride());
}
}
// 1. Traverse main scene graph
@ -1024,6 +1052,9 @@ void MWShadowTechnique::cull(osgUtil::CullVisitor& cv)
cv.popStateSet();
if (_reverseZ)
cv.pushProjectionMatrix(new osg::RefMatrix(shadowProj));
if (cv.getComputeNearFarMode()!=osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR)
{
OSG_INFO<<"Just done main subgraph traversak"<<std::endl;
@ -1063,7 +1094,8 @@ void MWShadowTechnique::cull(osgUtil::CullVisitor& cv)
}
// return compute near far mode back to it's original settings
cv.setComputeNearFarMode(cachedNearFarMode);
if (!_reverseZ)
cv.setComputeNearFarMode(cachedNearFarMode);
OSG_INFO<<"frustum.eye="<<frustum.eye<<", frustum.centerNearPlane, "<<frustum.centerNearPlane<<" distance = "<<(frustum.eye-frustum.centerNearPlane).length()<<std::endl;
@ -1448,6 +1480,8 @@ void MWShadowTechnique::cull(osgUtil::CullVisitor& cv)
prepareStateSetForRenderingShadow(*vdd, cv.getTraversalNumber());
}
if (_reverseZ)
cv.popProjectionMatrix();
// OSG_NOTICE<<"End of shadow setup Projection matrix "<<*cv.getProjectionMatrix()<<std::endl;
}
@ -1636,6 +1670,9 @@ void MWShadowTechnique::createShaders()
_shadowCastingStateSet->addUniform(new osg::Uniform("alphaTestShadows", false));
osg::ref_ptr<osg::Depth> depth = new osg::Depth;
depth->setWriteMask(true);
osg::ref_ptr<osg::ClipControl> clipcontrol = new osg::ClipControl(osg::ClipControl::LOWER_LEFT, osg::ClipControl::NEGATIVE_ONE_TO_ONE);
if (_reverseZ)
_shadowCastingStateSet->setAttribute(clipcontrol, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
_shadowCastingStateSet->setAttribute(depth, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
_shadowCastingStateSet->setMode(GL_DEPTH_CLAMP, osg::StateAttribute::ON);