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/KhronosGroup/KTX-Software#readme

安装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彪叔” 可以添加作者微信进行交流,及时收到更多有价值的文章。

WebGL压缩纹理实践的更多相关文章

  1. OpenGL ES 压缩纹理

    什么是压缩纹理 在实际应用特别是游戏中纹理占用了相当大的包体积,而且GPU无法直接解码目前流行的图片格式,图片必须转换为RGB等类型的格式才能上传到GPU内存,这显然增加了GPU内存的占用.为了处理这 ...

  2. Android 使用压缩纹理

    本文介绍了什么是压缩纹理,以及加载压缩纹理的核心步骤.并在 Android OpenGLES 平台上实现了压缩纹理的显示. 一.压缩纹理概念 传统的图片文件格式有 PNG . JPEG 等,这种类型的 ...

  3. [转]各种移动GPU压缩纹理的使用方法

    介绍了各种移动设备所使用的GPU,以及各个GPU所支持的压缩纹理的格式和使用方法.1. 移动GPU大全 目前移动市场的GPU主要有四大厂商系列:1)Imagination Technologies的P ...

  4. 腾讯技术分享:GIF动图技术详解及手机QQ动态表情压缩技术实践

    本文来自腾讯前端开发工程师“ wendygogogo”的技术分享,作者自评:“在Web前端摸爬滚打的码农一枚,对技术充满热情的菜鸟,致力为手Q的建设添砖加瓦.” 1.GIF格式的历史 GIF ( Gr ...

  5. Html5 中获取镜像图像 - 解决 WebGL 中纹理倒置问题

    Html5 中获取镜像图像 - 解决 WebGL 中纹理倒置问题 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致& ...

  6. OpenGL 加载DDS文件(压缩纹理)

    想必很多人都见过DDS这种文件,它是一个“图片文件”,如果你安装了某些看图软件,你可以直接双击打开它来进行预览. 那么,这种DDS文件和我们常见的TGA/PNG之类的文件有何不同呢? DDS和TGA/ ...

  7. 各种移动GPU压缩纹理的使用方法

    本文系原创整理,欢迎转载,请标明链接 http://www.cnblogs.com/luming1979 有问题欢迎加qq群讨论:366239605 介绍了各种移动设备所使用的GPU,以及各个GPU所 ...

  8. ASP.NET Core文件压缩最佳实践

    前言 在微软官方文档中,未明确指出文件压缩功能的使用误区. 本文将对 ASP.NET Core 文件响应压缩的常见使用误区做出说明. 误区1:未使用 Brotil 压缩 几乎不需要任何额外的代价,Br ...

  9. WebGL 与 WebGPU比对[6] - 纹理

    目录 1. WebGL 中的纹理 1.1. 创建二维纹理与设置采样参数 1.2. 纹理数据写入与拷贝 1.3. 着色器中的纹理 1.4. 纹理对象 vs 渲染缓冲对象 1.5. 立方体六面纹理 1.6 ...

  10. WebGL入门教程(五)-webgl纹理

    前面文章: WebGL入门教程(一)-初识webgl WebGL入门教程(二)-webgl绘制三角形 WebGL入门教程(三)-webgl动画 WebGL入门教程(四)-webgl颜色 这里就需要用到 ...

随机推荐

  1. 如何使用 JavaScript 获取当前页面帧率 FPS

    可以通过计算每秒 window.requestAnimationFrame 的调用频率来做为 FPS 值.它接收一个回调函数,该回调函数会在浏览器下一次重绘之前执行.所以只要我们循环调用并记录单位时间 ...

  2. go高并发之路——go语言如何解决并发问题

    一.选择GO的原因 作为一个后端开发,日常工作中接触最多的两门语言就是PHP和GO了.无可否认,PHP确实是最好的语言(手动狗头哈哈),写起来真的很舒爽,没有任何心智负担,字符串和整型压根就不用区分, ...

  3. go高并发之路——启航

    工作7年有余了,B端和C端业务都做过不少,打算整理分享一些自己在实际工作中所遇到的高并发的场景和解决方案,也是对自己本人职业生涯中的一些经验的总结和感悟.与其他博文略有不同的是,这些基本上都是自己实际 ...

  4. 京东二面:Sychronized的锁升级过程是怎样的

    引言 Java作为主流的面向对象编程语言,提供了丰富的并发工具来帮助开发者解决多线程环境下的数据一致性问题.其中,内置的关键字"Synchronized"扮演了至关重要的角色,它能 ...

  5. golang 切片原理面试题

    package main import "fmt" func main() { var s = make([]int, 0, 10) _ = append(s, 1,2,3) fm ...

  6. 关于Zotero组件在office word中的添加

    引言:学姐问我,怎么弄Zotero,在调试过程中遇到的问题及解决方案 Q&A Zotero的安装 找到官网(https://www.zotero.org/)点击download,安装(个人觉得 ...

  7. 微信小程序跳转重新加载目标页

    可用于在首次进入到小程序后就执行性了首页的onLoad方法,等你再去点击其它页面再回来的时候就不会加载onLoad了,比如你跳到登录页后再返回到首页会发现首页啥数据都没加载,所以你在登录那边进行跳转的 ...

  8. 快速生成树协议(RSTP)基本知识及实验(使用eNSP)

    关于生成树协议的知识可参考我的另一个博客:https://www.cnblogs.com/mrlayfolk/p/12242627.html 这篇博文主要介绍快速生成树协议(RSTP)的基本知识.-- ...

  9. react withRouter高阶组件

    作用:把不是通过路由切换过来的组件中,将react-router 的 history.location.match 三个对象传入props对象上 默认情况下必须是经过路由匹配渲染的组件才存在this. ...

  10. kettle从入门到精通 第四十八课 ETL之kettle webspoon

    1.kettle自带的客户端spoon工具是cs架构,多人协同办公起来不是特别方便.当然spoon也可以通过文件仓库设置为database模式进行协同办公.每个人在自己电脑上安装&打开spoo ...