mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-10-31 07:26:38 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			186 lines
		
	
	
	
		
			6.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			186 lines
		
	
	
	
		
			6.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "depth.hpp"
 | |
| 
 | |
| #include <algorithm>
 | |
| 
 | |
| #include <components/debug/debuglog.hpp>
 | |
| #include <components/settings/settings.hpp>
 | |
| 
 | |
| 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 isDepthFormat(GLenum format)
 | |
|     {
 | |
|         constexpr std::array<GLenum, 8> formats = {
 | |
|             GL_DEPTH_COMPONENT32F,
 | |
|             GL_DEPTH_COMPONENT32F_NV,
 | |
|             GL_DEPTH_COMPONENT16,
 | |
|             GL_DEPTH_COMPONENT24,
 | |
|             GL_DEPTH_COMPONENT32,
 | |
|             GL_DEPTH32F_STENCIL8,
 | |
|             GL_DEPTH32F_STENCIL8_NV,
 | |
|             GL_DEPTH24_STENCIL8,
 | |
|         };
 | |
| 
 | |
|         return std::find(formats.cbegin(), formats.cend(), format) != formats.cend();
 | |
|     }
 | |
| 
 | |
|     bool isDepthStencilFormat(GLenum format)
 | |
|     {
 | |
|         constexpr std::array<GLenum, 8> formats = {
 | |
|             GL_DEPTH32F_STENCIL8,
 | |
|             GL_DEPTH32F_STENCIL8_NV,
 | |
|             GL_DEPTH24_STENCIL8,
 | |
|         };
 | |
| 
 | |
|         return std::find(formats.cbegin(), formats.cend(), format) != formats.cend();
 | |
|     }
 | |
| 
 | |
|     void getDepthFormatSourceFormatAndType(GLenum internalFormat, GLenum& sourceFormat, GLenum& sourceType)
 | |
|     {
 | |
|         switch (internalFormat)
 | |
|         {
 | |
|         case GL_DEPTH_COMPONENT16:
 | |
|         case GL_DEPTH_COMPONENT24:
 | |
|         case GL_DEPTH_COMPONENT32:
 | |
|             sourceType = GL_UNSIGNED_INT;
 | |
|             sourceFormat = GL_DEPTH_COMPONENT;
 | |
|             break;
 | |
|         case GL_DEPTH_COMPONENT32F:
 | |
|         case GL_DEPTH_COMPONENT32F_NV:
 | |
|             sourceType = GL_FLOAT;
 | |
|             sourceFormat = GL_DEPTH_COMPONENT;
 | |
|             break;
 | |
|         case GL_DEPTH24_STENCIL8:
 | |
|             sourceType = GL_UNSIGNED_INT_24_8_EXT;
 | |
|             sourceFormat = GL_DEPTH_STENCIL_EXT;
 | |
|             break;
 | |
|         case GL_DEPTH32F_STENCIL8:
 | |
|         case GL_DEPTH32F_STENCIL8_NV:
 | |
|             sourceType = GL_FLOAT_32_UNSIGNED_INT_24_8_REV;
 | |
|             sourceFormat = GL_DEPTH_STENCIL_EXT;
 | |
|             break;
 | |
|         default:
 | |
|             sourceType = GL_UNSIGNED_INT;
 | |
|             sourceFormat = GL_DEPTH_COMPONENT;
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     GLenum getDepthFormatOfDepthStencilFormat(GLenum internalFormat)
 | |
|     {
 | |
|         switch (internalFormat)
 | |
|         {
 | |
|         case GL_DEPTH24_STENCIL8:
 | |
|             return GL_DEPTH_COMPONENT24;
 | |
|             break;
 | |
|         case GL_DEPTH32F_STENCIL8:
 | |
|             return GL_DEPTH_COMPONENT32F;
 | |
|             break;
 | |
|         case GL_DEPTH32F_STENCIL8_NV:
 | |
|             return GL_DEPTH_COMPONENT32F_NV;
 | |
|             break;
 | |
|         default:
 | |
|             return internalFormat;
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     void SelectDepthFormatOperation::operator()(osg::GraphicsContext* graphicsContext)
 | |
|     {
 | |
|         bool enableReverseZ = false;
 | |
| 
 | |
|         if (Settings::Manager::getBool("reverse z", "Camera"))
 | |
|         {
 | |
|             osg::ref_ptr<osg::GLExtensions> exts = osg::GLExtensions::Get(0, false);
 | |
|             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);
 | |
| 
 | |
|         constexpr char errPreamble[] = "Postprocessing and floating point depth buffers disabled: ";
 | |
|         std::vector<GLenum> requestedFormats;
 | |
|         unsigned int contextID = graphicsContext->getState()->getContextID();
 | |
|         if (SceneUtil::AutoDepth::isReversed())
 | |
|         {
 | |
|             if (osg::isGLExtensionSupported(contextID, "GL_ARB_depth_buffer_float"))
 | |
|             {
 | |
|                 requestedFormats.push_back(GL_DEPTH32F_STENCIL8);
 | |
|             }
 | |
|             else if (osg::isGLExtensionSupported(contextID, "GL_NV_depth_buffer_float"))
 | |
|             {
 | |
|                 requestedFormats.push_back(GL_DEPTH32F_STENCIL8_NV);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 Log(Debug::Warning) << errPreamble << "'GL_ARB_depth_buffer_float' and 'GL_NV_depth_buffer_float' unsupported.";
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         requestedFormats.push_back(GL_DEPTH24_STENCIL8);
 | |
|         if (mSupportedFormats.empty())
 | |
|         {
 | |
|             SceneUtil::AutoDepth::setDepthFormat(requestedFormats.front());
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             for (auto requestedFormat : requestedFormats)
 | |
|             {
 | |
|                 if (std::find(mSupportedFormats.cbegin(), mSupportedFormats.cend(), requestedFormat) != mSupportedFormats.cend())
 | |
|                 {
 | |
|                     SceneUtil::AutoDepth::setDepthFormat(requestedFormat);
 | |
|                     break;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     void AutoDepth::setDepthFormat(GLenum format)
 | |
|     {
 | |
|         sDepthInternalFormat = format;
 | |
|         getDepthFormatSourceFormatAndType(sDepthInternalFormat, sDepthSourceFormat, sDepthSourceType);
 | |
|     }
 | |
| }
 |