mirror of https://github.com/OpenMW/openmw.git
Merge branch 'depth_refactor' into 'master'
Depth refactor See merge request OpenMW/openmw!1326fix-static-urls
commit
3d381bf0d3
@ -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
|
Loading…
Reference in New Issue