diff --git a/docs/api/en/textures/CompressedArrayTexture.html b/docs/api/en/textures/CompressedArrayTexture.html index 7c2d2ba2a25c0..0b1cfcd5ee6f2 100644 --- a/docs/api/en/textures/CompressedArrayTexture.html +++ b/docs/api/en/textures/CompressedArrayTexture.html @@ -61,11 +61,32 @@

[property:number wrapR]

[property:Object image]

Overridden with a object containing width, height, and depth.

+

[property:Set layerUpdates]

+

+ A set of all layers which need to be updated in the texture. See + [Page:CompressedTextureArray.addLayerUpdate addLayerUpdate]. +

+

[property:Boolean isCompressedArrayTexture]

Read-only flag to check if a given object is of type [name].

Methods

+

[method:addLayerUpdate addLayerUpdate]( layerIndex )

+

+ Describes that a specific layer of the texture needs to be updated. + Normally when [page:Texture.needsUpdate needsUpdate] is set to true, the + entire compressed texture array is sent to the GPU. Marking specific + layers will only transmit subsets of all mipmaps associated with a + specific depth in the array which is often much more performant. +

+ +

[method:clearLayerUpdates clearLayerUpdates]()

+

+ Resets the layer updates registry. See + [Page:CompressedTextureArray.addLayerUpdate addLayerUpdate]. +

+

See the base [page:CompressedTexture CompressedTexture] class for common methods. diff --git a/docs/api/en/textures/DataArrayTexture.html b/docs/api/en/textures/DataArrayTexture.html index 2c4d4e94fff4a..0848d826c3185 100644 --- a/docs/api/en/textures/DataArrayTexture.html +++ b/docs/api/en/textures/DataArrayTexture.html @@ -143,8 +143,30 @@

[property:number wrapR]

page for details.

+

[property:Set layerUpdates]

+

+ A set of all layers which need to be updated in the texture. See + [Page:DataArrayTexture.addLayerUpdate addLayerUpdate]. +

+

Methods

+

[method:addLayerUpdate addLayerUpdate]( layerIndex )

+

+ Describes that a specific layer of the texture needs to be updated. + Normally when [page:Texture.needsUpdate needsUpdate] is set to true, the + entire compressed texture array is sent to the GPU. Marking specific + layers will only transmit subsets of all mipmaps associated with a + specific depth in the array which is often much more performant. +

+ +

[method:clearLayerUpdates clearLayerUpdates]()

+

+ Resets the layer updates registry. See + [Page:DataArrayTexture.addLayerUpdate addLayerUpdate]. +

+ +

See the base [page:Texture Texture] class for common methods.

Source

diff --git a/src/renderers/webgl/WebGLTextures.js b/src/renderers/webgl/WebGLTextures.js index 1d8f9553a1772..1aa1e9f7bdb47 100644 --- a/src/renderers/webgl/WebGLTextures.js +++ b/src/renderers/webgl/WebGLTextures.js @@ -820,7 +820,22 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( dataReady ) { - state.compressedTexSubImage3D( _gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, mipmap.data, 0, 0 ); + if ( texture.layerUpdates.size > 0 ) { + + for ( const layerIndex of texture.layerUpdates ) { + + const layerSize = mipmap.width * mipmap.height; + state.compressedTexSubImage3D( _gl.TEXTURE_2D_ARRAY, i, 0, 0, layerIndex, mipmap.width, mipmap.height, 1, glFormat, mipmap.data.slice( layerSize * layerIndex, layerSize * ( layerIndex + 1 ) ), 0, 0 ); + + } + + texture.clearLayerUpdates(); + + } else { + + state.compressedTexSubImage3D( _gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, mipmap.data, 0, 0 ); + + } } @@ -926,7 +941,72 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( dataReady ) { - state.texSubImage3D( _gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data ); + if ( texture.layerUpdates.size > 0 ) { + + // When type is GL_UNSIGNED_BYTE, each of these bytes is + // interpreted as one color component, depending on format. When + // type is one of GL_UNSIGNED_SHORT_5_6_5, + // GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_5_5_5_1, each + // unsigned value is interpreted as containing all the components + // for a single pixel, with the color components arranged + // according to format. + // + // See https://registry.khronos.org/OpenGL-Refpages/es1.1/xhtml/glTexImage2D.xml + let texelSize; + switch ( glType ) { + + case _gl.UNSIGNED_BYTE: + switch ( glFormat ) { + + case _gl.ALPHA: + texelSize = 1; + break; + case _gl.LUMINANCE: + texelSize = 1; + break; + case _gl.LUMINANCE_ALPHA: + texelSize = 2; + break; + case _gl.RGB: + texelSize = 3; + break; + case _gl.RGBA: + texelSize = 4; + break; + + default: + throw new Error( `Unknown texel size for format ${glFormat}.` ); + + } + + break; + + case _gl.UNSIGNED_SHORT_4_4_4_4: + case _gl.UNSIGNED_SHORT_5_5_5_1: + case _gl.UNSIGNED_SHORT_5_6_5: + texelSize = 1; + break; + + default: + throw new Error( `Unknown texel size for type ${glType}.` ); + + } + + const layerSize = image.width * image.height * texelSize; + + for ( const layerIndex of texture.layerUpdates ) { + + state.texSubImage3D( _gl.TEXTURE_2D_ARRAY, 0, 0, 0, layerIndex, image.width, image.height, 1, glFormat, glType, image.data.slice( layerSize * layerIndex, layerSize * ( layerIndex + 1 ) ) ); + + } + + texture.clearLayerUpdates(); + + } else { + + state.texSubImage3D( _gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data ); + + } } diff --git a/src/textures/CompressedArrayTexture.js b/src/textures/CompressedArrayTexture.js index cc062e695d41b..80aa2132b1b86 100644 --- a/src/textures/CompressedArrayTexture.js +++ b/src/textures/CompressedArrayTexture.js @@ -11,6 +11,20 @@ class CompressedArrayTexture extends CompressedTexture { this.image.depth = depth; this.wrapR = ClampToEdgeWrapping; + this.layerUpdates = new Set(); + + } + + addLayerUpdates( layerIndex ) { + + this.layerUpdates.add( layerIndex ); + + } + + clearLayerUpdates() { + + this.layerUpdates.clear(); + } } diff --git a/src/textures/DataArrayTexture.js b/src/textures/DataArrayTexture.js index 759973df66378..daac7aad1c3f4 100644 --- a/src/textures/DataArrayTexture.js +++ b/src/textures/DataArrayTexture.js @@ -20,6 +20,20 @@ class DataArrayTexture extends Texture { this.flipY = false; this.unpackAlignment = 1; + this.layerUpdates = new Set(); + + } + + addLayerUpdate( layerIndex ) { + + this.layerUpdates.add( layerIndex ); + + } + + clearLayerUpdates() { + + this.layerUpdates.clear(); + } }