七匣子logo

热搜:青云志阴阳师诛仙手游天堂2血盟九阴真经3D

您当前的位置: 手机游戏 >  角色扮演 >  手游新闻  >  如何把WebGL显存占用减少84.2%

如何把WebGL显存占用减少84.2%

http://www.7xz.com/news/     作者:SilvaReta    2017-07-07 14:59:22

转载自腾讯GAD:http://www.gad.qq.com/article/detail/28913
 
H5游戏端的性能优化包括几个方向:物理内存,帧耗时,GPU内存(显存)等等。这些指标占用越低,游戏运行就越流畅,现在就讲讲空间宠物spine动画的显存优化,另外我也会把中间遇到的每个知识点都深入解释清楚,当做福利送给大家

上一篇介绍完一系列优化方案,包括物理内存(拆分动作json文件),帧耗时(canvas2D渲染时独立背景部分到dom节点上),GPU内存(及时销毁内存)等等方案之后游戏也能流畅稳定的运行在上千万的用户手机端了。不过作为前端开发,必须折腾不止,将游戏更好地呈现给用户,占用用户更少的资源,用有限的资源干更多的事情!现在讲讲我们的GPU内存优化三十六计

第一章——想法诞生:显存优化三十六计之开源节流

每个机器的显存大小都是有限,想做字面意思上的开源并不是我们webview应用层能干的事情,不过可以换种思路,就是申请新的显存的时候,看看旧的显存是不是可以释放而减少剩余显存的申请,让总体占用的显存维持在一个比较低而稳定的数值,而不是递增。上一篇我们已经简单做了一些措施,为什么说简单,我觉得还远远不够,得继续深入研究。现在就讲讲我们对于节流的研究:

节流:游戏中跟GPU相关的概念是texture(纹理),也就是图片。要想节流就必须最大限度的减少图片的尺寸。

第二章——深入分析:显存优化三十六计之知己知彼

分析了一下空间模型里面的页面(打包的时候会把所有的图片生成一张大的雪碧图,这里统一就叫页面)发现有大面积的透明区域,主要是:
 
1
 
一、2的幂数的影响:因为是三端共用的模型,客户端用的是cocos2d游戏引擎,他们需要图片必须是2的幂数,这就造成为了凑足1024,2048这样的尺寸导致透明区域很多,约占40%

解释下:

2的幂数是为了迎合一项技术:mipmap(为了加快渲染速度和减少图像锯齿,贴图被处理成由一系列被预先计算和优化过的图片组成的文件),在WebGL读取纹理之前,设置了需要mipmap处理,WebGL代码为:

gl.generateMipmap(gl.TEXTURE_2D)

 就会先把图片按2的倍数逐渐缩小7张图片,并且缓存起来,如下图:

2
 
      从而在图片与视点距离切换的时候,webgl能最快地给到该物体与眼睛的距离下,跟已经缓存的8张图片中大小最接近的图片(都已经缓存啦,肯定快,而且都是2的幂数,等比缩放,也没有变形锯齿),对于怎么寻找最接近的图片也是有一套算法的,这里就不展开了。这样分析下来,mipmap优缺点就显而易见了:

缺点:会占用内存,因为mipmap会根据摄像机远近不同而生成对应的七个贴图,所以必然占内存!

优点:会优化显存带宽,用来减少渲染,因为可以根据实际情况,会选择适合的贴图来渲染,距离摄像机越远,显示的贴图像素越低,反之,像素越高!


为了视角发生变化的时候更加流畅(跑酷类游戏中人物跳跃,奔跑的时候都会有一些放大缩小,来表达距离的远近,从而2d也能有些3d的效果)
 
3
 
有些引擎,特别是3d引擎,他,mipmap是必选项,如果是非2幂的图片,会先强行拉伸转化成2的幂数,这就造成变形,这样肯定不行!

大多数时候,适合你的才是最好的。先分析下我们游戏的现状

1.游戏比较特殊,目前交互简单,纯2d展示,并没有距离的变化,生成这么多mipmap内存占用确实有点浪费

2.H5选择的spine引擎并不强制使用2的幂数,它会识别图片的尺寸,如果是非2幂的就不mipmap了

  if(texture.isPowerOfTwo)
        {
            if(texture.mipmap)
            {
                glTexture.enableMipmap();
            }
       }


 有这样2点基本条件,就可以关掉2的幂数的勾选了,减少了很大一部分原始页面的透明区域以及生成mipmap会多出来的7份缓存。

二、装扮类的图片,因为最初的模型都是没有装扮的,所以原始页面这部分全部都是透明的。约占60%

脑洞大开:装扮类别的既然都是空白的,就不需要打包在原始页面(大雪碧图)里,由前端自己生成这个图片。声明同等大小的空白canvas来做装扮类的图片。60%的空白全部缩减。现在就有两个问题:

1.如何把原始大页面中的装扮类透明区域去掉

2.如何在图集(.atlas)中带上装扮类的尺寸,好让前端页面能够用一个canvas代替

小结:较少纹理的尺寸在于减少纹理中的透明区域,2的幂数以及装扮图片是造成透明区域的源头。而非2的幂数可以不使用mipmap,也进一步较少了GPU内存的占用

第三章——实现:显存优化三十六计之借力打力

为了避免重复造轮子,肯定先找有没有现成的工具把一张图片中的透明区域抠掉。后面想到spine编辑器的导出工具是否支持这样的功能。

在此之前先详细介绍一下spine编辑器导出的参数介绍,和官网雷同的地方就不赘述了。这里只讲经常要用到的导出json和打包图集(可单独打包图集的哦,参数设置和导出json时候是同一套)

1.导出json的参数,较为简单
 
4
 
非必要的数据:勾选时, JSON 将包含那些渲染骨架所不必需的额外数据,使得文件略大。不过 JSON 导回 Spine 时需要此类数据。试了一下500多KB的json文件能少10KB左右

优质打印:导出的时候会格式化json格式,会有很多空格和换行,如果在外网读取的话还是不要勾选这个选项,可以减少文件大小

2.图集打包器参数(可单独使用)
 
5
 
去除x/y轴空白区,为了减少导出的页面尺寸,每张图片在页面的尺寸会比实际尺寸要小,图片的四边的空白区域会被裁剪,可以通过orig,size,offset这三个值还原实际图片。勾选这个值竟然就可以去掉页面中所有的空白区域,大小都会变成1*1,问题一搞定

skin_back
  rotate: false
  xy: 410, 2
  size: 1, 1
  orig: 1, 1
  offset: 0, 0
  index: -1


其余参数的说明见文章最后

总结一下,我们可以通过SPINE编辑器的导出工具来实现扣去页面上所有的透明区域,那接下来就剩怎么利用这张被阉割的页面去正常的展示和换装了。

这样导出的图集直接可以正常的展示,换装就有问题,换装的含义就是替换同名附件的图片纹理,其中有两类换装方式:
 
6
 
(1)图片类型的附件换装,直接就可以换,使用的是引擎自带的换装接口

(2)mesh类型的附件:因为需要绑定顶点和三角形区域,再绘制纹理。自带的换装接口无用。最优的方案是先用一个透明的canvas占位,绑定好顶点和三角区域之后,换装则是把新图片画到以前的canvas上,再update一下这个纹理即可,流程如下:

a.读取atlas => b.生成该装扮图片一样大小(数据缺失)的canvas => c.生成前端模型 => d.换装是把装扮图片drawImage到canvas上 => e.update纹理

整个流程分析下来需要mesh类型附件图片的大小参数,这个就可以通过自己写的工具从完整的图集数据里面读取出来,生成如下的一份图集配置
 
skin_body.png
size: 460,420
format: RGBA8888
filter: Linear,Linear
repeat: none
skin_body
  rotate: false
  xy: 0, 0
  size: 460,420
  orig: 460,420
  offset: 0, 0
  index: -1


 注:a.第一行必须是空格  b.size要设置成装扮图片的大小。

工具地址:http://meteor.cm.com/pet-tool/model-zip/package.html
 
7
 
第四章——优化结果

眼见为实,下面是在chrome上的测试结果:

实验条件:初始显存一样,分别加载优化前的模型数据和优化后的模型数据,对比GPU内存增量

实验数据:初始显存 :42265K

实验结果:

(1)优化前的模型,显存增量:58199 - 42265 = 15934KB
 
8
 
(2)优化后的模型,显存增量:44739 - 42265 = 2474KB
 
9
 
实验结论:一只模型占用的显存从15.9MB下降到2.5MB,下降了84.2%

经过理性的分析,GPU内存是肯定有显著的下降的因为:

(1)透明区域没有了,图片尺寸减小了很多。纹理申请的GPU内存计算方式是:内存大小=宽*高*4+...  宽高减少了之后内存就会下降

(2)非2的幂数不会启用mipmap,不需要预缓存的7张不同尺寸的纹理,减少了GPU内存占用。
 
-------------------------------------------分割线,接上面导出参数介绍部分------------------------------------------
 
 10
 
 
旋转:导出的时候图片可以90度旋转,从而打包工具可以计算得出最佳的雪碧图排版方式,生成的页面最小,引擎一般都是支持rotate属性的

别名:像素相同的只打包一次,也可以减少一定的透明区域,但是不够彻底

忽略空白图片:透明图和其附件都会被忽略,不在图集文件里面显示,这个比较危险,不建议勾选

页面类(就是通俗意义上的雪碧图)

最大宽/高度:限制了之后,可能会生成多张页面,引擎也是支持的哈

2的幂数:刚刚分析篇就已经介绍了,mipmap的需要,有些客户端引擎必须要勾选这个属性,不然纹理会变形,而且如果模型有距离变化的时候最好勾选上。否则不勾选可以节约内存,但必须要引擎支持

区域填充(重要)

填充X/Y/边缘:填充到图片和图片之间的px值和边缘的空白px值,不添加一些空白区域的话,渲染的时候可能会出现这样的问题:
 
11
 
预乘alpha:合成的效能更高,实现正确的透明效果,减少锯齿的出现,这里需要注意的是需要渲染引擎也需要支持这种格式,不然会显示成这样:会有黑边

12
 
运行时:

包裹X/Y:ClampToEdge,Repeat,MirrorRepeat三种模型,pixi规定在用Repeat,MirrorRepeat这两种模式需要先支持mipmap。这个概念有点像css的repeat属性。clamptoedge相当于no-repeat。具体示例图如下:
 
-----------------------------------------------------------------------------------------------------------------------------------
参考文档:
http://www.cnblogs.com/MrZivChu/p/mipmap.html
http://zh.esotericsoftware.com/spine-texture-packer
http://www.cppblog.com/wc250en007/archive/2011/08/06/152653.html

七匣子声明:七匣子登载此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述。

推荐礼包 换一换
  • 斗战狂神

    斗战狂神媒体礼包

    三倍经验药水*1;经验灵珠(60级)*1;百年佳酿*2

    剩余98%
    领取礼包
  • 西游记之大圣归来

    西游记之大圣归来特权礼包

    精炼石*15,扫荡卷*20,元宝*150,铜币*80000

    剩余88%
    领取礼包
  • 泰利的魔法旅途

    泰利的魔法旅途豪华礼包

    2级宝石*5,强化石*20

    剩余94%
    领取礼包
手游新闻相关资讯
手游新闻相关攻略
扫描关注公众号
七匣子公众号

七匣子公众号

七匣子新浪微博

七匣子新浪微博

大家都在玩
每周一星
手游礼包助手

手游礼包助手

类型:平台

大小:14MB

手游礼包助手,是全新的手游礼包、礼包码、首充券发放中心、发卡中心,为您提供全面的手游福利,是您贴心的礼包助手;手游礼包助手内,每天上线多款新手礼包、 珍贵礼包等手游礼包准时奉上、源源不断,完全匹配您的需要!敬请关注!
立即下载
扫描下载手游礼包助手
查看礼包助手
ChinaJoy正能量
电竞热点 More+
和道杯京津冀高校电竞大赛总决赛燃爆白沟 和道杯京津冀高校电竞大赛总决赛燃爆白沟
综艺娱乐 More+
《爸爸去哪儿5》主题曲MV,真的很好听 《开心俱乐部》第九期花絮:叶祖新试戏
美女图库 More+
少年西游记唯美静态电影“长相思”简介 2017ChinaJoy玩友时代展台甜美showgirl吸睛无数
手游排行榜