From 57c49a75e6dded5d371b5a44fc388e3f37af863e Mon Sep 17 00:00:00 2001 From: Mugen87 Date: Tue, 15 Oct 2024 12:40:19 +0200 Subject: [PATCH 1/3] WebGLRenderer: Support render target textures in copyTextureToTexture(). --- src/renderers/WebGLRenderer.js | 33 +++++++++++++++++++++++----- src/renderers/webgl/WebGLTextures.js | 14 ++++++++---- 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js index f464e7489a516c..2c424df8279dfc 100644 --- a/src/renderers/WebGLRenderer.js +++ b/src/renderers/WebGLRenderer.js @@ -2627,19 +2627,42 @@ class WebGLRenderer { _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, minX ); _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, minY ); - if ( srcTexture.isDataTexture ) { + if ( srcTexture.isRenderTargetTexture || srcTexture.isDepthTexture ) { - _gl.texSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, width, height, glFormat, glType, image.data ); + const srcTextureProperties = properties.get( srcTexture ); + const dstTextureProperties = properties.get( dstTexture ); + const srcRenderTargetProperties = properties.get( srcTextureProperties.__renderTarget ); + const dstRenderTargetProperties = properties.get( dstTextureProperties.__renderTarget ); + + state.bindFramebuffer( _gl.READ_FRAMEBUFFER, srcRenderTargetProperties.__webglFramebuffer ); + state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, dstRenderTargetProperties.__webglFramebuffer ); + + let mask = _gl.COLOR_BUFFER_BIT; + + if ( srcTexture.isDepthTexture ) mask = _gl.DEPTH_BUFFER_BIT; + + _gl.blitFramebuffer( minX, minY, width, height, dstX, dstY, width, height, mask, _gl.NEAREST ); + + state.bindFramebuffer( _gl.READ_FRAMEBUFFER, null ); + state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, null ); } else { - if ( srcTexture.isCompressedTexture ) { + if ( srcTexture.isDataTexture ) { - _gl.compressedTexSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, image.width, image.height, glFormat, image.data ); + _gl.texSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, width, height, glFormat, glType, image.data ); } else { - _gl.texSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, width, height, glFormat, glType, image ); + if ( srcTexture.isCompressedTexture ) { + + _gl.compressedTexSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, image.width, image.height, glFormat, image.data ); + + } else { + + _gl.texSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, width, height, glFormat, glType, image ); + + } } diff --git a/src/renderers/webgl/WebGLTextures.js b/src/renderers/webgl/WebGLTextures.js index 5663c8e8affb88..046d6ee2cf3aa2 100644 --- a/src/renderers/webgl/WebGLTextures.js +++ b/src/renderers/webgl/WebGLTextures.js @@ -1408,6 +1408,9 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, const glType = utils.convert( texture.type ); const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); const renderTargetProperties = properties.get( renderTarget ); + const textureProperties = properties.get( texture ); + + textureProperties.__renderTarget = renderTarget; if ( ! renderTargetProperties.__hasExternalTextures ) { @@ -1430,11 +1433,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( useMultisampledRTT( renderTarget ) ) { - multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( texture ).__webglTexture, 0, getRenderTargetSamples( renderTarget ) ); + multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, attachment, textureTarget, textureProperties.__webglTexture, 0, getRenderTargetSamples( renderTarget ) ); } else if ( textureTarget === _gl.TEXTURE_2D || ( textureTarget >= _gl.TEXTURE_CUBE_MAP_POSITIVE_X && textureTarget <= _gl.TEXTURE_CUBE_MAP_NEGATIVE_Z ) ) { // see #24753 - _gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( texture ).__webglTexture, level ); + _gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, textureProperties.__webglTexture, level ); } @@ -1523,8 +1526,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } + const textureProperties = properties.get( renderTarget.depthTexture ); + textureProperties.__renderTarget = renderTarget; + // upload an empty depth texture with framebuffer size - if ( ! properties.get( renderTarget.depthTexture ).__webglTexture || + if ( ! textureProperties.__webglTexture || renderTarget.depthTexture.image.width !== renderTarget.width || renderTarget.depthTexture.image.height !== renderTarget.height ) { @@ -1536,7 +1542,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, setTexture2D( renderTarget.depthTexture, 0 ); - const webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture; + const webglDepthTexture = textureProperties.__webglTexture; const samples = getRenderTargetSamples( renderTarget ); if ( renderTarget.depthTexture.format === DepthFormat ) { From 41ffb44a09c5d25e08fea2dab8bfdc567e3cbf02 Mon Sep 17 00:00:00 2001 From: Mugen87 Date: Wed, 16 Oct 2024 10:27:00 +0200 Subject: [PATCH 2/3] WebGLRenderer: Update `copyTextureToTexture3D()` and docs. --- docs/api/en/renderers/WebGLRenderer.html | 14 +++++----- src/renderers/WebGLRenderer.js | 33 ++++++++++++++++++++---- 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/docs/api/en/renderers/WebGLRenderer.html b/docs/api/en/renderers/WebGLRenderer.html index 0b085051595cde..6b49a59f5caf06 100644 --- a/docs/api/en/renderers/WebGLRenderer.html +++ b/docs/api/en/renderers/WebGLRenderer.html @@ -383,20 +383,18 @@

[method:undefined copyTextureToTexture]( [param:Texture srcTexture], [param:Texture dstTexture], [param:Box2 srcRegion], [param:Vector2 dstPosition], [param:Number level] )

- Copies the pixels of a texture in the bounds '[page:Box2 srcRegion]' in - the destination texture starting from the given position. Enables access - to - [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/texSubImage2D WebGLRenderingContext.texSubImage2D]. + Copies the pixels of a texture in the bounds '[page:Box2 srcRegion]' in the destination texture starting from the given position. + The `depthTexture` and `texture` property of render targets are supported as well.
+ When using render target textures as `srcTexture` and `dstTexture`, you must make sure both render targets are intitialized e.g. via [page:.initRenderTarget]().

[method:undefined copyTextureToTexture3D]( [param:Texture srcTexture], [param:Texture dstTexture], [param:Box3 srcRegion], [param:Vector3 dstPosition], [param:Number level] )

- Copies the pixels of a texture in the bounds '[page:Box3 srcRegion]' in - the destination texture starting from the given position. Enables access - to - [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/texSubImage3D WebGL2RenderingContext.texSubImage3D]. + Copies the pixels of a texture in the bounds '[page:Box3 srcRegion]' in the destination texture starting from the given position. + The `depthTexture` and `texture` property of 3D render targets are supported as well.
+ When using render target textures as `srcTexture` and `dstTexture`, you must make sure both render targets are intitialized e.g. via [page:.initRenderTarget]().

[method:undefined dispose]( )

diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js index 2c424df8279dfc..192d021a217ff0 100644 --- a/src/renderers/WebGLRenderer.js +++ b/src/renderers/WebGLRenderer.js @@ -2771,19 +2771,42 @@ class WebGLRenderer { _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, minY ); _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, minZ ); - if ( srcTexture.isDataTexture || srcTexture.isData3DTexture ) { + if ( srcTexture.isRenderTargetTexture || srcTexture.isDepthTexture ) { + + const srcTextureProperties = properties.get( srcTexture ); + const dstTextureProperties = properties.get( dstTexture ); + const srcRenderTargetProperties = properties.get( srcTextureProperties.__renderTarget ); + const dstRenderTargetProperties = properties.get( dstTextureProperties.__renderTarget ); - _gl.texSubImage3D( glTarget, level, dstX, dstY, dstZ, width, height, depth, glFormat, glType, image.data ); + state.bindFramebuffer( _gl.READ_FRAMEBUFFER, srcRenderTargetProperties.__webglFramebuffer ); + state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, dstRenderTargetProperties.__webglFramebuffer ); + + let mask = _gl.COLOR_BUFFER_BIT; + + if ( srcTexture.isDepthTexture ) mask = _gl.DEPTH_BUFFER_BIT; + + _gl.blitFramebuffer( minX, minY, width, height, dstX, dstY, width, height, mask, _gl.NEAREST ); + + state.bindFramebuffer( _gl.READ_FRAMEBUFFER, null ); + state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, null ); } else { - if ( dstTexture.isCompressedArrayTexture ) { + if ( srcTexture.isDataTexture || srcTexture.isData3DTexture ) { - _gl.compressedTexSubImage3D( glTarget, level, dstX, dstY, dstZ, width, height, depth, glFormat, image.data ); + _gl.texSubImage3D( glTarget, level, dstX, dstY, dstZ, width, height, depth, glFormat, glType, image.data ); } else { - _gl.texSubImage3D( glTarget, level, dstX, dstY, dstZ, width, height, depth, glFormat, glType, image ); + if ( dstTexture.isCompressedArrayTexture ) { + + _gl.compressedTexSubImage3D( glTarget, level, dstX, dstY, dstZ, width, height, depth, glFormat, image.data ); + + } else { + + _gl.texSubImage3D( glTarget, level, dstX, dstY, dstZ, width, height, depth, glFormat, glType, image ); + + } } From d9bed5d318157a12ac2833ae8c20f5c147f9cd57 Mon Sep 17 00:00:00 2001 From: Mugen87 Date: Wed, 16 Oct 2024 19:49:15 +0200 Subject: [PATCH 3/3] WebGLRenderer: Attempt to fix `copyTextureToTexture3D()`. --- src/renderers/WebGLRenderer.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js index 192d021a217ff0..8362547b69b35b 100644 --- a/src/renderers/WebGLRenderer.js +++ b/src/renderers/WebGLRenderer.js @@ -2779,8 +2779,13 @@ class WebGLRenderer { const dstRenderTargetProperties = properties.get( dstTextureProperties.__renderTarget ); state.bindFramebuffer( _gl.READ_FRAMEBUFFER, srcRenderTargetProperties.__webglFramebuffer ); + + _gl.framebufferTextureLayer( _gl.READ_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, properties.get( srcTexture ).__webglTexture, level, 0 ); + state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, dstRenderTargetProperties.__webglFramebuffer ); + _gl.framebufferTextureLayer( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, properties.get( dstTexture ).__webglTexture, level, 0 ); + let mask = _gl.COLOR_BUFFER_BIT; if ( srcTexture.isDepthTexture ) mask = _gl.DEPTH_BUFFER_BIT;