@@ -697,70 +697,92 @@ 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 ) ;
713713
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 ;
714718 if ( srcRegion !== null ) {
715719
716720 width = srcRegion . max . x - srcRegion . min . x ;
717721 height = srcRegion . max . y - srcRegion . min . y ;
722+ depth = srcRegion . isBox3 ? srcRegion . max . z - srcRegion . min . z : 1 ;
718723 minX = srcRegion . min . x ;
719724 minY = srcRegion . min . y ;
725+ minZ = srcRegion . isBox3 ? srcRegion . min . z : 0 ;
720726
721727 } else {
722728
723- width = srcTexture . image . width ;
724- height = srcTexture . image . height ;
729+ const levelScale = Math . pow ( 2 , - srcLevel ) ;
730+ width = Math . floor ( image . width * levelScale ) ;
731+ height = Math . floor ( image . height * levelScale ) ;
732+ if ( srcTexture . isDataArrayTexture ) {
733+
734+ depth = image . depth ;
735+
736+ } else if ( srcTexture . isData3DTexture ) {
737+
738+ depth = Math . floor ( image . depth * levelScale ) ;
739+
740+ } else {
741+
742+ depth = 1 ;
743+
744+ }
745+
725746 minX = 0 ;
726747 minY = 0 ;
748+ minZ = 0 ;
727749
728750 }
729751
730752 if ( dstPosition !== null ) {
731753
732754 dstX = dstPosition . x ;
733755 dstY = dstPosition . y ;
756+ dstZ = dstPosition . z ;
734757
735758 } else {
736759
737760 dstX = 0 ;
738761 dstY = 0 ;
762+ dstZ = 0 ;
739763
740764 }
741765
742- state . bindTexture ( glTextureType , dstTextureGPU ) ;
743766
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 ) ;
747767 gl . pixelStorei ( gl . UNPACK_FLIP_Y_WEBGL , dstTexture . flipY ) ;
748768 gl . pixelStorei ( gl . UNPACK_PREMULTIPLY_ALPHA_WEBGL , dstTexture . premultiplyAlpha ) ;
749769 gl . pixelStorei ( gl . UNPACK_ALIGNMENT , dstTexture . unpackAlignment ) ;
750770
771+ // used for copying data from cpu
751772 const currentUnpackRowLen = gl . getParameter ( gl . UNPACK_ROW_LENGTH ) ;
752773 const currentUnpackImageHeight = gl . getParameter ( gl . UNPACK_IMAGE_HEIGHT ) ;
753774 const currentUnpackSkipPixels = gl . getParameter ( gl . UNPACK_SKIP_PIXELS ) ;
754775 const currentUnpackSkipRows = gl . getParameter ( gl . UNPACK_SKIP_ROWS ) ;
755776 const currentUnpackSkipImages = gl . getParameter ( gl . UNPACK_SKIP_IMAGES ) ;
756777
757- const image = srcTexture . isCompressedTexture ? srcTexture . mipmaps [ level ] : srcTexture . image ;
758-
759778 gl . pixelStorei ( gl . UNPACK_ROW_LENGTH , image . width ) ;
760779 gl . pixelStorei ( gl . UNPACK_IMAGE_HEIGHT , image . height ) ;
761780 gl . pixelStorei ( gl . UNPACK_SKIP_PIXELS , minX ) ;
762781 gl . pixelStorei ( gl . UNPACK_SKIP_ROWS , minY ) ;
782+ gl . pixelStorei ( gl . UNPACK_SKIP_IMAGES , minZ ) ;
763783
784+ // set up the src texture
785+ const isDst3D = dstTexture . isDataArrayTexture || dstTexture . isData3DTexture ;
764786 if ( srcTexture . isRenderTargetTexture || srcTexture . isDepthTexture ) {
765787
766788 const srcTextureData = backend . get ( srcTexture ) ;
@@ -786,39 +808,63 @@ class WebGLTextureUtils {
786808
787809 } else {
788810
789- if ( srcTexture . isDataTexture ) {
811+ if ( isDst3D ) {
812+
813+ // copy data into the 3d texture
814+ if ( srcTexture . isDataTexture || srcTexture . isData3DTexture ) {
790815
791- gl . texSubImage2D ( gl . TEXTURE_2D , level , dstX , dstY , width , height , glFormat , glType , image . data ) ;
816+ gl . texSubImage3D ( glTextureType , dstLevel , dstX , dstY , dstZ , width , height , depth , glFormat , glType , image . data ) ;
817+
818+ } else if ( dstTexture . isCompressedArrayTexture ) {
819+
820+ gl . compressedTexSubImage3D ( glTextureType , dstLevel , dstX , dstY , dstZ , width , height , depth , glFormat , image . data ) ;
821+
822+ } else {
823+
824+ gl . texSubImage3D ( glTextureType , dstLevel , dstX , dstY , dstZ , width , height , depth , glFormat , glType , image ) ;
825+
826+ }
792827
793828 } else {
794829
795- if ( srcTexture . isCompressedTexture ) {
830+ // copy data into the 2d texture
831+ if ( srcTexture . isDataTexture ) {
796832
797- gl . compressedTexSubImage2D ( gl . TEXTURE_2D , level , dstX , dstY , image . width , image . height , glFormat , image . data ) ;
833+ gl . texSubImage2D ( glTextureType , dstLevel , dstX , dstY , width , height , glFormat , glType , image . data ) ;
834+
835+ } else if ( srcTexture . isCompressedTexture ) {
836+
837+ gl . compressedTexSubImage2D ( glTextureType , dstLevel , dstX , dstY , image . width , image . height , glFormat , image . data ) ;
798838
799839 } else {
800840
801- gl . texSubImage2D ( gl . TEXTURE_2D , level , dstX , dstY , width , height , glFormat , glType , image ) ;
841+ gl . texSubImage2D ( glTextureType , dstLevel , dstX , dstY , width , height , glFormat , glType , image ) ;
802842
803843 }
804844
805845 }
806846
807847 }
808848
849+ // reset values
809850 gl . pixelStorei ( gl . UNPACK_ROW_LENGTH , currentUnpackRowLen ) ;
810851 gl . pixelStorei ( gl . UNPACK_IMAGE_HEIGHT , currentUnpackImageHeight ) ;
811852 gl . pixelStorei ( gl . UNPACK_SKIP_PIXELS , currentUnpackSkipPixels ) ;
812853 gl . pixelStorei ( gl . UNPACK_SKIP_ROWS , currentUnpackSkipRows ) ;
813854 gl . pixelStorei ( gl . UNPACK_SKIP_IMAGES , currentUnpackSkipImages ) ;
814855
815856 // Generate mipmaps only when copying level 0
816- if ( level === 0 && dstTexture . generateMipmaps ) gl . generateMipmap ( gl . TEXTURE_2D ) ;
857+ if ( dstLevel === 0 && dstTexture . generateMipmaps ) {
858+
859+ gl . generateMipmap ( glTextureType ) ;
860+
861+ }
817862
818863 state . unbindTexture ( ) ;
819864
820865 }
821866
867+
822868 /**
823869 * Copies the current bound framebuffer to the given texture.
824870 *
0 commit comments