From 8845729351c06cd2ff1a5c1c8d24138deea624b7 Mon Sep 17 00:00:00 2001 From: Konstantin Timoshenko Date: Mon, 7 Oct 2024 19:26:17 +0300 Subject: [PATCH] fix: stable reversed Z buffer implementation Fix: reset clip state when reset is called Fix: valid depth clear value when reversed is enabled Feat: non-persistent reversedZ state ( can be controlled via renderer.state.buffers.depth.setReversed( ))) --- src/renderers/WebGLRenderer.js | 14 ++++++--- src/renderers/webgl/WebGLCapabilities.js | 9 +----- src/renderers/webgl/WebGLState.js | 39 ++++++++++++++++++++++-- 3 files changed, 48 insertions(+), 14 deletions(-) diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js index f464e7489a516c..82ef0412214752 100644 --- a/src/renderers/WebGLRenderer.js +++ b/src/renderers/WebGLRenderer.js @@ -70,6 +70,7 @@ class WebGLRenderer { preserveDrawingBuffer = false, powerPreference = 'default', failIfMajorPerformanceCaveat = false, + reverseDepthBuffer = false, } = parameters; this.isWebGLRenderer = true; @@ -288,9 +289,13 @@ class WebGLRenderer { capabilities = new WebGLCapabilities( _gl, extensions, parameters, utils ); - state = new WebGLState( _gl ); + state = new WebGLState( _gl, extensions ); - if ( capabilities.reverseDepthBuffer ) state.buffers.depth.setReversed( true ); + if ( capabilities.reverseDepthBuffer && reverseDepthBuffer ) { + + state.buffers.depth.setReversed( true ); + + } info = new WebGLInfo( _gl ); properties = new WebGLProperties(); @@ -594,7 +599,6 @@ class WebGLRenderer { if ( depth ) { bits |= _gl.DEPTH_BUFFER_BIT; - _gl.clearDepth( this.capabilities.reverseDepthBuffer ? 0 : 1 ); } @@ -1978,7 +1982,9 @@ class WebGLRenderer { // common camera uniforms - if ( capabilities.reverseDepthBuffer ) { + const reverseDepthBuffer = state.depth.getReversed (); + + if ( reverseDepthBuffer ) { _currentProjectionMatrix.copy( camera.projectionMatrix ); diff --git a/src/renderers/webgl/WebGLCapabilities.js b/src/renderers/webgl/WebGLCapabilities.js index a610a9cbbe1ea7..9fea7a1cb93c9d 100644 --- a/src/renderers/webgl/WebGLCapabilities.js +++ b/src/renderers/webgl/WebGLCapabilities.js @@ -92,14 +92,7 @@ function WebGLCapabilities( gl, extensions, parameters, utils ) { } const logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true; - const reverseDepthBuffer = parameters.reverseDepthBuffer === true && extensions.has( 'EXT_clip_control' ); - - if ( reverseDepthBuffer === true ) { - - const ext = extensions.get( 'EXT_clip_control' ); - ext.clipControlEXT( ext.LOWER_LEFT_EXT, ext.ZERO_TO_ONE_EXT ); - - } + const reverseDepthBuffer = extensions.has( 'EXT_clip_control' ); const maxTextures = gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS ); const maxVertexTextures = gl.getParameter( gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS ); diff --git a/src/renderers/webgl/WebGLState.js b/src/renderers/webgl/WebGLState.js index 3d380b1ce69f99..cf7cb83f67bd60 100644 --- a/src/renderers/webgl/WebGLState.js +++ b/src/renderers/webgl/WebGLState.js @@ -14,7 +14,7 @@ const reversedFuncs = { [ GreaterEqualDepth ]: LessEqualDepth, }; -function WebGLState( gl ) { +function WebGLState( gl, extensions ) { function ColorBuffer() { @@ -88,10 +88,36 @@ function WebGLState( gl ) { setReversed: function ( value ) { + if ( reversed !== value ) { + + const ext = extensions.get( 'EXT_clip_control' ); + + if ( reversed ) { + + ext.clipControlEXT( ext.LOWER_LEFT_EXT, ext.ZERO_TO_ONE_EXT ); + + } else { + + ext.clipControlEXT( ext.LOWER_LEFT_EXT, ext.NEGATIVE_ONE_TO_ONE_EXT ); + + } + + const oldDepth = currentDepthClear; + currentDepthClear = null; + this.setClear( oldDepth ); + + } + reversed = value; }, + getReversed: function () { + + return reversed; + + }, + setTest: function ( depthTest ) { if ( depthTest ) { @@ -187,6 +213,12 @@ function WebGLState( gl ) { if ( currentDepthClear !== depth ) { + if ( reversed ) { + + depth = 1 - depth; + + } + gl.clearDepth( depth ); currentDepthClear = depth; @@ -201,7 +233,7 @@ function WebGLState( gl ) { currentDepthMask = null; currentDepthFunc = null; currentDepthClear = null; - + reversed = false; } }; @@ -1171,6 +1203,9 @@ function WebGLState( gl ) { gl.depthMask( true ); gl.depthFunc( gl.LESS ); + + depthBuffer.setReversed ( false ); + gl.clearDepth( 1 ); gl.stencilMask( 0xffffffff );