车展作为车市的风向标,代表着汽车发展的趋势,也是厂商展示自己、推广自己的舞台。WebGL 作为一种新兴的技术,为 Web 端提供了交互式三维动画新体验,汽车之家的网上车展就是两者结合之后的一种新的产品形态。
到目前为止,汽车之家车展总共经历了五年的风雨发展,历经三大阶段,它们分别是全景实拍车展、步进式全景实拍车展和纯 3D 虚拟车展。
全景实拍车展:线下车展现场实拍全景图,以此为主要素材构建而成的线上车展。
步进式全景实拍车展:使用专业设备实地拍摄线下车展全景图,同时采集空间信息,实现全景场景的平滑切换,就像镜头在行走,这也是步进式这个名称在之家的由来。
纯 3D 虚拟车展:在 Web 端实现了展馆和汽车模型的加载展示,真正实现了第一人称逛展看车,源于现实而又超越现实,保证性能的同时尽可能的呈现高质量视觉效。
每一次的车展迭代更新都对业务有的极大的推进,而这背后都是 WebGL 技术不断成熟和生态的不断完整所造就的。
一、WebGL 介绍
1.1 WebGL 引擎现状
WebGL 是近些年出现的一种 3D 绘图协议,这种绘图技术通过增加 OpenGL ES 2.0 的一个 JavaScript 绑定,为 HTML5 Canvas 提供硬件 3D 加速渲染,这样 Web 开发人员就可以借助系统显卡来在浏览器里运行 3D 应用。随着移动互联网的崛起和发展,Web 业务也随之拓展,有时需要在网页/ H5 /小程序中渲染 3D 模型,WebGL 就有了用武之地。
WebGL 引擎使用 JavaScript 语言编程,学习成本低,容易入门,发布部署方便灵活且无需安装下载,但国内没有比较成熟的 WebGL 开发者生态,可使用的插件很少;因为是基于 Web 浏览器生态,可以非常方便的以外链方式对外进行社区裂变传播,同时引擎能力满足简单的 3D 需求,常见的 WebGL 引擎有 three.js、BabylonJS 和 PlayCanvas 等,它们都是最近几年才出现,积累相对于传统的虚幻(UE)或者 Unity 引擎要少很多。
1.2 WebGL 的优点
跨平台:WebGL 是 H5 标准之一,具有统一的、标准的、跨平台的 OpenGL 接口实现,通过 JavaScript 脚本实现了 Web 端的 3D 应用制作,无需任何浏览器插件支持,是浏览器级别的一次开发多处应用;
易传播:WebGL 基于 Web 浏览器生态,基于它开发的应用可以像普通网页一样非常方便的以外链方式对外进行社区裂变传播;
入门难度低:如上所述,WebGL 的开发语言是 JavaScript,上手速度快,发布部署方便灵活且无需安装下载;
1.3 WebGL 的缺点
图形绘制接口实现不完整:WebGL 的只实现了部分 OpenGL 函数,许多优秀的特性难以被使用;
设备性能较低:主要应用场景是移动端的浏览器,而移动设备的硬件性能较 PC 机普遍偏低,浏览器本身对资源分配也有限制,这使得复杂场景以及特效无法得到有效的使用,影响视觉体验。
资源加载耗时长:大部分 WebGL 应用需要在文件服务器获取必需的模型资源,在 4G 环境下这个加载过程往往需要十几秒到几分钟的时间,这对于一个 Web 端的应用是不可忍受的。
1.4 小结
随着 WebGL 的不断发展,Web 端的 3D 应用效果也有明显的提升,但是与传统 3D 应用程序相比, WebGL 即具有自身独特的优势,也存在有明显的不足,以汽车之家网上车展为例,为了使自己的应用有更好的呈现,我们必须克服加载时间长,内容呈现相对单一简单的缺点,解决这些问题的途径分别是几何数据压缩和纹理压缩。
二、几何数据压缩
2.1 几何数据定义
那什么是几何数据呢?要解释几何数据就要从模型的表示方法开始介绍,目前三维物体的三角形表示是经典的表示形式,在这种表示法中,物体用三角形小平面组成网格来表示。三角形表示法在计算机图形学中是普遍存在的,造成这种现象的原因有两个:创建三角形物体是很容易的,无论多么复杂的物体,我们总能够不断地重复构建三角形去完成物体的表示;三角形表示法在对物体明暗处理的时候有着巨大的优势。
物体拓扑结构表示
采用三角形网格表示法最大的困难是模型的精确度,即三角面与物体实际表面的差别,高质量的模型往往需要对物体表面进行更多层次的细分,同时伴随着大量的三角形产生,不幸的是这些数据都是需要进行实时传输到客户端的,一般来说 Web 端一台仅表示外观的 3D 车模型需要十兆左右的几何数据,仅仅传输这些数据就需要十秒(实测 4G 带宽)左右的时间,而传统的 Web 页面的完全展示时间绝大部分情况下不会超过一秒,这种情况会造成用户在进入 3D 应用时的大量流失。
上图是一个简单地 obj 模型文件的内容,它表示了一个由十个三角形组成的网格结构,因为三角形之间有重复顶点,所以顶点总共有十四个,而不是三十个。其中:v 表示几何体顶点、vt 表示贴图坐标点、vn 表示顶点法线、f 表示三角形。所以几何数据本质上就是构建模型的最基础的点、线、面数据,几何数据的压缩就是对数值顶点坐标精度和物体表面网格的压缩。
2.2 顶点数值精度压缩
通常情况下三角形的顶点坐标是由浮点型数表示,如果我们使用一个短整型数对其进行近似表示,那么由于浮点数占用四个字节,短整型数只占用两个字节,这样我们将能够节约一半的存储空间,不仅顶点坐标数据可以进行这种近似表示,其他依赖于顶点的数据,如 UV 值、颜色值、法线等也都可以用这种方式进行压缩处理,当然在实际应用中不会这么简单的处理,不同的模型往往需要不同的压缩精度。
2.3 物体表面网格压缩
参考本文之前提到的 obj 模型的表示方式,该表面网格需要存储十四个顶点,考虑到顶点复用节约存储空间,每一个三角形只需要指定三个顶点的序号,而不是为每个三角形都指定三个顶点的坐标,尽管如此,每个三角形仍然需要存储三个短整型数据,即每个顶点需要至少 16 个比特位存储。
2.4 EdgeBreaker 算法
EdgeBreaker 是一种用于压缩三角形网格的算法,能够将网格中的三角形输出为一组拓扑符,能够有效地减少存储体积,它的基本过程是将构成每一个表面的三角形用拓扑的方式进行表示,再按照一定的规则对表面三角形进行遍历,同时产出拓扑符,最终将生成的拓扑符列表进行霍夫曼编码输出。
首先,我们需要了解下这些拓扑符的定义,表面中的每一个三角形都用一种拓扑符号表示,经过统计这些拓扑关系总共有五种,每个拓扑符都对应一个唯一的编码,X 表示当前的三角形,箭头表示三角形起始边,v 表示三角形的另一个顶点,C、L、E、R、S 分别表示不同情况下的拓扑关系,如下图所示:
基本拓扑关系
知道了这些拓扑关系,我们就可以对一个表面进行遍历输出了,这个过程可以描述为以下过程:
任选任一三角形的任一条边,作为起始边;
输出当前边的拓扑符;
逆时针选取接下一个未被输出的三角形,作为当前三角形;
如果当前三角形存在,指定当前三角形未被遍历到的顶点的对边为起始边,转到步骤 2;
如果当前三角形不存在,并且当前三角形不是起始三角形,则输出拓扑符,指定上一三角形为当前三角形,转到步骤 3;如果当前三角形是起始三角形,退出,遍历结束。
通过以上步骤就可以对一个表面进行编码输出,以下图的表面为例,我们选定左下角的三角形为起始三角形,它的底部的边为起始边,按照上述遍历过程,沿着红色箭头进行编码输出,第一次和第二次回退后的遍历路径分别用绿色和黑色箭头表示,最终我们就得到了这个表面的所有三角形的编码输出序列:CCRRRSLCRSERRELCRRRCRRRE。
每个拓扑符最多由 3 个比特位进行表示,相比较之前每个顶点 16 个比特位,可将三角形的顶点序号存储空间压缩到原来的 18.75%,在实际应用中,例如 3D 车模型的外观部分,每个表面的三角形数量通常都会高于几万,对其进行霍夫曼编码后,甚至能够将存储空间压缩到原来的 10%。
表面遍历过程
2.5 几何数据压缩工具
Draco 是谷歌提供的开源工具,其核心的实现过程就是顶点数据压缩和物体表面网格压缩,它不仅能够对网格数据进行压缩,还提供了点云数据的压缩方法,也增加了对顶点数据精度压缩过程中指定比特位的配置,最后附上官方提供的压缩统计数据:
Draco 与 Zip 文件压缩情况
但是 Draco 也存在不足之处,截止到 1.35 版本,它只支持 obj 模型文件和 ply 点云文件作为输入,对于双 UV 和顶点具有颜色的情况是不能处理的,而且这个压缩过程过于强调压缩效率,压缩后经常会引起模型破面和贴图异常的情况,并且我们还需要在 C 端自行实现对 Draco 压缩文件的解压操作,这涉及大量的 CPU 运算,往往会引起卡顿的情况出现。
三、纹理压缩
3.1 纹理定义
纹理是什么呢?纹理是每个物体表面上的样子,譬如说木头上的木纹、大理石的纹路、汽车的车漆等,所以它是用来表达物体表面的显示细节,这些细节包括表面颜色、阴影、光照信息设置,甚至其它与显示无关的数据也可以纳入纹理的范畴。
比较常见的图片文件格式,例如 JPG、PNG、BMP 等并不能被 GPU 直接识别,所以它们都不是纹理格式文件,纹理格式是能够被 GPU 所识别的像素格式,能够被寻址采样。常见的简单的纹理格式有 R8G8B8A8、R4G4B4A4 、R8G8B8、R5G6B5、R5G5B5A1。
3.2 纹理压缩的必要性
受限于移动设备硬件和 WebGL 对 OpenGL 的图形绘制接口实现不完整,WebGL 应用不得不大量使用烘焙好的纹理贴图来提升整体效果,然而系统分配给浏览器的显存空间有限,尤其是 IOS 设备,通常在 100 兆至 200 兆左右的时候会出现显存空间不足,导致整个应用崩溃 。
另外,Web 端常用的 PNG/JPG 格式纹理图片需要 CPU 进行解压缩,像素之间存在依赖关系,无法实现单个像素的解析,因此发挥不了显卡的并发能力,而且这种解压缩操作本身就是对 CPU 资源的浪费。所以,无论是为了提高能够使用的纹理贴图数量,还是为了提高性能,都需要对纹理贴图进行压缩处理。
3.3 纹理压缩原理和现状
纹理压缩的本质是使用更少的存储空间去表达更多的色彩信息,不同的 GPU 所支持的纹理格式也并不全然相同,所以就导致目前纹理压缩比较混乱的现状,下图简要介绍了 DXT1 格式的工作原理:
DXT 格式工作原理
常用的纹理压缩格式有 DXT 系列、ETC 系列和 PVRTC 系列等,他们都可以将显存占用空间压缩到原来的 1/4 以下,增加了应用中可以配置的内容,也不需要 CPU 解压就能被 GPU 直接采样,可以减少内存和带宽的占用,提升了运行效率,但是这些压缩格式也有一个致命的缺点:在不同设备支持的压缩格式并不相同,特别是 Android 系统中的差异化更明显,甚至在同一个设备不同的浏览器支持的压缩格式也会存在差异。
3.4 Basis 格式
为了解决不同设备上纹理压缩格式不统一的问题,Basis 格式应运而生,它是一种开源的通用贴图格式,旨在提供一种更小存储尺寸,更快解码的方案,非常适合 WebGL 应用,在保持显存高压缩率的同时,解决了常用压缩格式低效率以及无法跨平台的问题。
贴图格式存储空间占用
Basis 纹理显存占用
从上两图可以看出,Basis 通用贴图格式的显存占用是 JPEG 的六分之一到八分之一,其存储的大小只是 JPEG 的一半。不过目前浏览器中并没有加入 Basis 通用贴图的转码器, WebGL API 以及 WebGPU API 并不能高效地跨平台读取压缩贴图,我们不得不为应用额外实现 Basis 的解码操作,这在一定程度上也增加了应用的负担。
四、写在最后
技术总是单一的,业务却是复杂的,本文核心围绕汽车之家网上车展在优化加载时长和丰富场景内容展开,介绍了模型压缩和纹理压缩两种技术,在一定程度上缓解了加载时长过长和 Web3D 应用内容不够丰富的现状,不可否认,Web 端的 3D 应用无论在画质和生态仍然无法达到传统的 3D 应用的水平,但是, WebGL 确实是能够为用户提供 3D 体验的最快捷的方式。
引用资料:
[1] A.V. Aho, J.E. Hopcroft, and J.D. Ullman, The Design and Analysis of Computer Algorithms, Addison-Wesley, Reading, MA, 1974.
[2]Jarek Rossignac, Edgebreaker: Connectivity compression for triangle meshes, GVU Center, Georgia Institute of Technology , 1999
[3] http://events.jianshu.io/p/a0d7eed9f44d
[4] https://github.com/BinomialLLC/basis_universal
[5] https://github.com/google/draco
评论