diff --git a/panda/src/glstuff/glGraphicsBuffer_src.cxx b/panda/src/glstuff/glGraphicsBuffer_src.cxx index f46c8288f1..50491df38d 100644 --- a/panda/src/glstuff/glGraphicsBuffer_src.cxx +++ b/panda/src/glstuff/glGraphicsBuffer_src.cxx @@ -864,14 +864,22 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot, case RTP_depth_stencil: if (_fb_properties.get_depth_bits() > 24 || _fb_properties.get_float_depth()) { - gl_format = GL_DEPTH32F_STENCIL8; + if (!glgsg->_use_remapped_depth_range) { + gl_format = GL_DEPTH32F_STENCIL8; + } else { + gl_format = GL_DEPTH32F_STENCIL8_NV; + } } else { gl_format = GL_DEPTH24_STENCIL8; } break; case RTP_depth: if (_fb_properties.get_float_depth()) { - gl_format = GL_DEPTH_COMPONENT32F; + if (!glgsg->_use_remapped_depth_range) { + gl_format = GL_DEPTH_COMPONENT32F; + } else { + gl_format = GL_DEPTH_COMPONENT32F_NV; + } } else if (_fb_properties.get_depth_bits() > 24) { gl_format = GL_DEPTH_COMPONENT32; } else if (_fb_properties.get_depth_bits() > 16) { diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 8df6b605bb..74080f274f 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -2997,6 +2997,50 @@ reset() { } #endif + // Set depth range from zero to one if requested. +#ifndef OPENGLES + _use_depth_zero_to_one = false; + _use_remapped_depth_range = false; + + if (gl_depth_zero_to_one) { + if (is_at_least_gl_version(4, 5) || has_extension("GL_ARB_clip_control")) { + PFNGLCLIPCONTROLPROC pglClipControl = + (PFNGLCLIPCONTROLPROC)get_extension_func("glClipControl"); + + if (pglClipControl != nullptr) { + pglClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE); + _use_depth_zero_to_one = true; + + if (GLCAT.is_debug()) { + GLCAT.debug() + << "Set zero-to-one depth using glClipControl\n"; + } + } + }/* else if (has_extension("GL_NV_depth_buffer_float")) { + // Alternatively, all GeForce 8+ and even some AMD drivers support this + // extension, which (unlike the core glDepthRange, which clamps its + // input parameters) can compensate for the built-in depth remapping. + _glDepthRangedNV = (PFNGLDEPTHRANGEDNVPROC)get_extension_func("glDepthRangedNV"); + + if (_glDepthRangedNV != nullptr) { + _glDepthRangedNV(-1.0, 1.0); + _use_depth_zero_to_one = true; + _use_remapped_depth_range = true; + + if (GLCAT.is_debug()) { + GLCAT.debug() + << "Set zero-to-one depth using glDepthRangedNV\n"; + } + } + }*/ + + if (!_use_depth_zero_to_one) { + GLCAT.warning() + << "Zero-to-one depth was requested, but driver does not support it.\n"; + } + } +#endif + // Set up all the enableddisabled flags to GL's known initial values: // everything off. _multisample_mode = 0; @@ -3646,6 +3690,19 @@ calc_projection_mat(const Lens *lens) { lens->get_coordinate_system()) * lens->get_projection_mat(_current_stereo_channel); +#ifndef OPENGLES + if (_use_depth_zero_to_one) { + // If we requested that the OpenGL NDC Z goes from zero to one like in + // Direct3D, we need to scale the projection matrix, which assumes -1..1. + static const LMatrix4 rescale_mat + (1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 0.5, 0, + 0, 0, 0.5, 1); + result *= rescale_mat; + } +#endif + if (_scene_setup->get_inverted()) { // If the scene is supposed to be inverted, then invert the projection // matrix. @@ -7452,7 +7509,13 @@ do_issue_depth_offset() { glDepthRangef((GLclampf)min_value, (GLclampf)max_value); #else // Mainline OpenGL uses a double-precision call. - glDepthRange((GLclampd)min_value, (GLclampd)max_value); + if (!_use_remapped_depth_range) { + glDepthRange((GLclampd)min_value, (GLclampd)max_value); + } else { + // If we have a remapped depth range, we should adjust the values to range + // from -1 to 1. We need to use an NV extension to pass unclamped values. + _glDepthRangedNV(min_value * 2.0 - 1.0, max_value * 2.0 - 1.0); + } #endif // OPENGLES report_my_gl_errors(); diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index c0f75a21d5..d00478a58d 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -743,6 +743,12 @@ protected: #endif public: +#ifndef OPENGLES + bool _use_depth_zero_to_one; + bool _use_remapped_depth_range; + PFNGLDEPTHRANGEDNVPROC _glDepthRangedNV; +#endif + bool _supports_point_parameters; PFNGLPOINTPARAMETERFVPROC _glPointParameterfv; bool _supports_point_sprite; diff --git a/panda/src/glstuff/glmisc_src.cxx b/panda/src/glstuff/glmisc_src.cxx index fd2bcf7aee..08e200a4a0 100644 --- a/panda/src/glstuff/glmisc_src.cxx +++ b/panda/src/glstuff/glmisc_src.cxx @@ -313,6 +313,13 @@ ConfigVariableEnum gl_coordinate_system "creating a shader-only application, it may be easier and " "more efficient to set this to default.")); +ConfigVariableBool gl_depth_zero_to_one + ("gl-depth-zero-to-one", false, + PRC_DESC("Normally, OpenGL uses an NDC coordinate space wherein the Z " + "ranges from -1 to 1. This setting can be used to instead use a " + "range from 0 to 1, matching other graphics APIs. This setting " + "requires OpenGL 4.5, or NVIDIA GeForce 8+ hardware.")); + extern ConfigVariableBool gl_parallel_arrays; void CLP(init_classes)() {