【游戏技术群】959392658  【游戏出海群】12067810
yzc88亚洲城 手机端
  • 开发者工具开发者工具
  • www.yzc88.comManual
  • 蛮牛杯蛮牛杯
  • Unity官方专区Unity官方专区
开发者专栏

关注:2422

当前位置:yzc88亚洲城 技术专区 开发者专栏

__________________________________________________________________________________
开发者干货区版块规则:

  1、文章必须是图文形式。(至少2幅图)
      2、文章字数必须保持在1500字节以上。(编辑器右下角有字数检查)
      3、本版块只支持在yzc88亚洲城原创首发,不支持转载。
      4、本版块回复不得无意义,如:顶、呵呵、不错......【真的会扣分的哦】
      5、......
__________________________________________________________________________________
查看: 3880|回复: 28
发新帖

[士郎] 在Unity里写一个纯手动的渲染管线(二)

[复制链接]  [移动端链接]
排名
1
昨日变化

7318

主题

7860

帖子

3万

积分

Rank: 16

UID
1231
好友
185
蛮牛币
8818
威望
30
注册时间
2013-7-29
在线时间
3742 小时
最后登录
2019-2-22

社区QQ达人活力之星原创精华达人突出贡献奖财富之证yzc88亚洲城QQ群会员蛮牛妹VIP

跳转到指定楼层
楼主
yzc88亚洲城 2018-9-26 11:00:43 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册帐号

x



上一章中(在Unity里写一个纯手动的渲染管线(一)),我们已经成功用最基础的API手撸出了整个管线的基本顺序,然而,这套管线很显然并不健全,我们今天尝试在其中加入一些性能和效果上的提升。注意,本章内容将会非常硬核,虽然我们尽量避免在图形学文章中加入大量程序框架的东西,但是显然这是没法避免的了。


我们即将实现多线程的剔除,多线程的并行排序。但是在此之前,我们首先需要在管线中加入一个看起来像那么回事的间接光,这里我就用了一个官方的案例和BRDF Reflection,加入了一个读取天空盒的mipmap的反射,虽然看起来依旧粗糙,但是感觉上已经够用了。MaxwellGengYF/Unity-Custom-Rendering-Pipline我们即将实现多线程的剔除,多线程的并行排序。但是在此之前,我们首先需要在管线中加入一个看起来像那么回事的间接光,这里我就用了一个官方的案例和BRDF Reflection,加入了一个读取天空盒的mipmap的反射,虽然看起来依旧粗糙,但是感觉上已经够用了。



在搭建管线之前,我们首先应该思考的是程序的框架问题,OOP?亦或是面向数据的架构如ECS?一条渲染管线,是有并行而很可能没大有什么异步需求的,在这种情况下,我们可以使用单例模式来搭建管线,让每个单例负责管线的一部分,各个单例先后顺序鲜明。



整个渲染的流程大致可以分为剔除->将剔除结果输入待排序的列表中->排序操作->按照排序结果依次drawcall,当然这其中还需要合批,只不过合批的事我们准备放在之后的优化章节中讲解。



Unity的Job System因其完成度低饱受诟病,然而笔者惊奇的发现,Job System用来作为静态单例的多线程工具,是非常好用的,那么我们就可以用Job System来实现这些多线程的操作,按照官方的解释,Job System中已经有了处理上下文,并行缓存等专门针对并发型运算的优化,而我们自己写的多线程调用器在很大概率上性能则不如官方的高。




我们首先创建一个负责剔除的类,这里提供的几个变量都是剔除必需的数据,其中renderObject是每个绘制物体的component,这里为了编辑更快就暂时写一个MonoBehaviour的类挂上去。6个Plane则是摄像机前后左右上下的视锥面,我们将使用bounding box进行视锥剔除,camera pos和cameraFarClipDistance则是为了计算物体与当前摄像机的距离,进而为之后的排序做数据上的准备。



首先呢,我们需要写一个静态的方法,这个方法的功能就是计算视锥体剔除,这个是图形学基础,不再过多赘述,值得一提的是,SRP里直接使用了一个抽象的CullingResult代替了这一系列繁杂的操作。代码大致如下:





这个方法简单粗暴的遍历了所有的面,然后和每个面进行碰撞比对,当确保Bounding Box在所有的面之前的时候,就可以确定这个方块是应该被绘制的,计算结束后应该将需要被绘制的物体,储存到排序的队列中:


这里的Execute是Job System提供的interface的方法,这里我们首先传入数据并进行剔除计算,当剔除的结果为true时,计算物体到摄像机的距离,然后使距离/远裁面,获得物体当前所处的距离层,然后按照这个层的值将其放到排序队列中。之所以要引入“距离层”这个概念,单纯是为了之后的并行化排序做准备,比如远裁面是1000米,我们就可以分成20个层,即每50米是一个层,而Unity将启动20个jobs来完成这20个数组的排序,这是一种非常暴力的用内存换取性能的方法,不过在内存已经十分富足的PC或主机端,这样的内存消耗还是可以接受的。



当然,实现一个排序方法还是非常必要的,为了尽可能的简单,我们这里用一个简单粗暴的二叉树前序遍历来进行排序,时间复杂度是O(nLogn),考虑到已经做了并行操作,这个操作应该不会造成明显的性能影响,排序的模板方法如下:





具体的方法实现属于基础的数据结构内容,有兴趣的朋友可以在开源中查看,这里不再赘述,值得一提的是,因为Add操作是多线程的,因此十分需要线程安全,我们就需要在Add中添加线程安全的保护:





将offset和resize操作统统保护起来,防止出现Bug
有了这个排序脚本,我们就可以进行排序操作了,首先,指定一个分层常量LAYERCOUNT,也就是说之后所有的物体都应该根据距离被准确而均匀的分配到这些层中,随后,通过调用Sort函数,完成排序操作,并调用GetSorted函数,完成二叉树的后序遍历,这样在主线程中就不需要再去执行对缓存不友好的二叉树遍历了:





这一系列该有的操作都有了,我们就可以开始编写主控脚本了,与上次没有太大的不同,只不过这次我们在控制脚本中加入了单例的初始化和每帧的数据更新:



游戏开始时的初始化

计算每帧的投影矩阵,并按照投影矩阵运算视锥裁面,以及清空上一帧遗留的二叉树排序的痕迹,随后将新的任务“提上日程”,使用Job System的调用开始在分线程中完成剔除和排序:



最后,快乐的完成绘制,注意,因为管线完成度低,我们并没有实现不同材质的SetPassCall和合批操作,这个会在之后的章节中慢慢讲解:






到这里时,我们可以认为所有的工作已经完成,接下来我们来测试一下看看结果如何,(初始的drawcall有Clear,Deferred Lighting和Skybox这三个):



当屏幕中只有1个球时,dc只多了1个


结果看起来没什么问题


在这一步结束以后,这个程序就可以真正的称之为渲染管线了,因为只使用了底层基础的API,所以开发起来还是相当麻烦的,但是通过这样的流程,希望读者可以更充分的了解,管线是应该如何工作,以及日后进行自己的管线定制时,如何绕开“坑”,实现更高效的渲染管线。


知乎@MaxwellGeng


[发帖际遇]: 一个袋子砸在了 清风 头上,清风 赚了 1 蛮牛币. 幸运榜 / 衰神榜

跟我念“站长妹纸萌萌哒!”我说站长,你说YO!爱你们么么哒~
3偶尔光临
254/300
排名
10731
昨日变化
5

2

主题

61

帖子

254

积分

Rank: 3Rank: 3Rank: 3

UID
70411
好友
0
蛮牛币
299
威望
0
注册时间
2015-1-22
在线时间
93 小时
最后登录
2019-2-22
沙发
yzc88亚洲城 2018-9-26 20:15:40 | 只看该作者
mark!!!!!!!!!!!!!!!!!

4四处流浪
472/500
排名
5740
昨日变化
3

0

主题

50

帖子

472

积分

Rank: 4

UID
159995
好友
0
蛮牛币
504
威望
0
注册时间
2016-8-1
在线时间
180 小时
最后登录
2019-2-21
板凳
yzc88亚洲城 2018-9-26 21:03:57 | 只看该作者
大神,很厉害
[发帖际遇]: 一个袋子砸在了 与光同尘 头上,与光同尘 赚了 1 蛮牛币. 幸运榜 / 衰神榜

6蛮牛粉丝
1456/1500
排名
3659
昨日变化
4

0

主题

856

帖子

1456

积分

Rank: 6Rank: 6Rank: 6

UID
210390
好友
0
蛮牛币
1766
威望
0
注册时间
2017-3-7
在线时间
194 小时
最后登录
2019-2-18
地板
yzc88亚洲城 2018-9-27 10:35:07 | 只看该作者

排名
47756
昨日变化
24

0

主题

5

帖子

18

积分

Rank: 1

UID
280530
好友
0
蛮牛币
12
威望
0
注册时间
2018-5-9
在线时间
9 小时
最后登录
2018-11-21
5#
yzc88亚洲城 2018-9-28 17:54:22 | 只看该作者
大神一般啊,受用了

5熟悉之中
684/1000
排名
14098
昨日变化
3

1

主题

98

帖子

684

积分

Rank: 5Rank: 5

UID
1944
好友
3
蛮牛币
1273
威望
0
注册时间
2013-8-13
在线时间
527 小时
最后登录
2019-2-15
6#
yzc88亚洲城 2018-9-30 16:41:53 | 只看该作者
非原创能不能加个原链接?

3偶尔光临
271/300
排名
8933
昨日变化
2

4

主题

67

帖子

271

积分

Rank: 3Rank: 3Rank: 3

UID
280448
好友
0
蛮牛币
407
威望
0
注册时间
2018-5-8
在线时间
70 小时
最后登录
2019-1-5
7#
yzc88亚洲城 2018-10-7 21:27:57 | 只看该作者
膜拜大神

7日久生情
1553/5000
排名
2133
昨日变化
5

5

主题

471

帖子

1553

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
54335
好友
2
蛮牛币
5419
威望
0
注册时间
2014-11-9
在线时间
429 小时
最后登录
2019-2-23
8#
yzc88亚洲城 2018-10-8 14:23:47 | 只看该作者
[发帖际遇]: 一个袋子砸在了 梦的方向 头上,梦的方向 赚了 1 蛮牛币. 幸运榜 / 衰神榜

7日久生情
2880/5000
排名
2485
昨日变化

2

主题

1851

帖子

2880

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
241666
好友
0
蛮牛币
10773
威望
0
注册时间
2017-9-6
在线时间
453 小时
最后登录
2019-1-31
9#
yzc88亚洲城 2018-10-9 04:17:07 | 只看该作者
感谢分享

3偶尔光临
172/300
排名
10731
昨日变化
5

0

主题

17

帖子

172

积分

Rank: 3Rank: 3Rank: 3

UID
232458
好友
0
蛮牛币
354
威望
0
注册时间
2017-7-16
在线时间
61 小时
最后登录
2019-2-13
10#
yzc88亚洲城 2018-10-10 10:26:27 | 只看该作者
感谢分享,留足回看
[发帖际遇]: 西木叔叔 在网吧通宵,花了 2 蛮牛币. 幸运榜 / 衰神榜

2初来乍到
130/150
排名
15176
昨日变化
3

1

主题

49

帖子

130

积分

Rank: 2Rank: 2

UID
294308
好友
0
蛮牛币
42
威望
0
注册时间
2018-8-22
在线时间
30 小时
最后登录
2019-1-16
11#
yzc88亚洲城 2018-10-10 19:59:47 | 只看该作者
大佬啊~~

4四处流浪
301/500
排名
8504
昨日变化
70

0

主题

77

帖子

301

积分

Rank: 4

UID
181921
好友
0
蛮牛币
360
威望
0
注册时间
2016-11-8
在线时间
82 小时
最后登录
2019-2-21
12#
yzc88亚洲城 2018-10-18 09:23:10 | 只看该作者
bangbangbangbangbangbang

排名
19810
昨日变化
3

0

主题

25

帖子

92

积分

Rank: 2Rank: 2

UID
275047
好友
0
蛮牛币
142
威望
0
注册时间
2018-3-31
在线时间
39 小时
最后登录
2019-2-15
13#
yzc88亚洲城 2018-10-30 14:14:49 | 只看该作者
谢谢楼主 有时间一定好好学学

3偶尔光临
185/300
排名
19810
昨日变化
3

0

主题

104

帖子

185

积分

Rank: 3Rank: 3Rank: 3

UID
28854
好友
0
蛮牛币
15
威望
0
注册时间
2014-6-9
在线时间
53 小时
最后登录
2018-12-22
14#
yzc88亚洲城 2018-11-6 23:22:19 | 只看该作者
太好了,非常的喜欢啊,非常的好啊,

3偶尔光临
240/300
排名
12375
昨日变化
2

0

主题

89

帖子

240

积分

Rank: 3Rank: 3Rank: 3

UID
269725
好友
0
蛮牛币
329
威望
0
注册时间
2018-2-27
在线时间
77 小时
最后登录
2019-2-23
15#
yzc88亚洲城 2018-11-12 15:15:04 | 只看该作者
感谢楼主分享

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

快速回复 返回顶部 返回列表