diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js index 0e72fbc991d79f..a46dec5be67f92 100644 --- a/src/renderers/WebGLRenderer.js +++ b/src/renderers/WebGLRenderer.js @@ -2268,6 +2268,28 @@ class WebGLRenderer { // Color and depth texture must be rebound in order for the swapchain to update. textures.rebindTextures( renderTarget, properties.get( renderTarget.texture ).__webglTexture, properties.get( renderTarget.depthTexture ).__webglTexture ); + } else if ( renderTarget.depthBuffer ) { + + // check if the depth texture is already bound to the frame buffer and that it's been initialized + const depthTexture = renderTarget.depthTexture; + if ( renderTargetProperties.__boundDepthTexture !== depthTexture ) { + + // check if the depth texture is compatible + if ( + depthTexture !== null && + properties.has( depthTexture ) && + ( renderTarget.width !== depthTexture.image.width || renderTarget.height !== depthTexture.image.height ) + ) { + + throw new Error( 'WebGLRenderTarget: Attached DepthTexture is initialized to the incorrect size.' ); + + } + + // Swap the depth buffer to the currently attached one + textures.setupDepthRenderbuffer( renderTarget ); + + } + } const texture = renderTarget.texture; diff --git a/src/renderers/webgl/WebGLProperties.js b/src/renderers/webgl/WebGLProperties.js index 42d34a3559ffc7..09a495447525f0 100644 --- a/src/renderers/webgl/WebGLProperties.js +++ b/src/renderers/webgl/WebGLProperties.js @@ -2,6 +2,12 @@ function WebGLProperties() { let properties = new WeakMap(); + function has( object ) { + + return properties.has( object ); + + } + function get( object ) { let map = properties.get( object ); @@ -36,6 +42,7 @@ function WebGLProperties() { } return { + has: has, get: get, remove: remove, update: update, diff --git a/src/renderers/webgl/WebGLTextures.js b/src/renderers/webgl/WebGLTextures.js index db1281babd1088..fea931ce25ef6c 100644 --- a/src/renderers/webgl/WebGLTextures.js +++ b/src/renderers/webgl/WebGLTextures.js @@ -1594,6 +1594,37 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, const renderTargetProperties = properties.get( renderTarget ); const isCube = ( renderTarget.isWebGLCubeRenderTarget === true ); + // if the bound depth texture has changed + if ( renderTargetProperties.__boundDepthTexture !== renderTarget.depthTexture ) { + + // fire the dispose event to get rid of stored state associated with the previously bound depth buffer + const depthTexture = renderTarget.depthTexture; + if ( renderTargetProperties.__depthDisposeCallback ) { + + renderTargetProperties.__depthDisposeCallback(); + + } + + // set up dispose listeners to track when the currently attached buffer is implicitly unbound + if ( depthTexture ) { + + const disposeEvent = () => { + + delete renderTargetProperties.__boundDepthTexture; + delete renderTargetProperties.__depthDisposeCallback; + depthTexture.removeEventListener( 'dispose', disposeEvent ); + + }; + + depthTexture.addEventListener( 'dispose', disposeEvent ); + renderTargetProperties.__depthDisposeCallback = disposeEvent; + + } + + renderTargetProperties.__boundDepthTexture = depthTexture; + + } + if ( renderTarget.depthTexture && ! renderTargetProperties.__autoAllocateDepthBuffer ) { if ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' ); @@ -1609,16 +1640,42 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, for ( let i = 0; i < 6; i ++ ) { state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer[ i ] ); - renderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer(); - setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget, false ); + + if ( renderTargetProperties.__webglDepthbuffer[ i ] === undefined ) { + + renderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer(); + setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget, false ); + + } else { + + // attach buffer if it's been created already + const glAttachmentType = renderTarget.stencilBuffer ? _gl.DEPTH_STENCIL_ATTACHMENT : _gl.DEPTH_ATTACHMENT; + const renderbuffer = renderTargetProperties.__webglDepthbuffer[ i ]; + _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer ); + _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, glAttachmentType, _gl.RENDERBUFFER, renderbuffer ); + + } } } else { state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); - renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer(); - setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget, false ); + + if ( renderTargetProperties.__webglDepthbuffer === undefined ) { + + renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer(); + setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget, false ); + + } else { + + // attach buffer if it's been created already + const glAttachmentType = renderTarget.stencilBuffer ? _gl.DEPTH_STENCIL_ATTACHMENT : _gl.DEPTH_ATTACHMENT; + const renderbuffer = renderTargetProperties.__webglDepthbuffer; + _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer ); + _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, glAttachmentType, _gl.RENDERBUFFER, renderbuffer ); + + } }