diff --git a/docs/api/en/renderers/WebGLRenderer.html b/docs/api/en/renderers/WebGLRenderer.html
index 6b49a59f5caf06..ad2f41a6271c85 100644
--- a/docs/api/en/renderers/WebGLRenderer.html
+++ b/docs/api/en/renderers/WebGLRenderer.html
@@ -380,21 +380,13 @@
- [method:undefined copyTextureToTexture]( [param:Texture srcTexture], [param:Texture dstTexture], [param:Box2 srcRegion], [param:Vector2 dstPosition], [param:Number level] )
-
-
- Copies the pixels of a texture in the bounds '[page:Box2 srcRegion]' in the destination texture starting from the given position.
- The `depthTexture` and `texture` property of render targets are supported as well.
- When using render target textures as `srcTexture` and `dstTexture`, you must make sure both render targets are intitialized e.g. via [page:.initRenderTarget]().
-
-
-
- [method:undefined copyTextureToTexture3D]( [param:Texture srcTexture], [param:Texture dstTexture], [param:Box3 srcRegion], [param:Vector3 dstPosition], [param:Number level] )
+ [method:undefined copyTextureToTexture]( [param:Texture srcTexture], [param:Texture dstTexture], [param:Box2 srcRegion] | [param:Box3 srcRegion], [param:Vector2 dstPosition] | [param:Vector3 dstPosition], [param:Number dstLevel] )
Copies the pixels of a texture in the bounds '[page:Box3 srcRegion]' in the destination texture starting from the given position.
- The `depthTexture` and `texture` property of 3D render targets are supported as well.
- When using render target textures as `srcTexture` and `dstTexture`, you must make sure both render targets are intitialized e.g. via [page:.initRenderTarget]().
+ 2D Texture, 3D Textures, or a mix of the two can be used as source and destination texture arguments for copying between layers of 3d textures.
+ The `depthTexture` and `texture` property of render targets are supported as well.
+ When using render target textures as `srcTexture` and `dstTexture`, you must make sure both render targets are initialized e.g. via [page:.initRenderTarget]().
[method:undefined dispose]( )
diff --git a/src/objects/BatchedMesh.js b/src/objects/BatchedMesh.js
index e873e3c8f53313..cf1617951bb6e5 100644
--- a/src/objects/BatchedMesh.js
+++ b/src/objects/BatchedMesh.js
@@ -744,6 +744,7 @@ class BatchedMesh extends Mesh {
}
nextVertexStart += geometryInfo.reservedVertexCount;
+ geometryInfo.start = geometry.index ? geometryInfo.indexStart : geometryInfo.vertexStart;
// step the next geometry points to the shifted position
this._nextIndexStart = geometry.index ? geometryInfo.indexStart + geometryInfo.reservedIndexCount : 0;
diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js
index 33bf1a112c0e64..dc6219794ceee2 100644
--- a/src/renderers/WebGLRenderer.js
+++ b/src/renderers/WebGLRenderer.js
@@ -2579,134 +2579,7 @@ class WebGLRenderer {
}
- let width, height, minX, minY;
- let dstX, dstY;
- if ( srcRegion !== null ) {
-
- width = srcRegion.max.x - srcRegion.min.x;
- height = srcRegion.max.y - srcRegion.min.y;
- minX = srcRegion.min.x;
- minY = srcRegion.min.y;
-
- } else {
-
- width = srcTexture.image.width;
- height = srcTexture.image.height;
- minX = 0;
- minY = 0;
-
- }
-
- if ( dstPosition !== null ) {
-
- dstX = dstPosition.x;
- dstY = dstPosition.y;
-
- } else {
-
- dstX = 0;
- dstY = 0;
-
- }
-
- const glFormat = utils.convert( dstTexture.format );
- const glType = utils.convert( dstTexture.type );
-
- textures.setTexture2D( dstTexture, 0 );
-
- // As another texture upload may have changed pixelStorei
- // parameters, make sure they are correct for the dstTexture
- _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY );
- _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha );
- _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment );
-
- const currentUnpackRowLen = _gl.getParameter( _gl.UNPACK_ROW_LENGTH );
- const currentUnpackImageHeight = _gl.getParameter( _gl.UNPACK_IMAGE_HEIGHT );
- const currentUnpackSkipPixels = _gl.getParameter( _gl.UNPACK_SKIP_PIXELS );
- const currentUnpackSkipRows = _gl.getParameter( _gl.UNPACK_SKIP_ROWS );
- 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_IMAGE_HEIGHT, image.height );
- _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, minX );
- _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, minY );
-
- if ( srcTexture.isRenderTargetTexture || srcTexture.isDepthTexture ) {
-
- const srcTextureProperties = properties.get( srcTexture );
- const dstTextureProperties = properties.get( dstTexture );
- const srcRenderTargetProperties = properties.get( srcTextureProperties.__renderTarget );
- const dstRenderTargetProperties = properties.get( dstTextureProperties.__renderTarget );
-
- state.bindFramebuffer( _gl.READ_FRAMEBUFFER, srcRenderTargetProperties.__webglFramebuffer );
- state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, dstRenderTargetProperties.__webglFramebuffer );
-
- if ( srcTexture.isDepthTexture ) {
-
- _gl.blitFramebuffer( minX, minY, width, height, dstX, dstY, width, height, _gl.DEPTH_BUFFER_BIT, _gl.NEAREST );
-
- } else {
-
- _gl.copyTexSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, minX, minY, width, height );
-
- }
-
- state.bindFramebuffer( _gl.READ_FRAMEBUFFER, null );
- state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, null );
-
- } else {
-
- if ( srcTexture.isDataTexture ) {
-
- _gl.texSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, width, height, glFormat, glType, image.data );
-
- } else {
-
- if ( srcTexture.isCompressedTexture ) {
-
- _gl.compressedTexSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, image.width, image.height, glFormat, image.data );
-
- } else {
-
- _gl.texSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, width, height, glFormat, glType, image );
-
- }
-
- }
-
- }
-
- _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, currentUnpackRowLen );
- _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, currentUnpackImageHeight );
- _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, currentUnpackSkipPixels );
- _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, currentUnpackSkipRows );
- _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, currentUnpackSkipImages );
-
- // Generate mipmaps only when copying level 0
- if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( _gl.TEXTURE_2D );
-
- state.unbindTexture();
-
- };
-
- this.copyTextureToTexture3D = function ( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) {
-
- // support previous signature with source box first
- if ( srcTexture.isTexture !== true ) {
-
- // @deprecated, r165
- warnOnce( 'WebGLRenderer: copyTextureToTexture3D function signature has changed.' );
-
- srcRegion = arguments[ 0 ] || null;
- dstPosition = arguments[ 1 ] || null;
- srcTexture = arguments[ 2 ];
- dstTexture = arguments[ 3 ];
- level = arguments[ 4 ] || 0;
-
- }
-
+ // gather the necessary dimensions to copy
let width, height, depth, minX, minY, minZ;
let dstX, dstY, dstZ;
const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ level ] : srcTexture.image;
@@ -2714,16 +2587,16 @@ class WebGLRenderer {
width = srcRegion.max.x - srcRegion.min.x;
height = srcRegion.max.y - srcRegion.min.y;
- depth = srcRegion.max.z - srcRegion.min.z;
+ depth = srcRegion.isBox3 ? srcRegion.max.z - srcRegion.min.z : 1;
minX = srcRegion.min.x;
minY = srcRegion.min.y;
- minZ = srcRegion.min.z;
+ minZ = srcRegion.isBox3 ? srcRegion.min.z : 0;
} else {
width = image.width;
height = image.height;
- depth = image.depth;
+ depth = image.depth || 1;
minX = 0;
minY = 0;
minZ = 0;
@@ -2744,6 +2617,7 @@ class WebGLRenderer {
}
+ // Set up the destination target
const glFormat = utils.convert( dstTexture.format );
const glType = utils.convert( dstTexture.type );
let glTarget;
@@ -2760,8 +2634,8 @@ class WebGLRenderer {
} else {
- console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.' );
- return;
+ textures.setTexture2D( dstTexture, 0 );
+ glTarget = _gl.TEXTURE_2D;
}
@@ -2769,6 +2643,7 @@ class WebGLRenderer {
_gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha );
_gl.pixelStorei( _gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment );
+ // used for copying data from cpu
const currentUnpackRowLen = _gl.getParameter( _gl.UNPACK_ROW_LENGTH );
const currentUnpackImageHeight = _gl.getParameter( _gl.UNPACK_IMAGE_HEIGHT );
const currentUnpackSkipPixels = _gl.getParameter( _gl.UNPACK_SKIP_PIXELS );
@@ -2781,6 +2656,9 @@ class WebGLRenderer {
_gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, minY );
_gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, minZ );
+ // set up the src texture
+ const isSrc3D = srcTexture.isDataArrayTexture || srcTexture.isData3DTexture;
+ const isDst3D = dstTexture.isDataArrayTexture || dstTexture.isData3DTexture;
if ( srcTexture.isRenderTargetTexture || srcTexture.isDepthTexture ) {
const srcTextureProperties = properties.get( srcTexture );
@@ -2793,17 +2671,31 @@ class WebGLRenderer {
for ( let i = 0; i < depth; i ++ ) {
- _gl.framebufferTextureLayer( _gl.READ_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, properties.get( srcTexture ).__webglTexture, level, minZ + i );
+ // if the source or destination are a 3d target then a layer needs to be bound
+ if ( isSrc3D ) {
+
+ _gl.framebufferTextureLayer( _gl.READ_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, properties.get( srcTexture ).__webglTexture, level, minZ + i );
+
+ }
if ( srcTexture.isDepthTexture ) {
- _gl.framebufferTextureLayer( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, properties.get( dstTexture ).__webglTexture, level, dstZ + i );
+ if ( isDst3D ) {
+
+ _gl.framebufferTextureLayer( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, properties.get( dstTexture ).__webglTexture, level, dstZ + i );
+
+ }
+
_gl.blitFramebuffer( minX, minY, width, height, dstX, dstY, width, height, _gl.DEPTH_BUFFER_BIT, _gl.NEAREST );
- } else {
+ } else if ( isDst3D ) {
_gl.copyTexSubImage3D( glTarget, level, dstX, dstY, dstZ + i, minX, minY, width, height );
+ } else {
+
+ _gl.copyTexSubImage2D( glTarget, level, dstX, dstY, dstZ + i, minX, minY, width, height );
+
}
}
@@ -2813,13 +2705,14 @@ class WebGLRenderer {
} else {
- if ( srcTexture.isDataTexture || srcTexture.isData3DTexture ) {
+ if ( isDst3D ) {
- _gl.texSubImage3D( glTarget, level, dstX, dstY, dstZ, width, height, depth, glFormat, glType, image.data );
+ // copy data into the 3d texture
+ if ( srcTexture.isDataTexture || srcTexture.isData3DTexture ) {
- } else {
+ _gl.texSubImage3D( glTarget, level, dstX, dstY, dstZ, width, height, depth, glFormat, glType, image.data );
- if ( dstTexture.isCompressedArrayTexture ) {
+ } else if ( dstTexture.isCompressedArrayTexture ) {
_gl.compressedTexSubImage3D( glTarget, level, dstX, dstY, dstZ, width, height, depth, glFormat, image.data );
@@ -2829,10 +2722,28 @@ class WebGLRenderer {
}
+ } else {
+
+ // copy data into the 2d texture
+ if ( srcTexture.isDataTexture ) {
+
+ _gl.texSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, width, height, glFormat, glType, image.data );
+
+ } else if ( srcTexture.isCompressedTexture ) {
+
+ _gl.compressedTexSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, image.width, image.height, glFormat, image.data );
+
+ } else {
+
+ _gl.texSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, width, height, glFormat, glType, image );
+
+ }
+
}
}
+ // reset values
_gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, currentUnpackRowLen );
_gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, currentUnpackImageHeight );
_gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, currentUnpackSkipPixels );
@@ -2840,12 +2751,39 @@ class WebGLRenderer {
_gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, currentUnpackSkipImages );
// Generate mipmaps only when copying level 0
- if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( glTarget );
+ if ( level === 0 && dstTexture.generateMipmaps ) {
+
+ _gl.generateMipmap( glTarget );
+
+ }
state.unbindTexture();
};
+ this.copyTextureToTexture3D = function ( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) {
+
+ // support previous signature with source box first
+ if ( srcTexture.isTexture !== true ) {
+
+ // @deprecated, r165
+ warnOnce( 'WebGLRenderer: copyTextureToTexture3D function signature has changed.' );
+
+ srcRegion = arguments[ 0 ] || null;
+ dstPosition = arguments[ 1 ] || null;
+ srcTexture = arguments[ 2 ];
+ dstTexture = arguments[ 3 ];
+ level = arguments[ 4 ] || 0;
+
+ }
+
+ // @deprecated, r170
+ warnOnce( 'WebGLRenderer: copyTextureToTexture3D function has been deprecated. Use "copyTextureToTexture" instead.' );
+
+ return this.copyTextureToTexture( srcTexture, dstTexture, srcRegion, dstPosition, level );
+
+ };
+
this.initRenderTarget = function ( target ) {
if ( properties.get( target ).__webglFramebuffer === undefined ) {