webgl纹理压缩实践

790 阅读2分钟

1.原因

    我们知道传统的图片文件格式有 PNG 、 JPEG 等,这种类型的图片格式无法直接被 GPU 读取,需要先经过 CPU 解码后再上传到 GPU 使用,解码后的数据无压缩。

    而纹理压缩顾名思义是一种压缩的纹理格式,它通常会将纹理划分为固定大小的块(block)或者瓦片(tile),每个块单独进行压缩,整体显存占用更低,并且能直接被 GPU 读取和渲染(无需 CPU 解码)。

2.项目技术方案

    本项目选择使用basis_universal压缩图片,生成.basis文件,使用ThreeJS中basisTextureLoader加载压缩后文件。

    已知basisTextureLoader加载.basis文件后,获取设备信息,将文件快速转换为适用于设备的压缩格式。如basisTextureLoader如下源码所示:

    var config = this.workerConfig;
    config.astcSupported = !! renderer.extensions.get( 'WEBGL_compressed_texture_astc' );
    config.etcSupported = !! renderer.extensions.get( 'WEBGL_compressed_texture_etc1' );
    config.dxtSupported = !! renderer.extensions.get( 'WEBGL_compressed_texture_s3tc' );
    config.pvrtcSupported = !! renderer.extensions.get( 'WEBGL_compressed_texture_pvrtc' )
    || !! renderer.extensions.get( 'WEBKIT_WEBGL_compressed_texture_pvrtc' );
    if ( config.astcSupported ) {
        config.format = BasisTextureLoader.BASIS_FORMAT.cTFASTC_4x4;
    } else if ( config.dxtSupported ) {
        config.format = BasisTextureLoader.BASIS_FORMAT.cTFBC3;
    } else if ( config.pvrtcSupported ) {
        config.format = BasisTextureLoader.BASIS_FORMAT.cTFPVRTC1_4_RGBA;
    } else if ( config.etcSupported ) {
        config.format = BasisTextureLoader.BASIS_FORMAT.cTFETC1;
    } else {
        throw new Error( 'THREE.BasisTextureLoader: No suitable compressed texture format found.' );
    }
    return this;
},

3.代码实现

    本项目使用BasisTextureLoader加载文件

    完整代码如下链接:

github.com/minicherry/…

    核心代码如下所示:

loader.setTranscoderPath( '../../public/lib/basis/' );
loader.detectSupport( renderer );
let a = new URL('../assets/textureCompression/9000.basis', import.meta.url)
loader.load( a, function ( texture ) {
    texture.encoding = THREE.sRGBEncoding;
    material.map = texture;
    material.needsUpdate = true;
}, undefined, function ( error ) {
    console.error( error );
} );

4.效果对比

    项目中选择了纯白图片进行压缩

4.1 显示效果对比

压缩前:

D56BB9FE-DDA3-445B-9B35-4A857A5AFD7C.png

压缩后:

9E53732C-7068-4676-8EB4-6BF756429A6E.png

4.2 图片压缩尺寸

0AE5CB20-CF41-4413-B0A2-CC1DFB6AAC4E.png     图片压缩前大小为262KB,压缩后大小为4KB

4.3 内存对比

压缩前:

932BAD80-2E1E-4387-9D13-0BF9C22F2D37.png 压缩后:

2715B064-3DFD-4119-A91B-BFD7D04561B1.png

    所以可以知道对于纯色图片,纹理压缩对于性能优化是有较好效果。

    对于其他项目和设备,还需要针对项目进行多端试验,本文旨在提供一个纹理优化的思路。

参考资料

isux.tencent.com/articles/is… 如何在页面极速渲染3D模型

github.com/BinomialLLC… 工具下载

wow.techbrood.com/fiddle/6319… 代码参考

zhuanlan.zhihu.com/p/154425898 webgl中大场景优化

zhuanlan.zhihu.com/p/486903217 图像块压缩/纹理压缩技术细节(文献翻译)

zhuanlan.zhihu.com/p/553445757 纹理压缩

docs.egret.com/engine/docs… ktx纹理压缩

www.jianshu.com/p/a4aec9f06… ktx转换工具的使用

www.jiazhengblog.com/blog/2017/0… webgl纹理详解-纹理压缩的使用

blog.csdn.net/Taobaojishu… 内存优化:纹理压缩技术

www.wenjiangs.com/doc/qmwhjzy… BasisTextureLoader使用

zhuanlan.zhihu.com/p/561894569 webgl压缩纹理实践