Как использовать compressTexSubImage2D с текстурой Threejs - PullRequest
0 голосов
/ 28 ноября 2018

Я пытаюсь создать TextureAtlas для Threejs, используя сжатую текстуру, но не могу найти способ получить правильный формат / внутренний формат

Я получаю ошибку: glCompressedTexSubImage2D: формат не соответствует внутреннему формату.

Я загружаю сжатую текстуру из THREE.KTXLoader и загружаю функцию обновления TextureAtlas с помощью mipmaps [0] .data, проанализированного из KTXLoader

Класс состоит из 3 частей:

  • конструктор: настройка базовой информации о текстуре
  • setRender (рендерер): настройка визуализации и утилит для будущего использования
  • setSize: настройка размера моей текстуры
  • обновление: обновить часть текстуры сжатой текстурой

Здесь полный класс:

class TextureAtlas extends THREE.Texture{
    constructor() {

        super()

        this.magFilter = THREE.LinearFilter;
        this.minFilter = THREE.LinearMipMapLinearFilter;
        const canvas = document.createElement('canvas');
        canvas.width = 1;
        canvas.height = 1;
        const ctx = canvas.getContext('2d');
        const imageData = ctx.createImageData(1, 1);            
        this.image = imageData
        this.generateMipmaps = false
        this.flipY = false
        // this.unpackAlignment = 1
        this.format = THREE.RGBAFormat
        this.needsUpdate = true
        this.isUpdatableTexture = true
    }

    setRenderer( renderer ) {
        this.renderer = renderer;
        this.gl = this.renderer.getContext()
        this.ct = this.gl.getExtension("WEBGL_compressed_texture_s3tc");
        this.utils = THREE.WebGLUtils(this.gl, this.renderer.extensions)
    }

    setSize( width, height ) {

        if( width === this.width && height === this.height ) return;
        if(!this.renderer){ return }
        var textureProperties = this.renderer.properties.get( this );
        if( !textureProperties.__webglTexture ) return;

        this.width = width;
        this.height = height;

        var activeTexture = this.gl.getParameter( this.gl.TEXTURE_BINDING_2D );
        this.gl.bindTexture( this.gl.TEXTURE_2D, textureProperties.__webglTexture );
        if( !textureProperties.__webglTexture ) this.width = null;

        this.gl.texImage2D(
            this.gl.TEXTURE_2D,
            0,
            this.utils.convert( this.format ),
            width,
            height,
            0,
            this.utils.convert( this.format ),
            this.utils.convert( this.type ),
            null
        );
        this.gl.bindTexture( this.gl.TEXTURE_2D, activeTexture );
        this.needsUpdate = true
    }

    update = ( pixels, x, y, width, height,format )=> {
        // return
        var textureProperties = this.renderer.properties.get( this );
        if( !textureProperties.__webglTexture ) { return}

        var activeTexture = this.gl.getParameter( this.gl.TEXTURE_BINDING_2D );
        this.gl.bindTexture( this.gl.TEXTURE_2D, textureProperties.__webglTexture );

        // WebGL 1 & 2:
        // https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/compressedTexSubImage2D
        // void gl.compressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, ArrayBufferView? pixels);
        this.gl.compressedTexSubImage2D(
            this.gl.TEXTURE_2D,                                         // texture 2d 3d or cubemap
            0,                                                                          // level of details
            0,//x,                                                                          // left offset
            0,//y,                                                                          // top offset
            width,                                                                  // texture width
            height,                                                                 // texture height
            this.utils.convert(this.ct.COMPRESSED_RGBA_S3TC_DXT5_EXT), // format of the compressed texture
            pixels                                                                  // ArrayBufferView
        );
        this.gl.generateMipmap( this.gl.TEXTURE_2D );
        this.gl.bindTexture( this.gl.TEXTURE_2D, activeTexture );
        this.needsUpdate = true
    }
}
...