|
@@ -697,33 +697,57 @@ class WebGLTextureUtils {
|
|
|
*
|
|
*
|
|
|
* @param {Texture} srcTexture - The source texture.
|
|
* @param {Texture} srcTexture - The source texture.
|
|
|
* @param {Texture} dstTexture - The destination texture.
|
|
* @param {Texture} dstTexture - The destination texture.
|
|
|
- * @param {?Vector4} [srcRegion=null] - The region of the source texture to copy.
|
|
|
|
|
|
|
+ * @param {?(Box3|Box2)} [srcRegion=null] - The region of the source texture to copy.
|
|
|
* @param {?(Vector2|Vector3)} [dstPosition=null] - The destination position of the copy.
|
|
* @param {?(Vector2|Vector3)} [dstPosition=null] - The destination position of the copy.
|
|
|
- * @param {number} [level=0] - The mip level to copy.
|
|
|
|
|
|
|
+ * @param {number} [srcLevel=0] - The source mip level to copy from.
|
|
|
|
|
+ * @param {number} [dstLevel=0] - The destination mip level to copy to.
|
|
|
*/
|
|
*/
|
|
|
- copyTextureToTexture( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) {
|
|
|
|
|
|
|
+ copyTextureToTexture( srcTexture, dstTexture, srcRegion = null, dstPosition = null, srcLevel = 0, dstLevel = 0 ) {
|
|
|
|
|
|
|
|
const { gl, backend } = this;
|
|
const { gl, backend } = this;
|
|
|
const { state } = this.backend;
|
|
const { state } = this.backend;
|
|
|
|
|
|
|
|
const { textureGPU: dstTextureGPU, glTextureType, glType, glFormat } = backend.get( dstTexture );
|
|
const { textureGPU: dstTextureGPU, glTextureType, glType, glFormat } = backend.get( dstTexture );
|
|
|
|
|
|
|
|
- let width, height, minX, minY;
|
|
|
|
|
- let dstX, dstY;
|
|
|
|
|
|
|
+ state.bindTexture( glTextureType, dstTextureGPU );
|
|
|
|
|
+
|
|
|
|
|
+ // gather the necessary dimensions to copy
|
|
|
|
|
+ let width, height, depth, minX, minY, minZ;
|
|
|
|
|
+ let dstX, dstY, dstZ;
|
|
|
|
|
+ const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ dstLevel ] : srcTexture.image;
|
|
|
|
|
|
|
|
if ( srcRegion !== null ) {
|
|
if ( srcRegion !== null ) {
|
|
|
|
|
|
|
|
width = srcRegion.max.x - srcRegion.min.x;
|
|
width = srcRegion.max.x - srcRegion.min.x;
|
|
|
height = srcRegion.max.y - srcRegion.min.y;
|
|
height = srcRegion.max.y - srcRegion.min.y;
|
|
|
|
|
+ depth = srcRegion.isBox3 ? srcRegion.max.z - srcRegion.min.z : 1;
|
|
|
minX = srcRegion.min.x;
|
|
minX = srcRegion.min.x;
|
|
|
minY = srcRegion.min.y;
|
|
minY = srcRegion.min.y;
|
|
|
|
|
+ minZ = srcRegion.isBox3 ? srcRegion.min.z : 0;
|
|
|
|
|
|
|
|
} else {
|
|
} else {
|
|
|
|
|
|
|
|
- width = srcTexture.image.width;
|
|
|
|
|
- height = srcTexture.image.height;
|
|
|
|
|
|
|
+ const levelScale = Math.pow( 2, - srcLevel );
|
|
|
|
|
+ width = Math.floor( image.width * levelScale );
|
|
|
|
|
+ height = Math.floor( image.height * levelScale );
|
|
|
|
|
+
|
|
|
|
|
+ if ( srcTexture.isDataArrayTexture ) {
|
|
|
|
|
+
|
|
|
|
|
+ depth = image.depth;
|
|
|
|
|
+
|
|
|
|
|
+ } else if ( srcTexture.isData3DTexture ) {
|
|
|
|
|
+
|
|
|
|
|
+ depth = Math.floor( image.depth * levelScale );
|
|
|
|
|
+
|
|
|
|
|
+ } else {
|
|
|
|
|
+
|
|
|
|
|
+ depth = 1;
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
minX = 0;
|
|
minX = 0;
|
|
|
minY = 0;
|
|
minY = 0;
|
|
|
|
|
+ minZ = 0;
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -731,36 +755,36 @@ class WebGLTextureUtils {
|
|
|
|
|
|
|
|
dstX = dstPosition.x;
|
|
dstX = dstPosition.x;
|
|
|
dstY = dstPosition.y;
|
|
dstY = dstPosition.y;
|
|
|
|
|
+ dstZ = dstPosition.z;
|
|
|
|
|
|
|
|
} else {
|
|
} else {
|
|
|
|
|
|
|
|
dstX = 0;
|
|
dstX = 0;
|
|
|
dstY = 0;
|
|
dstY = 0;
|
|
|
|
|
+ dstZ = 0;
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- state.bindTexture( glTextureType, dstTextureGPU );
|
|
|
|
|
|
|
|
|
|
- // As another texture upload may have changed pixelStorei
|
|
|
|
|
- // parameters, make sure they are correct for the dstTexture
|
|
|
|
|
- gl.pixelStorei( gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment );
|
|
|
|
|
gl.pixelStorei( gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY );
|
|
gl.pixelStorei( gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY );
|
|
|
gl.pixelStorei( gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha );
|
|
gl.pixelStorei( gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha );
|
|
|
gl.pixelStorei( gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment );
|
|
gl.pixelStorei( gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment );
|
|
|
|
|
|
|
|
|
|
+ // used for copying data from cpu
|
|
|
const currentUnpackRowLen = gl.getParameter( gl.UNPACK_ROW_LENGTH );
|
|
const currentUnpackRowLen = gl.getParameter( gl.UNPACK_ROW_LENGTH );
|
|
|
const currentUnpackImageHeight = gl.getParameter( gl.UNPACK_IMAGE_HEIGHT );
|
|
const currentUnpackImageHeight = gl.getParameter( gl.UNPACK_IMAGE_HEIGHT );
|
|
|
const currentUnpackSkipPixels = gl.getParameter( gl.UNPACK_SKIP_PIXELS );
|
|
const currentUnpackSkipPixels = gl.getParameter( gl.UNPACK_SKIP_PIXELS );
|
|
|
const currentUnpackSkipRows = gl.getParameter( gl.UNPACK_SKIP_ROWS );
|
|
const currentUnpackSkipRows = gl.getParameter( gl.UNPACK_SKIP_ROWS );
|
|
|
const currentUnpackSkipImages = gl.getParameter( gl.UNPACK_SKIP_IMAGES );
|
|
const currentUnpackSkipImages = gl.getParameter( gl.UNPACK_SKIP_IMAGES );
|
|
|
|
|
|
|
|
- const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ level ] : srcTexture.image;
|
|
|
|
|
-
|
|
|
|
|
gl.pixelStorei( gl.UNPACK_ROW_LENGTH, image.width );
|
|
gl.pixelStorei( gl.UNPACK_ROW_LENGTH, image.width );
|
|
|
gl.pixelStorei( gl.UNPACK_IMAGE_HEIGHT, image.height );
|
|
gl.pixelStorei( gl.UNPACK_IMAGE_HEIGHT, image.height );
|
|
|
gl.pixelStorei( gl.UNPACK_SKIP_PIXELS, minX );
|
|
gl.pixelStorei( gl.UNPACK_SKIP_PIXELS, minX );
|
|
|
gl.pixelStorei( gl.UNPACK_SKIP_ROWS, minY );
|
|
gl.pixelStorei( gl.UNPACK_SKIP_ROWS, minY );
|
|
|
|
|
+ gl.pixelStorei( gl.UNPACK_SKIP_IMAGES, minZ );
|
|
|
|
|
|
|
|
|
|
+ // set up the src texture
|
|
|
|
|
+ const isDst3D = dstTexture.isDataArrayTexture || dstTexture.isData3DTexture;
|
|
|
if ( srcTexture.isRenderTargetTexture || srcTexture.isDepthTexture ) {
|
|
if ( srcTexture.isRenderTargetTexture || srcTexture.isDepthTexture ) {
|
|
|
|
|
|
|
|
const srcTextureData = backend.get( srcTexture );
|
|
const srcTextureData = backend.get( srcTexture );
|
|
@@ -786,19 +810,37 @@ class WebGLTextureUtils {
|
|
|
|
|
|
|
|
} else {
|
|
} else {
|
|
|
|
|
|
|
|
- if ( srcTexture.isDataTexture ) {
|
|
|
|
|
|
|
+ if ( isDst3D ) {
|
|
|
|
|
|
|
|
- gl.texSubImage2D( gl.TEXTURE_2D, level, dstX, dstY, width, height, glFormat, glType, image.data );
|
|
|
|
|
|
|
+ // copy data into the 3d texture
|
|
|
|
|
+ if ( srcTexture.isDataTexture || srcTexture.isData3DTexture ) {
|
|
|
|
|
+
|
|
|
|
|
+ gl.texSubImage3D( glTextureType, dstLevel, dstX, dstY, dstZ, width, height, depth, glFormat, glType, image.data );
|
|
|
|
|
+
|
|
|
|
|
+ } else if ( dstTexture.isCompressedArrayTexture ) {
|
|
|
|
|
+
|
|
|
|
|
+ gl.compressedTexSubImage3D( glTextureType, dstLevel, dstX, dstY, dstZ, width, height, depth, glFormat, image.data );
|
|
|
|
|
+
|
|
|
|
|
+ } else {
|
|
|
|
|
+
|
|
|
|
|
+ gl.texSubImage3D( glTextureType, dstLevel, dstX, dstY, dstZ, width, height, depth, glFormat, glType, image );
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
} else {
|
|
} else {
|
|
|
|
|
|
|
|
- if ( srcTexture.isCompressedTexture ) {
|
|
|
|
|
|
|
+ // copy data into the 2d texture
|
|
|
|
|
+ if ( srcTexture.isDataTexture ) {
|
|
|
|
|
+
|
|
|
|
|
+ gl.texSubImage2D( glTextureType, dstLevel, dstX, dstY, width, height, glFormat, glType, image.data );
|
|
|
|
|
|
|
|
- gl.compressedTexSubImage2D( gl.TEXTURE_2D, level, dstX, dstY, image.width, image.height, glFormat, image.data );
|
|
|
|
|
|
|
+ } else if ( srcTexture.isCompressedTexture ) {
|
|
|
|
|
+
|
|
|
|
|
+ gl.compressedTexSubImage2D( glTextureType, dstLevel, dstX, dstY, image.width, image.height, glFormat, image.data );
|
|
|
|
|
|
|
|
} else {
|
|
} else {
|
|
|
|
|
|
|
|
- gl.texSubImage2D( gl.TEXTURE_2D, level, dstX, dstY, width, height, glFormat, glType, image );
|
|
|
|
|
|
|
+ gl.texSubImage2D( glTextureType, dstLevel, dstX, dstY, width, height, glFormat, glType, image );
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -806,6 +848,7 @@ class WebGLTextureUtils {
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // reset values
|
|
|
gl.pixelStorei( gl.UNPACK_ROW_LENGTH, currentUnpackRowLen );
|
|
gl.pixelStorei( gl.UNPACK_ROW_LENGTH, currentUnpackRowLen );
|
|
|
gl.pixelStorei( gl.UNPACK_IMAGE_HEIGHT, currentUnpackImageHeight );
|
|
gl.pixelStorei( gl.UNPACK_IMAGE_HEIGHT, currentUnpackImageHeight );
|
|
|
gl.pixelStorei( gl.UNPACK_SKIP_PIXELS, currentUnpackSkipPixels );
|
|
gl.pixelStorei( gl.UNPACK_SKIP_PIXELS, currentUnpackSkipPixels );
|
|
@@ -813,12 +856,17 @@ class WebGLTextureUtils {
|
|
|
gl.pixelStorei( gl.UNPACK_SKIP_IMAGES, currentUnpackSkipImages );
|
|
gl.pixelStorei( gl.UNPACK_SKIP_IMAGES, currentUnpackSkipImages );
|
|
|
|
|
|
|
|
// Generate mipmaps only when copying level 0
|
|
// Generate mipmaps only when copying level 0
|
|
|
- if ( level === 0 && dstTexture.generateMipmaps ) gl.generateMipmap( gl.TEXTURE_2D );
|
|
|
|
|
|
|
+ if ( dstLevel === 0 && dstTexture.generateMipmaps ) {
|
|
|
|
|
+
|
|
|
|
|
+ gl.generateMipmap( glTextureType );
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
state.unbindTexture();
|
|
state.unbindTexture();
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* Copies the current bound framebuffer to the given texture.
|
|
* Copies the current bound framebuffer to the given texture.
|
|
|
*
|
|
*
|