Skip to content

Commit 19db40b

Browse files
authored
WebGLRenderer: Support render target textures in copyTextureToTexture(). (#29662)
* WebGLRenderer: Support render target textures in copyTextureToTexture(). * WebGLRenderer: Update `copyTextureToTexture3D()` and docs. * WebGLRenderer: Attempt to fix `copyTextureToTexture3D()`.
1 parent 8cba4e8 commit 19db40b

File tree

3 files changed

+77
-22
lines changed

3 files changed

+77
-22
lines changed

docs/api/en/renderers/WebGLRenderer.html

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -383,20 +383,18 @@ <h3>
383383
[method:undefined copyTextureToTexture]( [param:Texture srcTexture], [param:Texture dstTexture], [param:Box2 srcRegion], [param:Vector2 dstPosition], [param:Number level] )
384384
</h3>
385385
<p>
386-
Copies the pixels of a texture in the bounds '[page:Box2 srcRegion]' in
387-
the destination texture starting from the given position. Enables access
388-
to
389-
[link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/texSubImage2D WebGLRenderingContext.texSubImage2D].
386+
Copies the pixels of a texture in the bounds '[page:Box2 srcRegion]' in the destination texture starting from the given position.
387+
The `depthTexture` and `texture` property of render targets are supported as well.<br />
388+
When using render target textures as `srcTexture` and `dstTexture`, you must make sure both render targets are intitialized e.g. via [page:.initRenderTarget]().
390389
</p>
391390

392391
<h3>
393392
[method:undefined copyTextureToTexture3D]( [param:Texture srcTexture], [param:Texture dstTexture], [param:Box3 srcRegion], [param:Vector3 dstPosition], [param:Number level] )
394393
</h3>
395394
<p>
396-
Copies the pixels of a texture in the bounds '[page:Box3 srcRegion]' in
397-
the destination texture starting from the given position. Enables access
398-
to
399-
[link:https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/texSubImage3D WebGL2RenderingContext.texSubImage3D].
395+
Copies the pixels of a texture in the bounds '[page:Box3 srcRegion]' in the destination texture starting from the given position.
396+
The `depthTexture` and `texture` property of 3D render targets are supported as well.<br />
397+
When using render target textures as `srcTexture` and `dstTexture`, you must make sure both render targets are intitialized e.g. via [page:.initRenderTarget]().
400398
</p>
401399

402400
<h3>[method:undefined dispose]( )</h3>

src/renderers/WebGLRenderer.js

Lines changed: 61 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2627,19 +2627,42 @@ class WebGLRenderer {
26272627
_gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, minX );
26282628
_gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, minY );
26292629

2630-
if ( srcTexture.isDataTexture ) {
2630+
if ( srcTexture.isRenderTargetTexture || srcTexture.isDepthTexture ) {
26312631

2632-
_gl.texSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, width, height, glFormat, glType, image.data );
2632+
const srcTextureProperties = properties.get( srcTexture );
2633+
const dstTextureProperties = properties.get( dstTexture );
2634+
const srcRenderTargetProperties = properties.get( srcTextureProperties.__renderTarget );
2635+
const dstRenderTargetProperties = properties.get( dstTextureProperties.__renderTarget );
2636+
2637+
state.bindFramebuffer( _gl.READ_FRAMEBUFFER, srcRenderTargetProperties.__webglFramebuffer );
2638+
state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, dstRenderTargetProperties.__webglFramebuffer );
2639+
2640+
let mask = _gl.COLOR_BUFFER_BIT;
2641+
2642+
if ( srcTexture.isDepthTexture ) mask = _gl.DEPTH_BUFFER_BIT;
2643+
2644+
_gl.blitFramebuffer( minX, minY, width, height, dstX, dstY, width, height, mask, _gl.NEAREST );
2645+
2646+
state.bindFramebuffer( _gl.READ_FRAMEBUFFER, null );
2647+
state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, null );
26332648

26342649
} else {
26352650

2636-
if ( srcTexture.isCompressedTexture ) {
2651+
if ( srcTexture.isDataTexture ) {
26372652

2638-
_gl.compressedTexSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, image.width, image.height, glFormat, image.data );
2653+
_gl.texSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, width, height, glFormat, glType, image.data );
26392654

26402655
} else {
26412656

2642-
_gl.texSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, width, height, glFormat, glType, image );
2657+
if ( srcTexture.isCompressedTexture ) {
2658+
2659+
_gl.compressedTexSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, image.width, image.height, glFormat, image.data );
2660+
2661+
} else {
2662+
2663+
_gl.texSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, width, height, glFormat, glType, image );
2664+
2665+
}
26432666

26442667
}
26452668

@@ -2748,19 +2771,47 @@ class WebGLRenderer {
27482771
_gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, minY );
27492772
_gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, minZ );
27502773

2751-
if ( srcTexture.isDataTexture || srcTexture.isData3DTexture ) {
2774+
if ( srcTexture.isRenderTargetTexture || srcTexture.isDepthTexture ) {
2775+
2776+
const srcTextureProperties = properties.get( srcTexture );
2777+
const dstTextureProperties = properties.get( dstTexture );
2778+
const srcRenderTargetProperties = properties.get( srcTextureProperties.__renderTarget );
2779+
const dstRenderTargetProperties = properties.get( dstTextureProperties.__renderTarget );
2780+
2781+
state.bindFramebuffer( _gl.READ_FRAMEBUFFER, srcRenderTargetProperties.__webglFramebuffer );
27522782

2753-
_gl.texSubImage3D( glTarget, level, dstX, dstY, dstZ, width, height, depth, glFormat, glType, image.data );
2783+
_gl.framebufferTextureLayer( _gl.READ_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, properties.get( srcTexture ).__webglTexture, level, 0 );
2784+
2785+
state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, dstRenderTargetProperties.__webglFramebuffer );
2786+
2787+
_gl.framebufferTextureLayer( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, properties.get( dstTexture ).__webglTexture, level, 0 );
2788+
2789+
let mask = _gl.COLOR_BUFFER_BIT;
2790+
2791+
if ( srcTexture.isDepthTexture ) mask = _gl.DEPTH_BUFFER_BIT;
2792+
2793+
_gl.blitFramebuffer( minX, minY, width, height, dstX, dstY, width, height, mask, _gl.NEAREST );
2794+
2795+
state.bindFramebuffer( _gl.READ_FRAMEBUFFER, null );
2796+
state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, null );
27542797

27552798
} else {
27562799

2757-
if ( dstTexture.isCompressedArrayTexture ) {
2800+
if ( srcTexture.isDataTexture || srcTexture.isData3DTexture ) {
27582801

2759-
_gl.compressedTexSubImage3D( glTarget, level, dstX, dstY, dstZ, width, height, depth, glFormat, image.data );
2802+
_gl.texSubImage3D( glTarget, level, dstX, dstY, dstZ, width, height, depth, glFormat, glType, image.data );
27602803

27612804
} else {
27622805

2763-
_gl.texSubImage3D( glTarget, level, dstX, dstY, dstZ, width, height, depth, glFormat, glType, image );
2806+
if ( dstTexture.isCompressedArrayTexture ) {
2807+
2808+
_gl.compressedTexSubImage3D( glTarget, level, dstX, dstY, dstZ, width, height, depth, glFormat, image.data );
2809+
2810+
} else {
2811+
2812+
_gl.texSubImage3D( glTarget, level, dstX, dstY, dstZ, width, height, depth, glFormat, glType, image );
2813+
2814+
}
27642815

27652816
}
27662817

src/renderers/webgl/WebGLTextures.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1417,6 +1417,9 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
14171417
const glType = utils.convert( texture.type );
14181418
const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace );
14191419
const renderTargetProperties = properties.get( renderTarget );
1420+
const textureProperties = properties.get( texture );
1421+
1422+
textureProperties.__renderTarget = renderTarget;
14201423

14211424
if ( ! renderTargetProperties.__hasExternalTextures ) {
14221425

@@ -1439,11 +1442,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
14391442

14401443
if ( useMultisampledRTT( renderTarget ) ) {
14411444

1442-
multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( texture ).__webglTexture, 0, getRenderTargetSamples( renderTarget ) );
1445+
multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, attachment, textureTarget, textureProperties.__webglTexture, 0, getRenderTargetSamples( renderTarget ) );
14431446

14441447
} else if ( textureTarget === _gl.TEXTURE_2D || ( textureTarget >= _gl.TEXTURE_CUBE_MAP_POSITIVE_X && textureTarget <= _gl.TEXTURE_CUBE_MAP_NEGATIVE_Z ) ) { // see #24753
14451448

1446-
_gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( texture ).__webglTexture, level );
1449+
_gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, textureProperties.__webglTexture, level );
14471450

14481451
}
14491452

@@ -1532,8 +1535,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
15321535

15331536
}
15341537

1538+
const textureProperties = properties.get( renderTarget.depthTexture );
1539+
textureProperties.__renderTarget = renderTarget;
1540+
15351541
// upload an empty depth texture with framebuffer size
1536-
if ( ! properties.get( renderTarget.depthTexture ).__webglTexture ||
1542+
if ( ! textureProperties.__webglTexture ||
15371543
renderTarget.depthTexture.image.width !== renderTarget.width ||
15381544
renderTarget.depthTexture.image.height !== renderTarget.height ) {
15391545

@@ -1545,7 +1551,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
15451551

15461552
setTexture2D( renderTarget.depthTexture, 0 );
15471553

1548-
const webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture;
1554+
const webglDepthTexture = textureProperties.__webglTexture;
15491555
const samples = getRenderTargetSamples( renderTarget );
15501556

15511557
if ( renderTarget.depthTexture.format === DepthFormat ) {

0 commit comments

Comments
 (0)