本节主要讲一下虚幻渲染之前,都发生了什么。
首先,虚幻的渲染由三个线程共同完成。分别是CPU线程,DRAW线程,和GPU线程。
这三个线程按照CPU->DRAW->GPU的顺序执行,请观察下图:
假如我们有4帧画面要渲染,分别是FrameA、FrameB、FrameC、FrameD。最下方是时间轴(以毫秒为单位)
为了将第一张画面(FrameA)呈现在我们面前,首先就是Cpu在0毫秒的时候处理FrameA,然后紧接着在第33毫秒Draw线程再对经过Cpu线程处理后的FrameA进行再处理(遮挡剔除,后面会讲),这时候Cpu线程在33毫秒处开始处理FrameB。之后在第66毫秒Gpu线程开始实际渲染FrameA。与此同时,Draw线程已经开始处理FrameB了,同时Cpu线程则已经开始处理FrameC。依此类推。。。
一个画面,经过三道工序处理,最终呈现到我们的面前,而这三道工序经过的时间是66ms。这就是cpu和gpu线程之间的线程同步。
在让渲染线程实际开始渲染画面的时候,我们需要对要渲染的对象进行一个筛选,一个游戏里的世界那么大,可我们玩家所看到的画面只是整个游戏世界中的某一个角度的画面,没必要将那些我们看不到的东西都渲染一遍。所以就要做遮挡处理,将不需要被渲染器渲染的东西,给移除之后,再进行渲染。
遮挡处理部分主要运行在Draw线程,前面说过,它决定了哪些对象最终会参与渲染。
虚幻主要有4种遮挡处理方案。分别是距离剔除,视锥剔除,预计算可见性和遮挡剔除。它们按照性能消耗从小到大的顺序依次执行。
遮挡处理完毕后,就可以把这些最终确认会参与渲染的对象传送给渲染线程进行渲染了。可是,为什么这四种剔除方案要按照性能消耗从小到大的顺序执行呢?
简单点描述就是:用廉价的人干最多的事儿,用最优质的人干最少的事儿。
复杂版本:我说过了,遮挡剔除是很耗费性能的一个过程。所以,假如你的场景中有10w个对象。先用距离剔除把远处的东西给去掉,好,10w个对象变成7w了,然后,利用视锥剔除,再从7w给砍到3w,然后再利用预计算可见性剔除,给看到7k。最后到了遮挡剔除这个步骤的时候,只需要问7k次“你可不可以被看到呀?”,而不是问10w次!
在虚幻4的控制台里,可以输入Freezerendering和Unfreezerendering来冻结和取消冻结当前渲染的画面。用人类的语言来描述就是,当你敲下这个命令的那一瞬间,除了你ue4编辑器当前视口能看到的东西,其他不参与当前这一帧渲染的物体都消失了,就这么简单。
Stat Initviews可以查看当前消耗,如果视图中显示超过10k个对象,就会有性能影响。
关于渲染性能优化这方面,重要的是找到一个平衡。模型大了,对Gpu不好(比如视锥剔除,看到一个非常大的地形边缘上的一根草,也会参与计算),模型多了,则对Cpu不好(要处理的对象变多了)