记一次 glTF 模型的绘制性能提升:从ppt到dove,丝滑感受
测试不易,机会难寻。转载请带连接:https://www.cnblogs.com/onsummer/p/13543826.html;全网@秋意正寒
转换思路
同样一个模型,分别取如下转换思路:
- 原始模型👉fbx👉gltf
- 原始模型👉obj👉gltf
但是我在打开中间格式fbx和obj时,发现这两者虽然顶点数量一致,三角形数量一致,但是使用 Windows 3D 查看器查看时,发现前者的绘图调用次数高达1600多次,而后者的绘图调用次数只有217次,效果是完全相同的。
遂打开gltf文件进行分析,对比gltf数据对象如下:
对比gltf对象 | fbx | obj |
---|---|---|
node数量 | 1600多+2500多 | 1 |
mesh数量 | 1600多 | 1 |
primitive总量(每个mesh的primitive数量和) | 1600多 | 217 |
特点 | 1个mesh存1个primitive,有2500多个node用于记录层级关系 | 用1个node包裹1个mesh,mesh下有217个primitive |
所以,故推断影响 gltf、3dtiles(b3dm格式)渲染性能的一个重要指标,就是 primitive 的数量,primitive 是 GL 库绘制图形的最小单元。
在上表中看到有2500多虚node其实是不直接引用 mesh 的,所以即使 node 的总数有 3700 多个,但是实际上只复现了 1600 多次 mesh,且由于 1个 mesh 只有 1个 primitive,所以绘制次数等于1600多次很正常。
要性能还是要逻辑?
这是一个很难取舍的话题,如果需要在 gltf 层面组织好属性数据、数据逻辑分层,那么要尽可能控制好 node 的树状结构,控制好负责引用mesh的node的数量,控制好 primitive 的总数,尽量把材质一样的 primitive 合并。
而如果要追求极致的性能,就不用太在意 node、mesh的组织,只要遇到材质一样的 primitive,合并就是,遇到相对坐标不一样,上转换矩阵算它。
空间换时间
三维渲染是一个极其昔时的话题,因为现在似乎磁盘容量是足够的——什么你跟我说文件大了下载慢?你搞辣么大的模型干啥?有大模型不会分拆吗吗吗吗
所以,很多时候要用空间换时间。
gltf 允许 1个mesh 由多个node 引用,那么这个 mesh 的绘制次数就会累加,虽然复用了mesh下辖的 primitive所指向的数据,不用存储多份mesh可以达到“只存一份数据重复绘制多次”的效果,但是这对性能毫无卵用,因为总的 primitive 数量还是上去了。
这个时候可以把需要重复的顶点根据 node 的坐标转换信息计算出来,重复塞到尽量少的primitive中去。
有人说你这样顶点数量上去了,文件体积也上去了:朋友,普通的750ti亮机卡绘制100w个点没什么压力的~,文件体积这个,就需要数据转换者自己权衡到底是重复mesh的引用,还是把重复的图形多存一份(位置不一样)塞到 primitive 中了。