基于Shader的动态合批


前言

    关于unity动态合批,一直被人诟病的是他的使用条件太过苛刻,上限900左右个顶点数,只能用来合批一些小物件。

    毕竟在Update上面每帧计算900个顶点数据,对Cpu是一个不小的消耗,所以我们不妨设想一些,如果我们把顶点的运算放到GPU上面,我们是不是就可以无视顶点上限的问题了。

    其实我最近一直在做关于性能优化的事情,关于合批上面的事情也做了很多,发现其实很多情况下,静态合批的情况下,也需要做一些运动等,但是unity自带的动态合批可用性实在是小的可怜,在各方面的问题下,我们依然还是决定自己做一个条件更少,适用性更广泛的合批。来优化我们项目的一些功能。

效果

    话不多说,先看一下测试场景对比效果。



Shader合批前后的 Batches和对比




支持运动,运动前后的帧率对比

对比

  相比于unity,他是把定点的运算都放到了cpu的update里面,每帧去更新顶点的位置,因为对cpu的消耗十分巨大,所以顶点的最大数量始终在900左右。但是cpu对于大量的计算能力,始终不如GPU,所以我们要做的就是把顶点的计算都放到GPU里面,这样对于CPU的消耗几乎为零。所以基于Gpu的,顶点的数量可以说是 没有限制的,但是也不能大于uint32最大值(也就是10亿左右)。

  下面就是一些基于Shader的动态合批的一些基本原理。

mesh合批实现原理

  对于合批的具体实现其实并不难,无疑是吧mesh的顶点,三角形数据,顶点光线等数据统一合并到一个大mesh中,这些可以自行百度了解。

  但是实际项目中我们可能同时合并很多个mesh,这是大量的mesh顶点数据需要在主线程中,会出现严重的掉帧现象,所以我们需要把顶点,三角形数据,顶点光线的计算放到子线程中,这里肯定会有很多小伙伴会问,不是unity的资源不能在子线程中访问嘛。

  所以我们需要分两步进行操作,首先在主线程把顶点,三角形数据,顶点光线等数据都收集数组中,第二步,然后把这些数组统一在子线程里面计算,如下图


此图是在子线程中进行数据运算的过程。

    到这里,算是完成了合批的这一部分,这时候会有小伙伴问道,这个shader好像并没有什么关系,只是把mesh的运算放到了子线程了而已, 哼哼,下面关于顶点的运动就必须放到shader里面去了。

基于shader 的顶点运算

      unity动态合批之所以顶点数量要求在900之内的原因,是因为把顶点的运算全都放到Cpu里面了。如果我们把顶点的运算放到Gpu 里面,那个对顶点数量的的要求将会彻底解除。

      呢么我们改如何去吧顶点的计算放入GPU呢,下面是两个猜想。

    设想1.  我们把通过ComputeShader,每帧将mesh的顶点,法线,传入GPU中,在GPU中计算过之后,在通过ComputeShader传过来。之后把数据重新赋给mesh。这样就可以实现他的运动了。缺点是每帧需要占用大量的宽带。并且需要三次数据的传递。

      设想2. 我们不改变mesh,只改变图形在屏幕中的显示。我们在合批mesh的时候,向顶点传入对应物体的序号,合批完成之后,我们只需要每一帧把改变物体的坐标矩阵传给shader中,呢么就可以实现物体的显示变换。每帧只需要传送每个子物体的矩阵即可,并且不需要CPU和GPU之间来回传递。

毫无疑问,无论是哪一方面,第二种都要比第一种要好一些。

        既然是基于shader的,所以我们必须要专门为合批写一个 shader,CombShader里面的一些代码如下


这里需要借鉴 骨骼动画的原理(原理类似),记录顶点的对应的bound。在GPU中找到bound对应的矩阵进行矩阵变换,就可以得到mesh在世界空间的坐标。



将子物体对应的transfrom传给GPU


      把子物体的mesh数据都合并到父对象上面,只留下子物体对应的transform组件来记录更新矩阵数据。这样一来就是对animation动画的完美契合。并不需要把animation数据重新生成一份矩阵数据到本地。只需要每帧把需要改变的子物体矩阵传到GPU即可。

    通过上面两步就可以实现Shader的模拟运动。

最终效果




最终效果

  可以看到,原本800多个物体,全都合在两个mesh中了,Batchs从870+减到了17左右,顶点数在40万左右的数量,因为是shader的图形在动,所以动画动起来也对帧率几乎是没有影响。

使用条件

1.作为合批,避免不了的是,合批的对象使用的材质必须是一样的。(贴图可以不一样)

2.顶点数不能超过uint32最大值。

3.贴图的读写权限要开启。

结束

    这个功能还是输入刚开始阶段,还存在一些问题,就比如在Update每帧要遍历子节点获取物体位置矩阵,增加了GC的频率。所以运动的时候偶尔会出现掉帧的现象。有兴趣的小伙伴可以研究一下怎么样更加高效的数据传递。

      功能有不足之处或者有问题可以加我哦:2364823151

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,001评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,210评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,874评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,001评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,022评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,005评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,929评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,742评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,193评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,427评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,583评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,305评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,911评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,564评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,731评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,581评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,478评论 2 352

推荐阅读更多精彩内容