copyTextureToTexture method
void
copyTextureToTexture(})
Implementation
void copyTextureToTexture(Texture srcTexture, Texture dstTexture, {srcRegion, dstPosition, int srcLevel = 0, dstLevel}) {
if ( dstLevel == null ) {
if ( srcLevel != 0 ) {
dstLevel = srcLevel;
srcLevel = 0;
}
else {
dstLevel = 0;
}
}
// gather the necessary dimensions to copy
int width, height, depth, minX, minY, minZ;
int dstX, dstY, dstZ;
final image = srcTexture is CompressedTexture ? srcTexture.mipmaps[ dstLevel ] : srcTexture.image;
if ( srcRegion != null ) {
width = srcRegion.max.x - srcRegion.min.x;
height = srcRegion.max.y - srcRegion.min.y;
depth = srcRegion is BoundingBox ? (srcRegion.max.z - srcRegion.min.z).toInt() : 1;
minX = srcRegion.min.x;
minY = srcRegion.min.y;
minZ = srcRegion is BoundingBox ? srcRegion.min.z.toInt() : 0;
}
else {
final levelScale = math.pow( 2, - srcLevel );
width = ( image.width * levelScale ).floor();
height = ( image.height * levelScale ).floor();
if ( srcTexture is DataArrayTexture ) {
depth = image.depth;
}
else if ( srcTexture is Data3DTexture ) {
depth = ( image.depth * levelScale ).floor();
}
else {
depth = 1;
}
minX = 0;
minY = 0;
minZ = 0;
}
if ( dstPosition != null ) {
dstX = dstPosition.x;
dstY = dstPosition.y;
dstZ = dstPosition.z;
}
else {
dstX = 0;
dstY = 0;
dstZ = 0;
}
// Set up the destination target
final glFormat = utils.convert( dstTexture.format );
final glType = utils.convert( dstTexture.type );
int glTarget = 0;
if ( dstTexture is Data3DTexture ) {
textures.setTexture3D( dstTexture, 0 );
glTarget = WebGL.TEXTURE_3D;
}
else if ( dstTexture is DataArrayTexture || dstTexture is CompressedArrayTexture ) {
textures.setTexture2DArray( dstTexture, 0 );
glTarget = WebGL.TEXTURE_2D_ARRAY;
}
else {
textures.setTexture2D( dstTexture, 0 );
glTarget = WebGL.TEXTURE_2D;
}
// if(kIsWeb){
// _gl.pixelStorei( WebGL.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY?1:0 );
// _gl.pixelStorei( WebGL.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha?1:0 );
// _gl.pixelStorei( WebGL.UNPACK_ALIGNMENT, dstTexture.unpackAlignment );
// }
// used for copying data from cpu
final currentUnpackRowLen = _gl.getParameter( WebGL.UNPACK_ROW_LENGTH );
final currentUnpackImageHeight = _gl.getParameter( WebGL.UNPACK_IMAGE_HEIGHT );
final currentUnpackSkipPixels = _gl.getParameter( WebGL.UNPACK_SKIP_PIXELS );
final currentUnpackSkipRows = _gl.getParameter( WebGL.UNPACK_SKIP_ROWS );
final currentUnpackSkipImages = _gl.getParameter( WebGL.UNPACK_SKIP_IMAGES );
_gl.pixelStorei( WebGL.UNPACK_ROW_LENGTH, image.width );
_gl.pixelStorei( WebGL.UNPACK_IMAGE_HEIGHT, image.height );
_gl.pixelStorei( WebGL.UNPACK_SKIP_PIXELS, minX );
_gl.pixelStorei( WebGL.UNPACK_SKIP_ROWS, minY );
_gl.pixelStorei( WebGL.UNPACK_SKIP_IMAGES, minZ );
// set up the src texture
final isSrc3D = srcTexture is DataArrayTexture || srcTexture is Data3DTexture;
final isDst3D = dstTexture is DataArrayTexture || dstTexture is Data3DTexture;
if ( srcTexture.isDepthTexture ) {
final srcTextureProperties = properties.get( srcTexture );
final dstTextureProperties = properties.get( dstTexture );
final srcRenderTargetProperties = properties.get( srcTextureProperties['__renderTarget'] );
final dstRenderTargetProperties = properties.get( dstTextureProperties['__renderTarget'] );
state.bindFramebuffer( WebGL.READ_FRAMEBUFFER, srcRenderTargetProperties['__webglFramebuffer'] );
state.bindFramebuffer( WebGL.DRAW_FRAMEBUFFER, dstRenderTargetProperties['__webglFramebuffer'] );
for (int i = 0; i < depth; i ++ ) {
// if the source or destination are a 3d target then a layer needs to be bound
if ( isSrc3D ) {
_gl.framebufferTextureLayer( WebGL.READ_FRAMEBUFFER, WebGL.COLOR_ATTACHMENT0, properties.get( srcTexture )['__webglTexture'], srcLevel, minZ + i );
_gl.framebufferTextureLayer( WebGL.DRAW_FRAMEBUFFER, WebGL.COLOR_ATTACHMENT0, properties.get( dstTexture )['__webglTexture'], dstLevel, dstZ + i );
}
_gl.blitFramebuffer( minX, minY, width, height, dstX, dstY, width, height, WebGL.DEPTH_BUFFER_BIT, WebGL.NEAREST );
}
state.bindFramebuffer( WebGL.READ_FRAMEBUFFER, null );
state.bindFramebuffer( WebGL.DRAW_FRAMEBUFFER, null );
}
else if ( srcLevel != 0 || srcTexture.isRenderTargetTexture || properties.has( srcTexture ) ) {
// get the appropriate frame buffers
final srcTextureProperties = properties.get( srcTexture );
final dstTextureProperties = properties.get( dstTexture );
// bind the frame buffer targets
state.bindFramebuffer( WebGL.READ_FRAMEBUFFER, _srcFramebuffer );
state.bindFramebuffer( WebGL.DRAW_FRAMEBUFFER, _dstFramebuffer );
for (int i = 0; i < depth; i ++ ) {
// assign the correct layers and mip maps to the frame buffers
if ( isSrc3D ) {
_gl.framebufferTextureLayer( WebGL.READ_FRAMEBUFFER, WebGL.COLOR_ATTACHMENT0, srcTextureProperties['__webglTexture'], srcLevel, minZ + i );
}
else {
_gl.framebufferTexture2D( WebGL.READ_FRAMEBUFFER, WebGL.COLOR_ATTACHMENT0, WebGL.TEXTURE_2D, srcTextureProperties['__webglTexture'], srcLevel );
}
if ( isDst3D ) {
_gl.framebufferTextureLayer( WebGL.DRAW_FRAMEBUFFER, WebGL.COLOR_ATTACHMENT0, dstTextureProperties['__webglTexture'], dstLevel, dstZ + i );
}
else {
_gl.framebufferTexture2D( WebGL.DRAW_FRAMEBUFFER, WebGL.COLOR_ATTACHMENT0, WebGL.TEXTURE_2D, dstTextureProperties['__webglTexture'], dstLevel );
}
// copy the data using the fastest function that can achieve the copy
if ( srcLevel != 0 ) {
_gl.blitFramebuffer( minX, minY, width, height, dstX, dstY, width, height, WebGL.COLOR_BUFFER_BIT, WebGL.NEAREST );
} else if ( isDst3D ) {
_gl.copyTexSubImage3D( glTarget, dstLevel, dstX, dstY, dstZ + i, minX, minY, width, height );
} else {
_gl.copyTexSubImage2D( glTarget, dstLevel, dstX, dstY, minX, minY, width, height );
}
}
// unbind read, draw buffers
state.bindFramebuffer( WebGL.READ_FRAMEBUFFER, null );
state.bindFramebuffer( WebGL.DRAW_FRAMEBUFFER, null );
}
else {
if ( isDst3D ) {
// copy data into the 3d texture
if ( srcTexture is DataTexture || srcTexture is Data3DTexture ) {
_gl.texSubImage3D( glTarget, dstLevel, dstX, dstY, dstZ, width, height, depth, glFormat, glType, image.data );
}
else if ( dstTexture is CompressedArrayTexture ) {
_gl.compressedTexSubImage3D( glTarget, dstLevel, dstX, dstY, dstZ, width, height, depth, glFormat, image.data );
}
else {
_gl.texSubImage3D( glTarget, dstLevel, dstX, dstY, dstZ, width, height, depth, glFormat, glType, image );
}
}
else {
// copy data into the 2d texture
if ( srcTexture is DataTexture ) {
_gl.texSubImage2D( WebGL.TEXTURE_2D, dstLevel, dstX, dstY, width, height, glFormat, glType, image.data );
}
else if ( srcTexture.isCompressedTexture ) {
_gl.compressedTexSubImage2D( WebGL.TEXTURE_2D, dstLevel, dstX, dstY, image.width, image.height, glFormat, image.data );
}
else {
_gl.texSubImage2D( WebGL.TEXTURE_2D, dstLevel, dstX, dstY, width, height, glFormat, glType, image );
}
}
}
// reset values
_gl.pixelStorei( WebGL.UNPACK_ROW_LENGTH, currentUnpackRowLen );
_gl.pixelStorei( WebGL.UNPACK_IMAGE_HEIGHT, currentUnpackImageHeight );
_gl.pixelStorei( WebGL.UNPACK_SKIP_PIXELS, currentUnpackSkipPixels );
_gl.pixelStorei( WebGL.UNPACK_SKIP_ROWS, currentUnpackSkipRows );
_gl.pixelStorei( WebGL.UNPACK_SKIP_IMAGES, currentUnpackSkipImages );
// Generate mipmaps only when copying level 0
if ( dstLevel == 0 && dstTexture.generateMipmaps ) {
_gl.generateMipmap( glTarget );
}
state.unbindTexture();
}