关于前端:WebGL压缩纹理实践

38次阅读

共计 2374 个字符,预计需要花费 6 分钟才能阅读完成。

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 等图片格式的毛病是:

  1. 图片须要解压,这会耗费 CPU 的性能。
  2. 纹理数据占用内存较多。通常是浏览器和 GPU 各自保留一份位图数据。

压缩纹理正是为了解决上述的问题而呈现的。通过应用压缩纹理,咱们能够把像素通过压缩算法,包装成数据块,这能够缩小在显存中的存储容量。这种包装好的数据块又很不便 GPU 进行解压,查问。所以从性能的角度来说也进步了拜访纹理的速度。

压缩文里有很多格局,比方 DDS,KTX 等。严格来说,DDS 和 kTX 是一种容器而不是格局,而压缩纹理的格局是有多种。此处为了简便起见,咱们就说成 DDS 和 KTX 格局,咱们晓得 KTX 有 2.0 的版本。而咱们最终选用的也就是 ktx2.0,它可能很不便的和 gltf 模型格局进行集成。

无关压缩纹理的更多常识,大家能够在网上搜寻啊,此处不进行具体的介绍。

0x02 工作流

建模工程师给的是 OBJ 模型,我的项目最开始用的也是 OBJ 模型,首先咱们须要把 OBJ 模型转换成 GLTF 格局。能够应用插件 obj2gltf 进行转换。转换的流程大抵如下:

npm install obj2gltf -g
obj2gltf -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 for KHR_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 彪叔”能够增加作者微信进行交换,及时收到更多有价值的文章。

正文完
 0