Merge branch 'depth_refactor' into 'master'

Depth refactor

See merge request OpenMW/openmw!1326
fix-static-urls
AnyOldName3 3 years ago
commit 3d381bf0d3

@ -42,6 +42,7 @@
#include <components/misc/frameratelimiter.hpp>
#include <components/sceneutil/screencapture.hpp>
#include <components/sceneutil/depth.hpp>
#include "mwinput/inputmanagerimp.hpp"
@ -761,6 +762,22 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
osg::ref_ptr<osg::GLExtensions> exts = osg::GLExtensions::Get(0, false);
bool shadersSupported = exts && (exts->glslLanguageVersion >= 1.2f);
bool enableReverseZ = false;
if (Settings::Manager::getBool("reverse z", "Camera"))
{
if (exts && exts->isClipControlSupported)
{
enableReverseZ = true;
Log(Debug::Info) << "Using reverse-z depth buffer";
}
else
Log(Debug::Warning) << "GL_ARB_clip_control not supported: disabling reverse-z depth buffer";
}
else
Log(Debug::Info) << "Using standard depth buffer";
SceneUtil::AutoDepth::setReversed(enableReverseZ);
#if OSG_VERSION_LESS_THAN(3, 6, 6)
// hack fix for https://github.com/openscenegraph/OpenSceneGraph/issues/1028

@ -8,7 +8,7 @@
#include "MyGUI_FactoryManager.h"
#include <components/misc/utf8stream.hpp>
#include <components/sceneutil/util.hpp>
#include <components/sceneutil/depth.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
@ -1221,7 +1221,7 @@ public:
RenderXform renderXform (mCroppedParent, textFormat.mRenderItem->getRenderTarget()->getInfo());
float z = SceneUtil::getReverseZ() ? 1.f : -1.f;
float z = SceneUtil::AutoDepth::isReversed() ? 1.f : -1.f;
GlyphStream glyphStream(textFormat.mFont, static_cast<float>(mCoord.left), static_cast<float>(mCoord.top - mViewTop),
z /*mNode->getNodeDepth()*/, vertices, renderXform);

@ -8,7 +8,7 @@
#include <components/debug/debuglog.hpp>
#include <components/misc/convert.hpp>
#include <components/sceneutil/util.hpp>
#include <components/sceneutil/depth.hpp>
#include <osg/PolygonMode>
#include <osg/PolygonOffset>
#include <osg/ShapeDrawable>
@ -66,7 +66,7 @@ void DebugDrawer::createGeometry()
auto* stateSet = new osg::StateSet;
stateSet->setAttributeAndModes(new osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE), osg::StateAttribute::ON);
stateSet->setAttributeAndModes(new osg::PolygonOffset(SceneUtil::getReverseZ() ? 1.0 : -1.0, SceneUtil::getReverseZ() ? 1.0 : -1.0));
stateSet->setAttributeAndModes(new osg::PolygonOffset(SceneUtil::AutoDepth::isReversed() ? 1.0 : -1.0, SceneUtil::AutoDepth::isReversed() ? 1.0 : -1.0));
osg::ref_ptr<osg::Material> material = new osg::Material;
material->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
stateSet->setAttribute(material);

@ -23,6 +23,7 @@
#include <components/sceneutil/shadow.hpp>
#include <components/settings/settings.hpp>
#include <components/sceneutil/nodecallback.hpp>
#include <components/sceneutil/depth.hpp>
#include "../mwbase/world.hpp"
#include "../mwworld/class.hpp"
@ -132,43 +133,6 @@ namespace MWRender
newStateSet->setTextureMode(7, GL_TEXTURE_2D, osg::StateAttribute::OFF);
newStateSet->setDefine("FORCE_OPAQUE", "0", osg::StateAttribute::ON);
}
if (SceneUtil::getReverseZ() && stateset->getAttribute(osg::StateAttribute::DEPTH))
{
bool depthModified = false;
osg::Depth* depth = static_cast<osg::Depth*>(stateset->getAttribute(osg::StateAttribute::DEPTH));
depth->getUserValue("depthModified", depthModified);
if (!depthModified)
{
if (!newStateSet)
{
newStateSet = new osg::StateSet(*stateset, osg::CopyOp::SHALLOW_COPY);
node.setStateSet(newStateSet);
}
// Setup standard depth ranges
osg::ref_ptr<osg::Depth> newDepth = new osg::Depth(*depth);
switch (newDepth->getFunction())
{
case osg::Depth::LESS:
newDepth->setFunction(osg::Depth::GREATER);
break;
case osg::Depth::LEQUAL:
newDepth->setFunction(osg::Depth::GEQUAL);
break;
case osg::Depth::GREATER:
newDepth->setFunction(osg::Depth::LESS);
break;
case osg::Depth::GEQUAL:
newDepth->setFunction(osg::Depth::LEQUAL);
break;
default:
break;
}
newStateSet->setAttribute(newDepth, osg::StateAttribute::ON);
newDepth->setUserValue("depthModified", true);
}
}
}
traverse(node);
}
@ -200,8 +164,6 @@ namespace MWRender
mCamera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT, osg::Camera::PIXEL_BUFFER_RTT);
mCamera->setClearColor(osg::Vec4(0.f, 0.f, 0.f, 0.f));
mCamera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
const float fovYDegrees = 12.3f;
mCamera->setProjectionMatrixAsPerspective(fovYDegrees, sizeX/static_cast<float>(sizeY), 0.1f, 10000.f); // zNear and zFar are autocomputed
mCamera->setViewport(0, 0, sizeX, sizeY);
mCamera->setRenderOrder(osg::Camera::PRE_RENDER);
mCamera->attach(osg::Camera::COLOR_BUFFER, mTexture, 0, 0, false, Settings::Manager::getInt("antialiasing", "Video"));
@ -211,6 +173,8 @@ namespace MWRender
mCamera->setNodeMask(Mask_RenderToTexture);
SceneUtil::setCameraClearDepth(mCamera);
bool ffp = mResourceSystem->getSceneManager()->getLightingMethod() == SceneUtil::LightingMethod::FFP;
osg::ref_ptr<SceneUtil::LightManager> lightManager = new SceneUtil::LightManager(ffp);
@ -226,9 +190,14 @@ namespace MWRender
defaultMat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(1,1,1,1));
defaultMat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4f(0.f, 0.f, 0.f, 0.f));
stateset->setAttribute(defaultMat);
stateset->addUniform(new osg::Uniform("projectionMatrix", static_cast<osg::Matrixf>(mCamera->getProjectionMatrix())));
stateset->setAttributeAndModes(new osg::Depth, osg::StateAttribute::ON);
const float fovYDegrees = 12.3f;
const float aspectRatio = static_cast<float>(sizeX) / static_cast<float>(sizeY);
const float znear = 0.1f;
const float zfar = 10000.f;
mCamera->setProjectionMatrixAsPerspective(fovYDegrees, aspectRatio, znear, zfar);
osg::Matrixf projectionMatrix = SceneUtil::AutoDepth::isReversed() ? static_cast<osg::Matrixf>(SceneUtil::getReversedZProjectionMatrixAsPerspective(fovYDegrees, aspectRatio, znear, zfar)) : static_cast<osg::Matrixf>(mCamera->getProjectionMatrix());
stateset->addUniform(new osg::Uniform("projectionMatrix", projectionMatrix));
SceneUtil::ShadowManager::disableShadowsForStateSet(stateset);

@ -4,7 +4,6 @@
#include <osg/Texture2D>
#include <osg/Group>
#include <osg/Geometry>
#include <osg/Depth>
#include <osg/TexEnvCombine>
#include <osgDB/WriteFile>
@ -15,8 +14,8 @@
#include <components/debug/debuglog.hpp>
#include <components/sceneutil/workqueue.hpp>
#include <components/sceneutil/util.hpp>
#include <components/sceneutil/nodecallback.hpp>
#include <components/sceneutil/depth.hpp>
#include <components/esm/globalmap.hpp>
@ -326,8 +325,8 @@ namespace MWRender
if (texture)
{
osg::ref_ptr<osg::Geometry> geom = createTexturedQuad(srcLeft, srcTop, srcRight, srcBottom);
auto depth = SceneUtil::createDepth();
depth->setWriteMask(0);
osg::ref_ptr<osg::Depth> depth = new SceneUtil::AutoDepth;
depth->setWriteMask(false);
osg::StateSet* stateset = geom->getOrCreateStateSet();
stateset->setAttribute(depth);
stateset->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);

@ -18,7 +18,7 @@
#include <components/settings/settings.hpp>
#include <components/sceneutil/visitor.hpp>
#include <components/sceneutil/shadow.hpp>
#include <components/sceneutil/util.hpp>
#include <components/sceneutil/depth.hpp>
#include <components/sceneutil/lightmanager.hpp>
#include <components/sceneutil/nodecallback.hpp>
#include <components/files/memorystream.hpp>
@ -178,7 +178,7 @@ osg::ref_ptr<osg::Camera> LocalMap::createOrthographicCamera(float x, float y, f
{
osg::ref_ptr<osg::Camera> camera (new osg::Camera);
if (SceneUtil::getReverseZ())
if (SceneUtil::AutoDepth::isReversed())
camera->setProjectionMatrix(SceneUtil::getReversedZProjectionMatrixAsOrtho(-width/2, width/2, -height/2, height/2, 5, (zmax-zmin) + 10));
else
camera->setProjectionMatrixAsOrtho(-width/2, width/2, -height/2, height/2, 5, (zmax-zmin) + 10);
@ -198,14 +198,10 @@ osg::ref_ptr<osg::Camera> LocalMap::createOrthographicCamera(float x, float y, f
osg::Camera::CullingMode cullingMode = (osg::Camera::DEFAULT_CULLING|osg::Camera::FAR_PLANE_CULLING) & ~(osg::Camera::SMALL_FEATURE_CULLING);
camera->setCullingMode(cullingMode);
osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet;
stateset->setAttribute(new osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::FILL), osg::StateAttribute::OVERRIDE);
if (SceneUtil::getReverseZ())
stateset->setAttributeAndModes(SceneUtil::createDepth(), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
SceneUtil::setCameraClearDepth(camera);
osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet;
stateset->setAttribute(new osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::FILL), osg::StateAttribute::OVERRIDE);
stateset->addUniform(new osg::Uniform("projectionMatrix", static_cast<osg::Matrixf>(camera->getProjectionMatrix())), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
// assign large value to effectively turn off fog

@ -20,6 +20,7 @@
#include <components/sceneutil/visitor.hpp>
#include <components/sceneutil/skeleton.hpp>
#include <components/sceneutil/keyframe.hpp>
#include <components/sceneutil/depth.hpp>
#include <components/settings/settings.hpp>
@ -310,7 +311,7 @@ class DepthClearCallback : public osgUtil::RenderBin::DrawCallback
public:
DepthClearCallback()
{
mDepth = SceneUtil::createDepth();
mDepth = new SceneUtil::AutoDepth;
mDepth->setWriteMask(true);
mStateSet = new osg::StateSet;

@ -9,7 +9,7 @@
#include <osgViewer/Viewer>
#include <components/settings/settings.hpp>
#include <components/sceneutil/util.hpp>
#include <components/sceneutil/depth.hpp>
#include <components/sceneutil/nodecallback.hpp>
#include <components/debug/debuglog.hpp>
@ -140,7 +140,7 @@ namespace MWRender
{
bool softParticles = Settings::Manager::getBool("soft particles", "Shaders");
if (!SceneUtil::getReverseZ() && !softParticles)
if (!SceneUtil::AutoDepth::isReversed() && !softParticles)
return;
osg::GraphicsContext* gc = viewer->getCamera()->getGraphicsContext();
@ -161,7 +161,7 @@ namespace MWRender
return;
}
if (SceneUtil::getReverseZ())
if (SceneUtil::AutoDepth::isReversed())
{
if (osg::isGLExtensionSupported(contextID, "GL_ARB_depth_buffer_float"))
mDepthFormat = GL_DEPTH_COMPONENT32F;

@ -32,7 +32,7 @@
#include <components/settings/settings.hpp>
#include <components/sceneutil/util.hpp>
#include <components/sceneutil/depth.hpp>
#include <components/sceneutil/lightmanager.hpp>
#include <components/sceneutil/statesetupdater.hpp>
#include <components/sceneutil/positionattitudetransform.hpp>
@ -310,13 +310,7 @@ namespace MWRender
, mFieldOfView(std::clamp(Settings::Manager::getFloat("field of view", "Camera"), 1.f, 179.f))
, mFirstPersonFieldOfView(std::clamp(Settings::Manager::getFloat("first person field of view", "Camera"), 1.f, 179.f))
{
bool reverseZ = SceneUtil::getReverseZ();
if (reverseZ)
Log(Debug::Info) << "Using reverse-z depth buffer";
else
Log(Debug::Info) << "Using standard depth buffer";
bool reverseZ = SceneUtil::AutoDepth::isReversed();
auto lightingMethod = SceneUtil::LightManager::getLightingMethodFromString(Settings::Manager::getString("lighting method", "Shaders"));
resourceSystem->getSceneManager()->setParticleSystemMask(MWRender::Mask_ParticleSystem);
@ -538,7 +532,7 @@ namespace MWRender
if (reverseZ)
{
osg::ref_ptr<osg::ClipControl> clipcontrol = new osg::ClipControl(osg::ClipControl::LOWER_LEFT, osg::ClipControl::ZERO_TO_ONE);
mRootNode->getOrCreateStateSet()->setAttributeAndModes(SceneUtil::createDepth(), osg::StateAttribute::ON);
mRootNode->getOrCreateStateSet()->setAttributeAndModes(new SceneUtil::AutoDepth, osg::StateAttribute::ON);
mRootNode->getOrCreateStateSet()->setAttributeAndModes(clipcontrol, osg::StateAttribute::ON);
}
@ -1150,7 +1144,7 @@ namespace MWRender
mViewer->getCamera()->setProjectionMatrixAsPerspective(fov, aspect, mNearClip, mViewDistance);
if (SceneUtil::getReverseZ())
if (SceneUtil::AutoDepth::isReversed())
{
mSharedUniformStateUpdater->setLinearFac(-mNearClip / (mViewDistance - mNearClip) - 1.f);
mSharedUniformStateUpdater->setProjectionMatrix(SceneUtil::getReversedZProjectionMatrixAsPerspective(fov, aspect, mNearClip, mViewDistance));

@ -16,7 +16,7 @@
#include <components/resource/resourcesystem.hpp>
#include <components/resource/scenemanager.hpp>
#include <components/fallback/fallback.hpp>
#include <components/sceneutil/util.hpp>
#include <components/sceneutil/depth.hpp>
#include "vismask.hpp"
@ -56,13 +56,13 @@ namespace
stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
stateset->setTextureAttributeAndModes(0, textures[0], osg::StateAttribute::ON);
auto depth = SceneUtil::createDepth();
osg::ref_ptr<osg::Depth> depth = new SceneUtil::AutoDepth;
depth->setWriteMask(false);
stateset->setAttributeAndModes(depth, osg::StateAttribute::ON);
osg::ref_ptr<osg::PolygonOffset> polygonOffset (new osg::PolygonOffset);
polygonOffset->setUnits(SceneUtil::getReverseZ() ? 1 : -1);
polygonOffset->setFactor(SceneUtil::getReverseZ() ? 1 : -1);
polygonOffset->setUnits(SceneUtil::AutoDepth::isReversed() ? 1 : -1);
polygonOffset->setFactor(SceneUtil::AutoDepth::isReversed() ? 1 : -1);
stateset->setAttributeAndModes(polygonOffset, osg::StateAttribute::ON);
stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);

@ -12,7 +12,7 @@
#include <components/resource/resourcesystem.hpp>
#include <components/resource/scenemanager.hpp>
#include <components/shader/shadermanager.hpp>
#include <components/sceneutil/util.hpp>
#include <components/sceneutil/depth.hpp>
#include <components/settings/settings.hpp>
@ -331,7 +331,7 @@ namespace MWRender
float nearClip = Settings::Manager::getFloat("near clip", "Camera");
float viewDistance = Settings::Manager::getFloat("viewing distance", "Camera");
// each cubemap side sees 90 degrees
if (SceneUtil::getReverseZ())
if (SceneUtil::AutoDepth::isReversed())
rttCamera->setProjectionMatrix(SceneUtil::getReversedZProjectionMatrixAsPerspectiveInf(90.0, w/float(h), nearClip));
else
rttCamera->setProjectionMatrixAsPerspective(90.0, w/float(h), nearClip, viewDistance);

@ -14,7 +14,7 @@
#include <components/sceneutil/controller.hpp>
#include <components/sceneutil/shadow.hpp>
#include <components/sceneutil/visitor.hpp>
#include <components/sceneutil/util.hpp>
#include <components/sceneutil/depth.hpp>
#include <components/resource/scenemanager.hpp>
#include <components/resource/imagemanager.hpp>
@ -338,7 +338,7 @@ namespace MWRender
mEarlyRenderBinRoot->getOrCreateStateSet()->setAttributeAndModes(program, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
}
auto depth = SceneUtil::createDepth();
osg::ref_ptr<osg::Depth> depth = new SceneUtil::AutoDepth;
depth->setWriteMask(false);
mEarlyRenderBinRoot->getOrCreateStateSet()->setAttributeAndModes(depth);
mEarlyRenderBinRoot->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);

@ -25,7 +25,7 @@
#include <components/resource/scenemanager.hpp>
#include <components/resource/imagemanager.hpp>
#include <components/sceneutil/util.hpp>
#include <components/sceneutil/depth.hpp>
#include <components/fallback/fallback.hpp>
@ -811,11 +811,11 @@ namespace MWRender
osg::StateSet* queryStateSet = new osg::StateSet;
if (queryVisible)
{
auto depth = SceneUtil::createDepth();
osg::ref_ptr<osg::Depth> depth = new SceneUtil::AutoDepth;
// This is a trick to make fragments written by the query always use the maximum depth value,
// without having to retrieve the current far clipping distance.
// We want the sun glare to be "infinitely" far away.
double far = SceneUtil::getReverseZ() ? 0.0 : 1.0;
double far = SceneUtil::AutoDepth::isReversed() ? 0.0 : 1.0;
depth->setZNear(far);
depth->setZFar(far);
depth->setWriteMask(false);

@ -27,7 +27,7 @@
#include <components/sceneutil/rtt.hpp>
#include <components/sceneutil/shadow.hpp>
#include <components/sceneutil/util.hpp>
#include <components/sceneutil/depth.hpp>
#include <components/sceneutil/waterutil.hpp>
#include <components/sceneutil/lightmanager.hpp>
@ -268,7 +268,6 @@ public:
void setDefaults(osg::Camera* camera) override
{
SceneUtil::setCameraClearDepth(camera);
camera->setReferenceFrame(osg::Camera::RELATIVE_RF);
camera->setSmallFeatureCullingPixelSize(Settings::Manager::getInt("small feature culling pixel size", "Water"));
camera->setName("RefractionCamera");
@ -344,7 +343,6 @@ public:
void setDefaults(osg::Camera* camera) override
{
SceneUtil::setCameraClearDepth(camera);
camera->setReferenceFrame(osg::Camera::RELATIVE_RF);
camera->setSmallFeatureCullingPixelSize(Settings::Manager::getInt("small feature culling pixel size", "Water"));
camera->setName("ReflectionCamera");
@ -645,7 +643,7 @@ public:
{
stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
stateset->setRenderBinDetails(MWRender::RenderBin_Water, "RenderBin");
osg::ref_ptr<osg::Depth> depth = SceneUtil::createDepth();
osg::ref_ptr<osg::Depth> depth = new SceneUtil::AutoDepth;
depth->setWriteMask(false);
stateset->setAttributeAndModes(depth, osg::StateAttribute::ON);
}

@ -57,7 +57,7 @@ add_component_dir (sceneutil
clone attach visitor util statesetupdater controller skeleton riggeometry morphgeometry lightcontroller
lightmanager lightutil positionattitudetransform workqueue pathgridutil waterutil writescene serialize optimizer
actorutil detourdebugdraw navmesh agentpath shadow mwshadowtechnique recastmesh shadowsbin osgacontroller rtt
screencapture
screencapture depth
)
add_component_dir (nif

@ -16,7 +16,6 @@
#include <components/misc/stringops.hpp>
#include <components/misc/resourcehelpers.hpp>
#include <components/resource/imagemanager.hpp>
#include <components/sceneutil/util.hpp>
#include <components/misc/osguservalues.hpp>
// particle
@ -1838,7 +1837,7 @@ namespace NifOsg
// Depth test flag
stateset->setMode(GL_DEPTH_TEST, zprop->flags&1 ? osg::StateAttribute::ON
: osg::StateAttribute::OFF);
auto depth = SceneUtil::createDepth();
osg::ref_ptr<osg::Depth> depth = new osg::Depth;
// Depth write flag
depth->setWriteMask((zprop->flags>>1)&1);
// Morrowind ignores depth test function

@ -32,6 +32,7 @@
#include <components/sceneutil/optimizer.hpp>
#include <components/sceneutil/visitor.hpp>
#include <components/sceneutil/lightmanager.hpp>
#include <components/sceneutil/depth.hpp>
#include <components/shader/shadervisitor.hpp>
#include <components/shader/shadermanager.hpp>
@ -252,14 +253,14 @@ namespace Resource
{
if (stateset->getRenderingHint() == osg::StateSet::TRANSPARENT_BIN)
{
osg::ref_ptr<osg::Depth> depth = SceneUtil::createDepth();
osg::ref_ptr<osg::Depth> depth = new osg::Depth;
depth->setWriteMask(false);
stateset->setAttributeAndModes(depth, osg::StateAttribute::ON);
}
else if (stateset->getRenderingHint() == osg::StateSet::OPAQUE_BIN)
{
osg::ref_ptr<osg::Depth> depth = SceneUtil::createDepth();
osg::ref_ptr<osg::Depth> depth = new osg::Depth;
depth->setWriteMask(true);
stateset->setAttributeAndModes(depth, osg::StateAttribute::ON);
@ -692,6 +693,9 @@ namespace Resource
SetFilterSettingsControllerVisitor setFilterSettingsControllerVisitor(mMinFilter, mMagFilter, mMaxAnisotropy);
loaded->accept(setFilterSettingsControllerVisitor);
SceneUtil::ReplaceDepthVisitor replaceDepthVisitor;
loaded->accept(replaceDepthVisitor);
osg::ref_ptr<Shader::ShaderVisitor> shaderVisitor (createShaderVisitor());
loaded->accept(*shaderVisitor);

@ -0,0 +1,63 @@
#include "depth.hpp"
#include <algorithm>
#include <SDL_opengl_glext.h>
#include <components/settings/settings.hpp>
#ifndef GL_DEPTH32F_STENCIL8_NV
#define GL_DEPTH32F_STENCIL8_NV 0x8DAC
#endif
namespace SceneUtil
{
void setCameraClearDepth(osg::Camera* camera)
{
camera->setClearDepth(AutoDepth::isReversed() ? 0.0 : 1.0);
}
osg::Matrix getReversedZProjectionMatrixAsPerspectiveInf(double fov, double aspect, double near)
{
double A = 1.0/std::tan(osg::DegreesToRadians(fov)/2.0);
return osg::Matrix(
A/aspect, 0, 0, 0,
0, A, 0, 0,
0, 0, 0, -1,
0, 0, near, 0
);
}
osg::Matrix getReversedZProjectionMatrixAsPerspective(double fov, double aspect, double near, double far)
{
double A = 1.0/std::tan(osg::DegreesToRadians(fov)/2.0);
return osg::Matrix(
A/aspect, 0, 0, 0,
0, A, 0, 0,
0, 0, near/(far-near), -1,
0, 0, (far*near)/(far - near), 0
);
}
osg::Matrix getReversedZProjectionMatrixAsOrtho(double left, double right, double bottom, double top, double near, double far)
{
return osg::Matrix(
2/(right-left), 0, 0, 0,
0, 2/(top-bottom), 0, 0,
0, 0, 1/(far-near), 0,
(right+left)/(left-right), (top+bottom)/(bottom-top), far/(far-near), 1
);
}
bool isFloatingPointDepthFormat(GLenum format)
{
constexpr std::array<GLenum, 4> formats = {
GL_DEPTH_COMPONENT32F,
GL_DEPTH_COMPONENT32F_NV,
GL_DEPTH32F_STENCIL8,
GL_DEPTH32F_STENCIL8_NV,
};
return std::find(formats.cbegin(), formats.cend(), format) != formats.cend();
}
}

@ -0,0 +1,117 @@
#ifndef OPENMW_COMPONENTS_SCENEUTIL_DEPTH_H
#define OPENMW_COMPONENTS_SCENEUTIL_DEPTH_H
#include <osg/Depth>
#include "util.hpp"
namespace SceneUtil
{
// Sets camera clear depth to 0 if reversed depth buffer is in use, 1 otherwise.
void setCameraClearDepth(osg::Camera* camera);
// Returns a perspective projection matrix for use with a reversed z-buffer
// and an infinite far plane. This is derived by mapping the default z-range
// of [0,1] to [1,0], then taking the limit as far plane approaches infinity.
osg::Matrix getReversedZProjectionMatrixAsPerspectiveInf(double fov, double aspect, double near);
// Returns a perspective projection matrix for use with a reversed z-buffer.
osg::Matrix getReversedZProjectionMatrixAsPerspective(double fov, double aspect, double near, double far);
// Returns an orthographic projection matrix for use with a reversed z-buffer.
osg::Matrix getReversedZProjectionMatrixAsOrtho(double left, double right, double bottom, double top, double near, double far);
// Returns true if the GL format is a floating point depth format.
bool isFloatingPointDepthFormat(GLenum format);
// Brief wrapper around an osg::Depth that applies the reversed depth function when a reversed depth buffer is in use
class AutoDepth : public osg::Depth
{
public:
AutoDepth(osg::Depth::Function func=osg::Depth::LESS, double zNear=0.0, double zFar=1.0, bool writeMask=true)
{
setFunction(func);
setZNear(zNear);
setZFar(zFar);
setWriteMask(writeMask);
}
AutoDepth(const osg::Depth& copy, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY) : osg::Depth(copy, copyop) {}
osg::Object* cloneType() const override { return new AutoDepth; }
osg::Object* clone(const osg::CopyOp& copyop) const override { return new AutoDepth(*this,copyop); }
void apply(osg::State& state) const override
{
glDepthFunc(static_cast<GLenum>(AutoDepth::isReversed() ? getReversedDepthFunction() : getFunction()));
glDepthMask(static_cast<GLboolean>(getWriteMask()));
#if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE) || defined(OSG_GLES3_AVAILABLE)
glDepthRangef(getZNear(),getZFar());
#else
glDepthRange(getZNear(),getZFar());
#endif
}
static void setReversed(bool reverseZ)
{
static bool init = false;
if (!init)
{
AutoDepth::sReversed = reverseZ;
init = true;
}
}
static bool isReversed()
{
return AutoDepth::sReversed;
}
private:
static inline bool sReversed = false;
osg::Depth::Function getReversedDepthFunction() const
{
const osg::Depth::Function func = getFunction();
switch (func)
{
case osg::Depth::LESS:
return osg::Depth::GREATER;
case osg::Depth::LEQUAL:
return osg::Depth::GEQUAL;
case osg::Depth::GREATER:
return osg::Depth::LESS;
case osg::Depth::GEQUAL:
return osg::Depth::LEQUAL;
default:
return func;
}
}
};
// Replaces all nodes osg::Depth state attributes with SceneUtil::AutoDepth.
class ReplaceDepthVisitor : public osg::NodeVisitor
{
public:
ReplaceDepthVisitor() : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) {}
void apply(osg::Node& node) override
{
osg::StateSet* stateSet = node.getStateSet();
if (stateSet)
{
if (osg::Depth* depth = static_cast<osg::Depth*>(stateSet->getAttribute(osg::StateAttribute::DEPTH)))
stateSet->setAttribute(new SceneUtil::AutoDepth(*depth));
};
traverse(node);
}
};
}
#endif

@ -27,8 +27,6 @@
#include <sstream>
#include <components/sceneutil/util.hpp>
#include "shadowsbin.hpp"
namespace {
@ -1652,11 +1650,8 @@ void MWShadowTechnique::createShaders()
_shadowCastingStateSet->addUniform(new osg::Uniform("alphaTestShadows", false));
osg::ref_ptr<osg::Depth> depth = new osg::Depth;
depth->setWriteMask(true);
if (SceneUtil::getReverseZ())
{
osg::ref_ptr<osg::ClipControl> clipcontrol = new osg::ClipControl(osg::ClipControl::LOWER_LEFT, osg::ClipControl::NEGATIVE_ONE_TO_ONE);
_shadowCastingStateSet->setAttribute(clipcontrol, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
}
osg::ref_ptr<osg::ClipControl> clipcontrol = new osg::ClipControl(osg::ClipControl::LOWER_LEFT, osg::ClipControl::NEGATIVE_ONE_TO_ONE);
_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);

@ -42,7 +42,7 @@
#include <iterator>
#include <components/sceneutil/util.hpp>
#include <components/sceneutil/depth.hpp>
using namespace osgUtil;
@ -1597,8 +1597,8 @@ bool Optimizer::MergeGeometryVisitor::mergeGroup(osg::Group& group)
}
if (_alphaBlendingActive && _mergeAlphaBlending && !geom->getStateSet())
{
auto d = createDepth();
d->setWriteMask(0);
osg::ref_ptr<osg::Depth> d = new SceneUtil::AutoDepth;
d->setWriteMask(false);
geom->getOrCreateStateSet()->setAttribute(d);
}
}

@ -8,6 +8,7 @@
#include <components/sceneutil/nodecallback.hpp>
#include <components/settings/settings.hpp>
#include <components/sceneutil/depth.hpp>
namespace SceneUtil
{
@ -69,6 +70,7 @@ namespace SceneUtil
camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
camera->setViewport(0, 0, mTextureWidth, mTextureHeight);
SceneUtil::setCameraClearDepth(camera);
setDefaults(mViewDependentDataMap[cv]->mCamera.get());

@ -4,8 +4,6 @@
#include <sstream>
#include <iomanip>
#include <SDL_opengl_glext.h>
#include <osg/Node>
#include <osg/NodeVisitor>
#include <osg/TexGen>
@ -16,27 +14,8 @@
#include <components/resource/imagemanager.hpp>
#include <components/resource/scenemanager.hpp>
#include <components/settings/settings.hpp>
#include <components/debug/debuglog.hpp>
#include <components/sceneutil/nodecallback.hpp>
#ifndef GL_DEPTH32F_STENCIL8_NV
#define GL_DEPTH32F_STENCIL8_NV 0x8DAC
#endif
namespace
{
bool isReverseZSupported()
{
if (!Settings::Manager::mDefaultSettings.count({"Camera", "reverse z"}))
return false;
auto ext = osg::GLExtensions::Get(0, false);
return Settings::Manager::getBool("reverse z", "Camera") && ext && ext->isClipControlSupported;
}
}
namespace SceneUtil
{
@ -338,81 +317,4 @@ bool attachAlphaToCoverageFriendlyFramebufferToCamera(osg::Camera* camera, osg::
return addMSAAIntermediateTarget;
}
void attachAlphaToCoverageFriendlyDepthColor(osg::Camera* camera, osg::Texture2D* colorTex, osg::Texture2D* depthTex, GLenum depthFormat)
{
bool addMSAAIntermediateTarget = Settings::Manager::getBool("antialias alpha test", "Shaders") && Settings::Manager::getInt("antialiasing", "Video") > 1;
if (isFloatingPointDepthFormat(depthFormat) && addMSAAIntermediateTarget)
{
camera->attach(osg::Camera::COLOR_BUFFER0, colorTex);
camera->attach(osg::Camera::DEPTH_BUFFER, depthTex);
camera->addCullCallback(new AttachMultisampledDepthColorCallback(colorTex, depthTex, 2, 1));
}
else
{
attachAlphaToCoverageFriendlyFramebufferToCamera(camera, osg::Camera::COLOR_BUFFER, colorTex);
camera->attach(osg::Camera::DEPTH_BUFFER, depthTex);
}
}
bool getReverseZ()
{
static bool reverseZ = isReverseZSupported();
return reverseZ;
}
void setCameraClearDepth(osg::Camera* camera)
{
camera->setClearDepth(getReverseZ() ? 0.0 : 1.0);
}
osg::ref_ptr<osg::Depth> createDepth()
{
return new osg::Depth(getReverseZ() ? osg::Depth::GEQUAL : osg::Depth::LEQUAL);
}
osg::Matrix getReversedZProjectionMatrixAsPerspectiveInf(double fov, double aspect, double near)
{
double A = 1.0/std::tan(osg::DegreesToRadians(fov)/2.0);
return osg::Matrix(
A/aspect, 0, 0, 0,
0, A, 0, 0,
0, 0, 0, -1,
0, 0, near, 0
);
}
osg::Matrix getReversedZProjectionMatrixAsPerspective(double fov, double aspect, double near, double far)
{
double A = 1.0/std::tan(osg::DegreesToRadians(fov)/2.0);
return osg::Matrix(
A/aspect, 0, 0, 0,
0, A, 0, 0,
0, 0, near/(far-near), -1,
0, 0, (far*near)/(far - near), 0
);
}
osg::Matrix getReversedZProjectionMatrixAsOrtho(double left, double right, double bottom, double top, double near, double far)
{
return osg::Matrix(
2/(right-left), 0, 0, 0,
0, 2/(top-bottom), 0, 0,
0, 0, 1/(far-near), 0,
(right+left)/(left-right), (top+bottom)/(bottom-top), far/(far-near), 1
);
}
bool isFloatingPointDepthFormat(GLenum format)
{
constexpr std::array<GLenum, 4> formats = {
GL_DEPTH_COMPONENT32F,
GL_DEPTH_COMPONENT32F_NV,
GL_DEPTH32F_STENCIL8,
GL_DEPTH32F_STENCIL8_NV,
};
return std::find(formats.cbegin(), formats.cend(), format) != formats.cend();
}
}

@ -6,7 +6,6 @@
#include <osg/Camera>
#include <osg/Texture2D>
#include <osg/Vec4f>
#include <osg/Depth>
#include <components/resource/resourcesystem.hpp>
@ -64,31 +63,6 @@ namespace SceneUtil
// Alpha-to-coverage requires a multisampled framebuffer, so we need to set that up for RTTs
bool attachAlphaToCoverageFriendlyFramebufferToCamera(osg::Camera* camera, osg::Camera::BufferComponent buffer, osg::Texture* texture, unsigned int level = 0, unsigned int face = 0, bool mipMapGeneration = false);
void attachAlphaToCoverageFriendlyDepthColor(osg::Camera* camera, osg::Texture2D* colorTex, osg::Texture2D* depthTex, GLenum depthFormat);
bool getReverseZ();
void setCameraClearDepth(osg::Camera* camera);
// Returns a suitable depth state attribute dependent on whether a reverse-z
// depth buffer is in use.
osg::ref_ptr<osg::Depth> createDepth();
// Returns a perspective projection matrix for use with a reversed z-buffer
// and an infinite far plane. This is derived by mapping the default z-range
// of [0,1] to [1,0], then taking the limit as far plane approaches
// infinity.
osg::Matrix getReversedZProjectionMatrixAsPerspectiveInf(double fov, double aspect, double near);
// Returns a perspective projection matrix for use with a reversed z-buffer.
osg::Matrix getReversedZProjectionMatrixAsPerspective(double fov, double aspect, double near, double far);
// Returns an orthographic projection matrix for use with a reversed z-buffer.
osg::Matrix getReversedZProjectionMatrixAsOrtho(double left, double right, double bottom, double top, double near, double far);
// Returns true if the GL format is a floating point depth format
bool isFloatingPointDepthFormat(GLenum format);
}
#endif

@ -5,7 +5,7 @@
#include <osg/Material>
#include <osg/StateSet>
#include "util.hpp"
#include "depth.hpp"
namespace SceneUtil
{
@ -78,7 +78,7 @@ namespace SceneUtil
stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
auto depth = createDepth();
osg::ref_ptr<osg::Depth> depth = new SceneUtil::AutoDepth;
depth->setWriteMask(false);
stateset->setAttributeAndModes(depth, osg::StateAttribute::ON);

@ -21,7 +21,7 @@
#include <components/vfs/manager.hpp>
#include <components/sceneutil/riggeometry.hpp>
#include <components/sceneutil/morphgeometry.hpp>
#include <components/sceneutil/util.hpp>
#include <components/sceneutil/depth.hpp>
#include "removedalphafunc.hpp"
#include "shadermanager.hpp"
@ -567,7 +567,7 @@ namespace Shader
{
softParticles = true;
auto depth = SceneUtil::createDepth();
auto depth = new SceneUtil::AutoDepth;
depth->setWriteMask(false);
writableStateSet->setAttributeAndModes(depth, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
writableStateSet->addUniform(new osg::Uniform("particleSize", partsys->getDefaultParticleTemplate().getSizeRange().maximum));

@ -8,7 +8,7 @@
#include <osg/BlendFunc>
#include <components/shader/shadermanager.hpp>
#include <components/sceneutil/util.hpp>
#include <components/sceneutil/depth.hpp>
#include <mutex>
@ -87,7 +87,7 @@ namespace
osg::ref_ptr<osg::Depth> mValue;
EqualDepth()
: mValue(new osg::Depth)
: mValue(new SceneUtil::AutoDepth)
{
mValue->setFunction(osg::Depth::EQUAL);
}
@ -106,7 +106,7 @@ namespace
osg::ref_ptr<osg::Depth> mValue;
LequalDepth()
: mValue(SceneUtil::createDepth())
: mValue(new SceneUtil::AutoDepth)
{
}
};

Loading…
Cancel
Save