当前位置: 首页 > Web前端 > HTML

WebGL压缩纹理实践

时间:2023-03-28 13:02:50 HTML

0x01本文将介绍压缩纹理在实际项目中的使用。最近的一个项目是这样的:因为项目涉及的楼很多,大概有40栋楼,每栋楼有10层,每层都有很多设备。这导致我们使用大量的纹理。在实际项目过程中,我们客户的电脑经常会遇到webgl崩溃的情况。这就需要我们想办法降低项目的纹理内存和内存占用。以下是公园和楼层的部分截图,数据已经脱敏:首先,我们可能会想到缩小图片尺寸。但是缩小图片尺寸是有一个限度的,因为如果图片尺寸太小,会影响我们最终的呈现效果。因此,我们需要想新的办法来减少对这种资源的占用。另一种思路是不使用generateMipmap。Mipmap生成金字塔图像结果。生成Mipmap会占用大约1/3的内存空间,所以不使用Mipmap会减少,大约1/3的内存空间。但是Mipmap是为了让模型在缩小的时候有很好的渲染效果。因此,如果不使用Mipmap,渲染质量会降低。最后我们使用压缩纹理。0x01压缩纹理介绍相信比较熟悉webgl的同学都知道压缩纹理。常用的纹理图片都是jpeg、png等图片格式。这些图片本来就是压缩图片。基于压缩算法,对文件进行压缩,减小文件体积,有利于大量图片在网络上的传输。但是,当使用jpegpng图像作为纹理时,它会首先转换为位图。这里所说的位图是指未经任何压缩算法的原始图像数据。以1024×1024为例,如果图像中每个像素需要三个RGB通道,每个通道需要8位空间,那么整幅图像需要用到1024×1024×8×3位的信息,也就是3M,这是所有3M信息都需要加载到GPU中,这与图像文件使用的压缩格式无关。如果图像中的每个像素都需要四个通道的rgba,那么就需要4兆字节的GPU显存空间。可以看出,使用jpeg、png等图片格式的缺点是图片需要解压,会消耗CPU性能。纹理数据占用更多内存。通常浏览器和GPU各自保存一份位图数据。压缩纹理似乎可以解决上述问题。通过使用压缩纹理,我们可以通过压缩算法将像素打包成数据块,这样可以减少显存中的存储容量。这个打包好的数据块非常方便GPU解压查询。所以从性能的角度来看,访问纹理的速度也得到了提升。压缩文件的格式有很多种,比如DDS、KTX等??,严格来说DDS、kTX是容器而不是格式,压缩贴图的格式有很多种。在这里,为了简单起见,我们指的是DDS和KTX格式。我们知道KTX有2.0版本。而我们最终选择了ktx2.0,可以方便的与gltf模型格式进行整合。关于压缩纹理的更多知识可以上网搜索,这里就不详细介绍了。0x02工作流建模工程师给的OBJ模型,项目一开始也是用的。首先,我们需要将OBJ模型转换成GLTF格式。可以使用插件obj2gltf完成转换。转换过程大致如下:npminstallobj2gltf-gobj2gltf-ia.obj-oa.gltf首先通过npm安装obj2gltf。然后通过obj2gltf转换模型,其中-i代表输入的OBJ模型。-o是输出gltf模型。转换为gltf后,压缩gltf。贴图压缩工具是一套开源的ktx工具,ktx-software,官方文档如下:https://github.com/KhronosGro...安装好ktx-software后,就可以对贴图进行压缩了,这里我们可以选择gltfpack(gltfpack比较简单,ktx-software也有自己的转换工具,比较复杂,但是转换的可选参数比较多,可以更灵活的选择高质量或者低质量的压缩贴图.有兴趣的读者可以查阅文献research)。压缩命令大致为:gltfpack-iscene.gltf-oscene.glb--tc其中tc是压缩贴图,原文如下:gltfpackcanalsocompresstexturesusingBasisUniversalformatstoredinaKTX2container(-tc标志,需要支持KHR_texture_basisu)。也可以使用-te标志将纹理嵌入到.bin/.glb输出中。0x03加载压缩纹理并将纹理更改为ktx2后,加载模型时需要解析纹理。以threejs为例,加载ktx2需要指定KTX2Loader,而KTX2Loader需要指定js文件“basis_transcoder”,所以需要指定basis_transcoder.js和basis_transcoder.wasm文件的路径,大致如下:让ktx2Loader=newKTX2Loader(manager).setTranscoderPath('./').detectSupport(renderder)gltfLoader.setKTX2Loader(ktx2Loader);gltfLoader指定ktx2loader后,可以像加载普通gltf模型一样加载ktx2纹理的模型。0x04压缩结果对比压缩后显存和webgl程序的内存占用都大大降低。整个场景的内存减少了50%左右,效果还是很明显的。当然,减少显存的方法还有很多,比如在建模过程中减少模型的面数、减小纹理的大小、禁用mipmaps、尽可能重复使用可重复使用的模型等等。结论本文介绍了一种减少视频内存、压缩纹理的方法。在压缩纹理和性能优化方面有更多的知识和技能点。如果您有好的经验,欢迎与我交流。关注公众号“ITMan表叔”添加作者微信进行交流,及时收到更多有价值的文章。