Skip to content

Commit

Permalink
WebGLRenderer: Support render target textures in `copyTextureToTextur…
Browse files Browse the repository at this point in the history
…e()`. (#29662)

* WebGLRenderer: Support render target textures in copyTextureToTexture().

* WebGLRenderer: Update `copyTextureToTexture3D()` and docs.

* WebGLRenderer: Attempt to fix `copyTextureToTexture3D()`.
  • Loading branch information
Mugen87 authored Oct 19, 2024
1 parent 8cba4e8 commit 19db40b
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 22 deletions.
14 changes: 6 additions & 8 deletions docs/api/en/renderers/WebGLRenderer.html
Original file line number Diff line number Diff line change
Expand Up @@ -383,20 +383,18 @@ <h3>
[method:undefined copyTextureToTexture]( [param:Texture srcTexture], [param:Texture dstTexture], [param:Box2 srcRegion], [param:Vector2 dstPosition], [param:Number level] )
</h3>
<p>
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.<br />
When using render target textures as `srcTexture` and `dstTexture`, you must make sure both render targets are intitialized e.g. via [page:.initRenderTarget]().
</p>

<h3>
[method:undefined copyTextureToTexture3D]( [param:Texture srcTexture], [param:Texture dstTexture], [param:Box3 srcRegion], [param:Vector3 dstPosition], [param:Number level] )
</h3>
<p>
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.<br />
When using render target textures as `srcTexture` and `dstTexture`, you must make sure both render targets are intitialized e.g. via [page:.initRenderTarget]().
</p>

<h3>[method:undefined dispose]( )</h3>
Expand Down
71 changes: 61 additions & 10 deletions src/renderers/WebGLRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 );

}

}

Expand Down Expand Up @@ -2748,19 +2771,47 @@ 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 );

state.bindFramebuffer( _gl.READ_FRAMEBUFFER, srcRenderTargetProperties.__webglFramebuffer );

_gl.texSubImage3D( glTarget, level, dstX, dstY, dstZ, width, height, depth, glFormat, glType, image.data );
_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;

_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 );

}

}

Expand Down
14 changes: 10 additions & 4 deletions src/renderers/webgl/WebGLTextures.js
Original file line number Diff line number Diff line change
Expand Up @@ -1417,6 +1417,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 ) {

Expand All @@ -1439,11 +1442,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 );

}

Expand Down Expand Up @@ -1532,8 +1535,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 ) {

Expand All @@ -1545,7 +1551,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 ) {
Expand Down

0 comments on commit 19db40b

Please sign in to comment.