0x01
本文将讲述压缩纹理在理论我的项目中的应用的案例。最近的一个我的项目是这样的:我的项目因为波及到的建筑物特地多,大略有近40栋的修建,而每一栋建筑物,又有10层楼,每层楼外面又有很多的设施。这就导致咱们须要应用到大量的贴图。在理论的我的项目过程中,咱们的客户的电脑会常常遇到webgl解体的状况。这就须要咱们想方法来缩小该我的项目下贴图显存和内存的占用。
上面是园区和楼层的局部截图,数据已脱敏:
首先咱们可能会想到的是缩小图片的尺寸。然而缩小图片尺寸也是有限度的,因为图片尺寸太小的话,会影响咱们最终的出现成果。因而咱们就须要想新的方法来缩小这种资源的占用。
另外一种思路就是 不应用generateMipmap。 Mipmap会生成金字塔式的图片后果。生成Mipmap会多占有大略1/3的内存空间,因而不应用Mipmap会缩小啊,大略1/3的内存空间。然而Mipmap是为了模型在放大的时候可能有很好的出现成果,因而不应用Mipmap呢,就会导致出现品质的降落。
最终咱们应用压缩纹理。
0x01 压缩纹理简介
置信对于webgl比拟相熟的同学都晓得压缩纹理。
咱们罕用的的纹理图片,都是jpeg,png等图片格式。 这些图片本事是压缩的图片,基于压缩算法,对于文件进行了压缩,减小了文件的大小,这对于网络上的大量的图片的传输是无利的。
不过jpeg png的图片在作为贴图应用的时候,首先会转换成位图,这里所说的位图是指没有应用任何压缩算法的原始图片数据。以1024×1024为例,如果图像中每个像素须要RGB三个通道,每个通道须要8位空间,那么整张图片就须要应用1024 x 1024 x 8 x 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模型,首先咱们须要把OBJ模型转换成GLTF格局。 能够应用插件obj2gltf进行转换。转换的流程大抵如下:
npm install obj2gltf -gobj2gltf -i a.obj -o a.gltf
首先通过npm装置obj2gltf。而后通过obj2gltf 进行模型的转换,其中 -i示意输出的OBJ模型。-o就是输入的gltf模型。
转换为gltf之后,通过对gltf进行压缩。其中贴图压缩的工具为一套开源的ktx工具,ktx-software,官网文档如下:
https://github.com/KhronosGro...
装置ktx-software之后,能够对贴图进行压缩,此处咱们能够抉择gltfpack(gltfpack绝对比较简单,ktx-software也自带转换工具,比较复杂,然而转换的可选参数更多,可能更灵便的抉择高质量还是低质量压缩纹理,有趣味读者能够查看文档钻研)。
压缩的命令大抵:
gltfpack -i scene.gltf -o scene.glb --tc
其中tc是对贴图进行压缩,原文如下:gltfpack can also compress textures using Basis Universal format stored in a KTX2 container (-tc
flag, requires support forKHR_texture_basisu
). Textures can also be embedded into.bin
/.glb
output using-te
flag.
0x03加载压缩贴图
贴图改成ktx2之后,在加载模型的时候须要对贴图进行解析,以threejs为例,加载ktx2须要指定KTX2Loader,KTX2Loader须要指定js文件“basis_transcoder”,所以须要指定basis_transcoder.js和basis_transcoder.wasm文件的门路,大抵如下所示:
let ktx2Loader = new KTX2Loader(manager) .setTranscoderPath('./') .detectSupport(renderder)gltfLoader.setKTX2Loader(ktx2Loader);
gltfLoader指定ktx2loader之后,就能够像加载一般gltf模型一样,加载带ktx2贴图的模型。
0x04 压缩后果比照
压缩之后,webgl程序的显存和内存占用都大幅度的升高。 整个场景的内存降落大略50%左右,成果还是很显著的。
当然升高显存,还有许多更多的伎俩,比方建模过程中升高模型的面数,减小贴图的尺寸,禁用mipmap,能复用的模型尽量复用等等。
结语
本文讲述了升高显存的一种伎俩,压缩纹理。 压缩纹理和性能优化还有更多的常识技能点,如果你有好的教训,也欢送和我交换。关注公号“ITMan彪叔” 能够增加作者微信进行交换,及时收到更多有价值的文章。