_updateTexParameters() {
        // be sure we're updating the right texture
        if(this.index && this.renderer.state.activeTexture !== this.index) {
            this._bindTexture();
        }

        // wrapS
        if(this.parameters.wrapS !== this._state.wrapS) {
            if(!this.renderer._isWebGL2 && (!isPowerOf2(this._size.width) || !isPowerOf2(this._size.height))) {
                this.parameters.wrapS = this.gl.CLAMP_TO_EDGE;
            }

            // handle wrong wrapS values
            if(
                this.parameters.wrapS !== this.gl.REPEAT
                && this.parameters.wrapS !== this.gl.CLAMP_TO_EDGE
                && this.parameters.wrapS !== this.gl.MIRRORED_REPEAT
            ) {
                if(!this.renderer.production) {
                    throwWarning(this.type + ": Wrong wrapS value", this.parameters.wrapS, "for this texture:", this, "\ngl.CLAMP_TO_EDGE wrapping will be used instead");
                }
                this.parameters.wrapS = this.gl.CLAMP_TO_EDGE;
            }

            this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.parameters.wrapS);
            this._state.wrapS = this.parameters.wrapS;
        }

        // wrapT
        if(this.parameters.wrapT !== this._state.wrapT) {
            if(!this.renderer._isWebGL2 && (!isPowerOf2(this._size.width) || !isPowerOf2(this._size.height))) {
                this.parameters.wrapT = this.gl.CLAMP_TO_EDGE;
            }

            // handle wrong wrapT values
            if(
                this.parameters.wrapT !== this.gl.REPEAT
                && this.parameters.wrapT !== this.gl.CLAMP_TO_EDGE
                && this.parameters.wrapT !== this.gl.MIRRORED_REPEAT
            ) {
                if(!this.renderer.production) {
                    throwWarning(this.type + ": Wrong wrapT value", this.parameters.wrapT, "for this texture:", this, "\ngl.CLAMP_TO_EDGE wrapping will be used instead");
                }
                this.parameters.wrapT = this.gl.CLAMP_TO_EDGE;
            }

            this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.parameters.wrapT);
            this._state.wrapT = this.parameters.wrapT;
        }

        // generate mip map only if it has a source
        if(this.parameters.generateMipmap && !this._state.generateMipmap && this.source) {
            if(!this.renderer._isWebGL2 && (!isPowerOf2(this._size.width) || !isPowerOf2(this._size.height))) {
                this.parameters.generateMipmap = false;
            }
            else {
                this.gl.generateMipmap(this.gl.TEXTURE_2D);
            }

            this._state.generateMipmap = this.parameters.generateMipmap;
        }

        // min filter
        if(this.parameters.minFilter !== this._state.minFilter) {
            // WebGL1 and non PO2
            if(!this.renderer._isWebGL2 && (!isPowerOf2(this._size.width) || !isPowerOf2(this._size.height))) {
                this.parameters.minFilter = this.gl.LINEAR;
            }

            // at this point if generateMipmap is null it means we will generate them later on
            if(!this.parameters.generateMipmap && this.parameters.generateMipmap !== null) {
                this.parameters.minFilter = this.gl.LINEAR;
            }

            // handle wrong minFilter values
            if(
                this.parameters.minFilter !== this.gl.LINEAR
                && this.parameters.minFilter !== this.gl.NEAREST
                && this.parameters.minFilter !== this.gl.NEAREST_MIPMAP_NEAREST
                && this.parameters.minFilter !== this.gl.LINEAR_MIPMAP_NEAREST
                && this.parameters.minFilter !== this.gl.NEAREST_MIPMAP_LINEAR
                && this.parameters.minFilter !== this.gl.LINEAR_MIPMAP_LINEAR
            ) {
                if(!this.renderer.production) {
                    throwWarning(this.type + ": Wrong minFilter value", this.parameters.minFilter, "for this texture:", this, "\ngl.LINEAR filtering will be used instead");
                }
                this.parameters.minFilter = this.gl.LINEAR;
            }

            this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.parameters.minFilter);
            this._state.minFilter = this.parameters.minFilter;
        }

        // mag filter
        if(this.parameters.magFilter !== this._state.magFilter) {
            if(!this.renderer._isWebGL2 && (!isPowerOf2(this._size.width) || !isPowerOf2(this._size.height))) {
                this.parameters.magFilter = this.gl.LINEAR;
            }

            // handle wrong magFilter values
            if(
                this.parameters.magFilter !== this.gl.LINEAR
                && this.parameters.magFilter !== this.gl.NEAREST
            ) {
                if(!this.renderer.production) {
                    throwWarning(this.type + ": Wrong magFilter value", this.parameters.magFilter, "for this texture:", this, "\ngl.LINEAR filtering will be used instead");
                }
                this.parameters.magFilter = this.gl.LINEAR;
            }

            this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.parameters.magFilter);
            this._state.magFilter = this.parameters.magFilter;
        }

        // anisotropy
        const anisotropyExt = this.renderer.extensions['EXT_texture_filter_anisotropic'];
        if(anisotropyExt && this.parameters.anisotropy !== this._state.anisotropy) {
            const max = this.gl.getParameter(anisotropyExt.MAX_TEXTURE_MAX_ANISOTROPY_EXT);
            this.parameters.anisotropy = Math.max(1, Math.min(this.parameters.anisotropy, max));

            this.gl.texParameterf(this.gl.TEXTURE_2D, anisotropyExt.TEXTURE_MAX_ANISOTROPY_EXT, this.parameters.anisotropy);
            this._state.anisotropy = this.parameters.anisotropy;
        }
    }
Updates per-textures parameters
     Wrapping, filters, anisotropy and mipmaps generation
     Usually called after uploading a texture to the GPU
*