diff --git a/examples/jsm/renderers/webgl/WebGLBackend.js b/examples/jsm/renderers/webgl/WebGLBackend.js index 1f72606d4f0371..2f3e1081960ebd 100644 --- a/examples/jsm/renderers/webgl/WebGLBackend.js +++ b/examples/jsm/renderers/webgl/WebGLBackend.js @@ -43,6 +43,10 @@ class WebGLBackend extends Backend { this.extensions.get( 'EXT_color_buffer_float' ); this._currentContext = null; + this.maxTexture = this.gl.getParameter( this.gl.MAX_TEXTURE_IMAGE_UNITS ); + this.activeTextureUnit = null; + this.textureBindings = Array( this.maxTexture ); + } get coordinateSystem() { @@ -312,8 +316,7 @@ class WebGLBackend extends Backend { } else if ( binding.isSampledTexture ) { - gl.activeTexture( gl.TEXTURE0 + index ); - gl.bindTexture( bindingData.glTextureType, bindingData.textureGPU ); + this._bindTexture( binding.texture, index ); } @@ -455,12 +458,26 @@ class WebGLBackend extends Backend { const glTextureType = textureUtils.getGLTextureType( texture ); let textureGPU = defaultTextures[ glTextureType ]; + let firstUse = false; if ( textureGPU === undefined ) { textureGPU = gl.createTexture(); + firstUse = true; + + } + + this.set( texture, { + textureGPU, + glTextureType, + isDefault: true, + unit: null + } ); + + if ( firstUse ) { + + this._bindTexture( texture ); - gl.bindTexture( glTextureType, textureGPU ); gl.texParameteri( glTextureType, gl.TEXTURE_MIN_FILTER, gl.NEAREST ); gl.texParameteri( glTextureType, gl.TEXTURE_MAG_FILTER, gl.NEAREST ); @@ -470,12 +487,6 @@ class WebGLBackend extends Backend { } - this.set( texture, { - textureGPU, - glTextureType, - isDefault: true - } ); - } createTexture( texture, options ) { @@ -490,7 +501,16 @@ class WebGLBackend extends Backend { const textureGPU = gl.createTexture(); const glTextureType = textureUtils.getGLTextureType( texture ); - gl.bindTexture( glTextureType, textureGPU ); + this.set( texture, { + textureGPU, + glTextureType, + glFormat, + glType, + glInternalFormat, + unit: null + } ); + + this._bindTexture( texture ); gl.pixelStorei( gl.UNPACK_FLIP_Y_WEBGL, texture.flipY ); gl.pixelStorei( gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha ); @@ -499,29 +519,19 @@ class WebGLBackend extends Backend { textureUtils.setTextureParameters( glTextureType, texture ); - gl.bindTexture( glTextureType, textureGPU ); - if ( ! texture.isVideoTexture ) { gl.texStorage2D( glTextureType, levels, glInternalFormat, width, height ); } - this.set( texture, { - textureGPU, - glTextureType, - glFormat, - glType, - glInternalFormat - } ); - } updateTexture( texture, options ) { const { gl } = this; const { width, height } = options; - const { textureGPU, glTextureType, glFormat, glType, glInternalFormat } = this.get( texture ); + const { glTextureType, glFormat, glType, glInternalFormat } = this._bindTexture( texture ); const getImage = ( source ) => { @@ -539,8 +549,6 @@ class WebGLBackend extends Backend { }; - gl.bindTexture( glTextureType, textureGPU ); - if ( texture.isCubeTexture ) { const images = options.images; @@ -573,16 +581,22 @@ class WebGLBackend extends Backend { generateMipmaps( texture ) { const { gl } = this; - const { textureGPU, glTextureType } = this.get( texture ); + const { glTextureType } = this._bindTexture( texture ); - gl.bindTexture( glTextureType, textureGPU ); gl.generateMipmap( glTextureType ); } - destroyTexture( /*texture*/ ) { + destroyTexture( texture ) { - console.warn( 'Abstract class.' ); + const { gl } = this; + const { textureGPU } = this.get( texture ); + + this.textureBindings[ textureGPU ] = null; + + gl.deleteTexture( textureGPU ); + + this.delete( texture ); } @@ -785,12 +799,8 @@ class WebGLBackend extends Backend { } else if ( binding.isSampledTexture ) { - const { textureGPU, glTextureType } = this.get( binding.texture ); - this.set( binding, { - index: textureIndex ++, - textureGPU, - glTextureType + index: textureIndex ++ } ); } @@ -890,10 +900,9 @@ class WebGLBackend extends Backend { } else { - gl.bindTexture( gl.TEXTURE_2D, textureGPU ); - gl.copyTexSubImage2D( gl.TEXTURE_2D, 0, 0, 0, 0, 0, width, height ); + this._bindTexture( texture ); - gl.bindTexture( gl.TEXTURE_2D, null ); + gl.copyTexSubImage2D( gl.TEXTURE_2D, 0, 0, 0, 0, 0, width, height ); } @@ -962,6 +971,38 @@ class WebGLBackend extends Backend { } + _bindTexture( texture, unit ) { + + const textureData = this.get( texture ); + + const { gl, textureBindings, maxTexture } = this; + const { glTextureType, textureGPU } = textureData; + + if ( unit === undefined ) unit = textureData.unit === null ? maxTexture - 1 : textureData.unit; + + if ( this.activeTextureUnit !== unit ) { + + gl.activeTexture( gl.TEXTURE0 + unit ); + this.activeTextureUnit = unit; + + } + + if ( textureBindings[ unit ] !== textureGPU ) { + + const oldBinding = textureBindings[ unit ]; + if ( oldBinding !== undefined ) oldBinding.unit = null; + + gl.bindTexture( glTextureType, textureGPU ); + + textureBindings[ unit ] = textureGPU; + textureData.unit = unit; + + } + + return textureData; + + } + } export default WebGLBackend;