1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-16 21:59:55 +00:00
openmw/components/sceneutil/depth.hpp
madsbuvi dd5901d351 Initial commit
Multiview shaders.

Refactor Frustum management

Rewrite shared shadow map

cull mask should respect stereo

Stereo savegame screencap

LocalMap refactoring

use the vertex buffer hint instead of the display list patch to enable/disable display lists

Character preview fixes
2022-04-28 21:05:34 +02:00

190 lines
6 KiB
C++

#ifndef OPENMW_COMPONENTS_SCENEUTIL_DEPTH_H
#define OPENMW_COMPONENTS_SCENEUTIL_DEPTH_H
#include <osg/Depth>
#include "util.hpp"
#ifndef GL_DEPTH32F_STENCIL8_NV
#define GL_DEPTH32F_STENCIL8_NV 0x8DAC
#endif
#ifndef GL_DEPTH32F_STENCIL8
#define GL_DEPTH32F_STENCIL8 0x8CAD
#endif
#ifndef GL_FLOAT_32_UNSIGNED_INT_24_8_REV
#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD
#endif
#ifndef GL_DEPTH24_STENCIL8
#define GL_DEPTH24_STENCIL8 0x88F0
#endif
#ifndef GL_DEPTH_STENCIL_EXT
#define GL_DEPTH_STENCIL_EXT 0x84F9
#endif
#ifndef GL_UNSIGNED_INT_24_8_EXT
#define GL_UNSIGNED_INT_24_8_EXT 0x84FA
#endif
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);
// Returns true if the GL format is a depth format
bool isDepthFormat(GLenum format);
// Returns true if the GL format is a depth+stencil format
bool isDepthStencilFormat(GLenum format);
// Returns the corresponding source format and type for the given internal format
void getDepthFormatSourceFormatAndType(GLenum internalFormat, GLenum& sourceFormat, GLenum& sourceType);
// Converts depth-stencil formats to their corresponding depth formats.
GLenum getDepthFormatOfDepthStencilFormat(GLenum internalFormat);
// 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;
}
static void setDepthFormat(GLenum format);
static GLenum depthInternalFormat()
{
return AutoDepth::sDepthInternalFormat;
}
static GLenum depthSourceFormat()
{
return AutoDepth::sDepthSourceFormat;
}
static GLenum depthSourceType()
{
return AutoDepth::sDepthSourceType;
}
private:
static inline bool sReversed = false;
static inline GLenum sDepthSourceFormat = GL_DEPTH_COMPONENT;
static inline GLenum sDepthInternalFormat = GL_DEPTH_COMPONENT24;
static inline GLenum sDepthSourceType = GL_UNSIGNED_INT;
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);
}
};
class SelectDepthFormatOperation : public osg::GraphicsOperation
{
public:
SelectDepthFormatOperation() : GraphicsOperation("SelectDepthFormatOperation", false)
{}
void operator()(osg::GraphicsContext* graphicsContext) override;
void setSupportedFormats(const std::vector<GLenum>& supportedFormats)
{
mSupportedFormats = supportedFormats;
}
private:
std::vector<GLenum> mSupportedFormats;
};
}
#endif