Skip to content

Commit a42a8cf

Browse files
authored
WebGLBackend: Bring back 3D functionality for copyTextureToTexture (#30584)
* Make dstLevel = 0 by default * Retrigger actions
1 parent a6aa9bd commit a42a8cf

File tree

3 files changed

+75
-25
lines changed

3 files changed

+75
-25
lines changed

src/renderers/common/Renderer.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2467,14 +2467,15 @@ class Renderer {
24672467
* @param {Texture} dstTexture - The destination texture.
24682468
* @param {Box2|Box3} [srcRegion=null] - A bounding box which describes the source region. Can be two or three-dimensional.
24692469
* @param {Vector2|Vector3} [dstPosition=null] - A vector that represents the origin of the destination region. Can be two or three-dimensional.
2470-
* @param {number} level - The mipmap level to copy.
2470+
* @param {number} [srcLevel=0] - The source mip level to copy from.
2471+
* @param {number} [dstLevel=0] - The destination mip level to copy to.
24712472
*/
2472-
copyTextureToTexture( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) {
2473+
copyTextureToTexture( srcTexture, dstTexture, srcRegion = null, dstPosition = null, srcLevel = 0, dstLevel = 0 ) {
24732474

24742475
this._textures.updateTexture( srcTexture );
24752476
this._textures.updateTexture( dstTexture );
24762477

2477-
this.backend.copyTextureToTexture( srcTexture, dstTexture, srcRegion, dstPosition, level );
2478+
this.backend.copyTextureToTexture( srcTexture, dstTexture, srcRegion, dstPosition, srcLevel, dstLevel );
24782479

24792480
}
24802481

src/renderers/webgl-fallback/WebGLBackend.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1894,11 +1894,12 @@ class WebGLBackend extends Backend {
18941894
* @param {Texture} dstTexture - The destination texture.
18951895
* @param {?Vector4} [srcRegion=null] - The region of the source texture to copy.
18961896
* @param {?(Vector2|Vector3)} [dstPosition=null] - The destination position of the copy.
1897-
* @param {number} [level=0] - The mip level to copy.
1897+
* @param {number} [srcLevel=0] - The source mip level to copy from.
1898+
* @param {number} [dstLevel=0] - The destination mip level to copy to.
18981899
*/
1899-
copyTextureToTexture( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) {
1900+
copyTextureToTexture( srcTexture, dstTexture, srcRegion = null, dstPosition = null, srcLevel = 0, dstLevel = 0 ) {
19001901

1901-
this.textureUtils.copyTextureToTexture( srcTexture, dstTexture, srcRegion, dstPosition, level );
1902+
this.textureUtils.copyTextureToTexture( srcTexture, dstTexture, srcRegion, dstPosition, srcLevel, dstLevel );
19021903

19031904
}
19041905

src/renderers/webgl-fallback/utils/WebGLTextureUtils.js

Lines changed: 67 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -697,70 +697,94 @@ class WebGLTextureUtils {
697697
*
698698
* @param {Texture} srcTexture - The source texture.
699699
* @param {Texture} dstTexture - The destination texture.
700-
* @param {?Vector4} [srcRegion=null] - The region of the source texture to copy.
700+
* @param {?(Box3|Box2)} [srcRegion=null] - The region of the source texture to copy.
701701
* @param {?(Vector2|Vector3)} [dstPosition=null] - The destination position of the copy.
702-
* @param {number} [level=0] - The mip level to copy.
702+
* @param {number} [srcLevel=0] - The source mip level to copy from.
703+
* @param {number} [dstLevel=0] - The destination mip level to copy to.
703704
*/
704-
copyTextureToTexture( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) {
705+
copyTextureToTexture( srcTexture, dstTexture, srcRegion = null, dstPosition = null, srcLevel = 0, dstLevel = 0 ) {
705706

706707
const { gl, backend } = this;
707708
const { state } = this.backend;
708709

709710
const { textureGPU: dstTextureGPU, glTextureType, glType, glFormat } = backend.get( dstTexture );
710711

711-
let width, height, minX, minY;
712-
let dstX, dstY;
712+
state.bindTexture( glTextureType, dstTextureGPU );
713+
714+
// gather the necessary dimensions to copy
715+
let width, height, depth, minX, minY, minZ;
716+
let dstX, dstY, dstZ;
717+
const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ dstLevel ] : srcTexture.image;
713718

714719
if ( srcRegion !== null ) {
715720

716721
width = srcRegion.max.x - srcRegion.min.x;
717722
height = srcRegion.max.y - srcRegion.min.y;
723+
depth = srcRegion.isBox3 ? srcRegion.max.z - srcRegion.min.z : 1;
718724
minX = srcRegion.min.x;
719725
minY = srcRegion.min.y;
726+
minZ = srcRegion.isBox3 ? srcRegion.min.z : 0;
720727

721728
} else {
722729

723-
width = srcTexture.image.width;
724-
height = srcTexture.image.height;
730+
const levelScale = Math.pow( 2, - srcLevel );
731+
width = Math.floor( image.width * levelScale );
732+
height = Math.floor( image.height * levelScale );
733+
734+
if ( srcTexture.isDataArrayTexture ) {
735+
736+
depth = image.depth;
737+
738+
} else if ( srcTexture.isData3DTexture ) {
739+
740+
depth = Math.floor( image.depth * levelScale );
741+
742+
} else {
743+
744+
depth = 1;
745+
746+
}
747+
725748
minX = 0;
726749
minY = 0;
750+
minZ = 0;
727751

728752
}
729753

730754
if ( dstPosition !== null ) {
731755

732756
dstX = dstPosition.x;
733757
dstY = dstPosition.y;
758+
dstZ = dstPosition.z;
734759

735760
} else {
736761

737762
dstX = 0;
738763
dstY = 0;
764+
dstZ = 0;
739765

740766
}
741767

742-
state.bindTexture( glTextureType, dstTextureGPU );
743768

744-
// As another texture upload may have changed pixelStorei
745-
// parameters, make sure they are correct for the dstTexture
746-
gl.pixelStorei( gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment );
747769
gl.pixelStorei( gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY );
748770
gl.pixelStorei( gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha );
749771
gl.pixelStorei( gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment );
750772

773+
// used for copying data from cpu
751774
const currentUnpackRowLen = gl.getParameter( gl.UNPACK_ROW_LENGTH );
752775
const currentUnpackImageHeight = gl.getParameter( gl.UNPACK_IMAGE_HEIGHT );
753776
const currentUnpackSkipPixels = gl.getParameter( gl.UNPACK_SKIP_PIXELS );
754777
const currentUnpackSkipRows = gl.getParameter( gl.UNPACK_SKIP_ROWS );
755778
const currentUnpackSkipImages = gl.getParameter( gl.UNPACK_SKIP_IMAGES );
756779

757-
const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ level ] : srcTexture.image;
758-
759780
gl.pixelStorei( gl.UNPACK_ROW_LENGTH, image.width );
760781
gl.pixelStorei( gl.UNPACK_IMAGE_HEIGHT, image.height );
761782
gl.pixelStorei( gl.UNPACK_SKIP_PIXELS, minX );
762783
gl.pixelStorei( gl.UNPACK_SKIP_ROWS, minY );
784+
gl.pixelStorei( gl.UNPACK_SKIP_IMAGES, minZ );
763785

786+
// set up the src texture
787+
const isDst3D = dstTexture.isDataArrayTexture || dstTexture.isData3DTexture;
764788
if ( srcTexture.isRenderTargetTexture || srcTexture.isDepthTexture ) {
765789

766790
const srcTextureData = backend.get( srcTexture );
@@ -786,39 +810,63 @@ class WebGLTextureUtils {
786810

787811
} else {
788812

789-
if ( srcTexture.isDataTexture ) {
813+
if ( isDst3D ) {
790814

791-
gl.texSubImage2D( gl.TEXTURE_2D, level, dstX, dstY, width, height, glFormat, glType, image.data );
815+
// copy data into the 3d texture
816+
if ( srcTexture.isDataTexture || srcTexture.isData3DTexture ) {
817+
818+
gl.texSubImage3D( glTextureType, dstLevel, dstX, dstY, dstZ, width, height, depth, glFormat, glType, image.data );
819+
820+
} else if ( dstTexture.isCompressedArrayTexture ) {
821+
822+
gl.compressedTexSubImage3D( glTextureType, dstLevel, dstX, dstY, dstZ, width, height, depth, glFormat, image.data );
823+
824+
} else {
825+
826+
gl.texSubImage3D( glTextureType, dstLevel, dstX, dstY, dstZ, width, height, depth, glFormat, glType, image );
827+
828+
}
792829

793830
} else {
794831

795-
if ( srcTexture.isCompressedTexture ) {
832+
// copy data into the 2d texture
833+
if ( srcTexture.isDataTexture ) {
834+
835+
gl.texSubImage2D( glTextureType, dstLevel, dstX, dstY, width, height, glFormat, glType, image.data );
796836

797-
gl.compressedTexSubImage2D( gl.TEXTURE_2D, level, dstX, dstY, image.width, image.height, glFormat, image.data );
837+
} else if ( srcTexture.isCompressedTexture ) {
838+
839+
gl.compressedTexSubImage2D( glTextureType, dstLevel, dstX, dstY, image.width, image.height, glFormat, image.data );
798840

799841
} else {
800842

801-
gl.texSubImage2D( gl.TEXTURE_2D, level, dstX, dstY, width, height, glFormat, glType, image );
843+
gl.texSubImage2D( glTextureType, dstLevel, dstX, dstY, width, height, glFormat, glType, image );
802844

803845
}
804846

805847
}
806848

807849
}
808850

851+
// reset values
809852
gl.pixelStorei( gl.UNPACK_ROW_LENGTH, currentUnpackRowLen );
810853
gl.pixelStorei( gl.UNPACK_IMAGE_HEIGHT, currentUnpackImageHeight );
811854
gl.pixelStorei( gl.UNPACK_SKIP_PIXELS, currentUnpackSkipPixels );
812855
gl.pixelStorei( gl.UNPACK_SKIP_ROWS, currentUnpackSkipRows );
813856
gl.pixelStorei( gl.UNPACK_SKIP_IMAGES, currentUnpackSkipImages );
814857

815858
// Generate mipmaps only when copying level 0
816-
if ( level === 0 && dstTexture.generateMipmaps ) gl.generateMipmap( gl.TEXTURE_2D );
859+
if ( dstLevel === 0 && dstTexture.generateMipmaps ) {
860+
861+
gl.generateMipmap( glTextureType );
862+
863+
}
817864

818865
state.unbindTexture();
819866

820867
}
821868

869+
822870
/**
823871
* Copies the current bound framebuffer to the given texture.
824872
*

0 commit comments

Comments
 (0)