mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-04-28 21:07:59 +03:00
initial reverse-z depth implementation
This commit is contained in:
parent
10d100f205
commit
70fac33940
46 changed files with 614 additions and 92 deletions
|
@ -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);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue