diff --git a/docs/api/en/renderers/WebGLRenderer.html b/docs/api/en/renderers/WebGLRenderer.html index ce1ba15f2502bc..640b3694ae13db 100644 --- a/docs/api/en/renderers/WebGLRenderer.html +++ b/docs/api/en/renderers/WebGLRenderer.html @@ -310,6 +310,9 @@

[method:null copyFramebufferToTexture]( [param:Vector2 position], [param:Tex

[method:null copyTextureToTexture]( [param:Vector2 position], [param:Texture srcTexture], [param:Texture dstTexture], [param:Number level] )

Copies all pixels of a texture to an existing texture starting from the given position. Enables access to [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/texSubImage2D WebGLRenderingContext.texSubImage2D].

+

[method:null copyTextureToTexture3D]( [param:Box3 sourceBox], [param:Vector2 position], [param:Texture srcTexture], [param:Texture dstTexture], [param:Number level] )

+

Copies the pixels of a texture in the bounds '[page:Box3 sourceBox]' in the desination texture starting from the given position. Enables access to [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/texSubImage3D WebGL2RenderingContext.texSubImage3D].

+

[method:null dispose]( )

Dispose of the current rendering context.

diff --git a/examples/files.json b/examples/files.json index 6c0a0db3c02dd0..e6928ef0a17e5d 100644 --- a/examples/files.json +++ b/examples/files.json @@ -319,6 +319,7 @@ "webgl2_materials_texture3d", "webgl2_multisampled_renderbuffers", "webgl2_rendertarget_texture2darray", + "webgl2_materials_texture3d_partialupdate.html", "webgl2_volume_cloud", "webgl2_volume_instancing", "webgl2_volume_perlin" diff --git a/examples/webgl2_materials_texture3d_partialupdate.html b/examples/webgl2_materials_texture3d_partialupdate.html new file mode 100644 index 00000000000000..db841419f16290 --- /dev/null +++ b/examples/webgl2_materials_texture3d_partialupdate.html @@ -0,0 +1,358 @@ + + + + three.js webgl2 - volume - cloud + + + + + + +
+ three.js webgl2 - volume - cloud +
+ + + + + diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js index 5c50a0c11b923f..451552aca98644 100644 --- a/src/renderers/WebGLRenderer.js +++ b/src/renderers/WebGLRenderer.js @@ -1987,6 +1987,80 @@ function WebGLRenderer( parameters ) { }; + this.copyTextureToTexture3D = function ( sourceBox, position, srcTexture, dstTexture, level = 0 ) { + + if ( _this.isWebGL1Renderer ) { + + console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: can only be used with WebGL2.' ); + return; + + } + + const { width, height, data } = srcTexture.image; + const glFormat = utils.convert( dstTexture.format ); + const glType = utils.convert( dstTexture.type ); + let glTarget; + + if ( dstTexture.isDataTexture3D ) { + + textures.setTexture3D( dstTexture, 0 ); + glTarget = _gl.TEXTURE_3D; + + } else if ( dstTexture.isDataTexture2DArray ) { + + textures.setTexture2DArray( dstTexture, 0 ); + glTarget = _gl.TEXTURE_2D_ARRAY; + + } else { + + console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.' ); + return; + + } + + _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 unpackRowLen = _gl.getParameter( _gl.UNPACK_ROW_LENGTH ); + const unpackImageHeight = _gl.getParameter( _gl.UNPACK_IMAGE_HEIGHT ); + const unpackSkipPixels = _gl.getParameter( _gl.UNPACK_SKIP_PIXELS ); + const unpackSkipRows = _gl.getParameter( _gl.UNPACK_SKIP_ROWS ); + const unpackSkipImages = _gl.getParameter( _gl.UNPACK_SKIP_IMAGES ); + + _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, width ); + _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, height ); + _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, sourceBox.min.x ); + _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, sourceBox.min.y ); + _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, sourceBox.min.z ); + + _gl.texSubImage3D( + glTarget, + level, + position.x, + position.y, + position.z, + sourceBox.max.x - sourceBox.min.x + 1, + sourceBox.max.y - sourceBox.min.y + 1, + sourceBox.max.z - sourceBox.min.z + 1, + glFormat, + glType, + data + ); + + _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, unpackRowLen ); + _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, unpackImageHeight ); + _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, unpackSkipPixels ); + _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, unpackSkipRows ); + _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, unpackSkipImages ); + + // Generate mipmaps only when copying level 0 + if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( glTarget ); + + state.unbindTexture(); + + }; + this.initTexture = function ( texture ) { textures.setTexture2D( texture, 0 ); diff --git a/utils/build/rollup.config.js b/utils/build/rollup.config.js index 240e78392aa170..912649d8333174 100644 --- a/utils/build/rollup.config.js +++ b/utils/build/rollup.config.js @@ -153,6 +153,11 @@ function glconstants() { MAX_FRAGMENT_UNIFORM_VECTORS: 36349, UNPACK_FLIP_Y_WEBGL: 37440, UNPACK_PREMULTIPLY_ALPHA_WEBGL: 37441, + UNPACK_ROW_LENGTH: 3314, + UNPACK_IMAGE_HEIGHT: 32878, + UNPACK_SKIP_PIXELS: 3316, + UNPACK_SKIP_ROWS: 3315, + UNPACK_SKIP_IMAGES: 32877, MAX_SAMPLES: 36183, READ_FRAMEBUFFER: 36008, DRAW_FRAMEBUFFER: 36009