1.1、延迟渲染(Deferred)
1)延迟渲染和前向渲染的区别:延迟渲染延迟了部分渲染,它拥有的信息总是并非总是和前向渲染一样。例如,到了最后光照渲染阶段,延迟渲染渲染光照时就不在拥有之前渲染几何体时所获得的所有信息。使用延迟渲染在一开始的时候性能会损失很多,但是随着各种功能的增多和混合,性能都会很稳定不会下降很多,这就是为啥很多手机游戏和应用都使用前向渲染,而很多高端游戏比如主机游戏如3A大作等一类的游戏倾向于使用延迟渲染。
2)延迟渲染的优势:可以获得更加稳定而又可预测的高质量效果,虚幻和Unity都是默认使用延迟渲染。
3)多重采样抗锯齿(MSAA)在延迟渲染时不能用,需要依赖临时抗锯齿(TAA)
1.2、前向渲染(Forward)
1)光照和着色不会延迟,它们会在几何体渲染时被同时完成,当在计算材质和阴影时,前向渲染可以获得更多信息,因为它们在同一个环节完成。
2)不擅长混合各种不同功能,擅长渲染半透明表面,在渲染简单应用时快很多,可以使用MASS。同样前向渲染适用VR应用。
1.3、在渲染之前的工作
如图1所示,在渲染之前的CPU和GPU的工作示意图。
只渲染可见的网格,主要是由CPU处理,但是GPU也会处理一部分。渲染之前会做如下工作:
1)距离剔除
在虚幻4中设置距离剔除
2)视锥体剔除
3)预计算可见性
4)遮挡剔除:模型最好还是分成细的部分不要整个模型,整个模型在遮挡的时候会一直渲染整个部分,如果模型是由各个小的部件拼接成的模型则会在遮挡处理是选择在摄像机画面内的部分进行渲染。
渲染都是按照模型逐个进行的,不会逐像素、像素块或线条渲染。
2.1、绘制调用(DrawCall)
1)先渲染环境,然后被遮挡的部分先预渲染。
DarwCall绘制调用就是渲染时采用的单一处理过程,通常可以理解为拥有相同属性的一组多边形。如图所示左边需要绘制五次,天空、地面时两个模型和三个圆
柱体,右边的需要六次绘制,因为右边的有两种材质,没一种新的材质都意味着一次新的绘制调用。绘制调用时影响性能的关键,会成为最大的性能损耗。
如图是UE4的渲染过程,如图所示为右边的渲染情况示意图。
2)两千到三千的绘制调用时比较合理的,游戏在超过一万次绘制调用的时候会有可能出现问题。绘制调用即完成了一次绘制之后需要询问CPU并等待下一次的任务。
3)当面数低于一定值(4000以下)后绘制调用是渲染时性能影响最大的因素,三角面的数量反而没有那么大的影响。
4)不同的静态网格体也会都需要单独一次绘制调用。在虚幻中无论是为一个物体添加组件还是该组件单独存在作为一个物体,绘制调用时一样的。
5)减少绘制调用的方法:
首先,将模型的局部坐标转换成世界坐标,然后,处理平滑过渡,最后,还能产生额外偏移。偏移能实现网格顶点的位置改变,如大量草地风吹的的效果,这些效果不可能使用动画来驱动,这样会消耗CPU的性能,但是在GPU中使用顶点着色器实现是一件非常简单的事情。顶点着色器只是将模型渲染到哪个位置,模型实际的位置GPU并不知道,也即它时间上是无法让模型位移,因此碰撞不会发生改变。
优化建议:场景中的树木使用顶点着色器实现了风吹的效果,但是在远处观看树的时候应该关闭掉世界坐标偏移也即顶点着色器实现的风吹效果。
1)如下图所示,要渲染图中三角形,就必须找出所有被三角形影响的像素网格,收到影响的网格将被着色,计算这个结果的数学过程被称为光栅化过程。光栅化按照绘制调用逐次进行。
注意:过度着色的问题,前向渲染会因为过度着色产生巨大的影响,简单理解就是模型网格重叠时候的像素反复着色。
2)G缓存,用于合成各种内容
3)深度缓冲:记录了每个像素和摄像机的距离
3.1、纹理贴图
1)纹理在导入的时候总是会被压缩,压缩方式有DXTC是“DirectX纹理压缩”的简称、BC是“块压缩”的简称。块压缩正如其名是通过生成像素块来压缩纹理。法线贴图使用的是一种特殊压缩设置,仅仅保留红色和绿色通道,然后需要执行一些额外计算。发现贴图通常用红、绿、蓝三个通道来确定不同的轴线如何对光照做出响应。实际上可以通过红和绿来算出蓝色的通道,因此移除了蓝色的通道。
2)多级渐进纹理:如果没有多级渐进纹理纹理的噪点会非常厉害。还因为需要处理纹理流送,纹理流送就是确定引擎在何时需要哪张纹理以及哪些多级渐进纹理的过程。因为,你不会希望导入所有可能需要的纹理这样会用光宽带和内存,让加载过程变得非常漫长。通常的做法都是根据物体所处的位置和摄像机的角度及时加载需要的纹理。因此,通常将多级渐进纹理贴图的边长设置为2的指数幂。如果问题边长不是2的幂,导入当然能够继续使用,但是不会使用多级渐进纹理。
3.2、像素着色器
像素着色器实现材质的整个过程,同时实现光照、雾、反射、后期处理、颜色校正等等。
1)虚幻4中的材质编辑器可以通过如下的方式查看HLSL代码,一个很简单的材质的HLSL代码很多,是因为虚幻引擎中的Shader代码都是使用了模板创建的,这也解释了为什么材质上有些会显示灰色不可用的状态。
2)材质管线的很大一部分都是基于物理的渲染(PBR)
实时反射很难实现,因为在某种程度上没出现一次反射都需要重新渲染整个场景,显然,考虑到性能和硬件能力有限,我们不可能这么做。必须使用某种障眼法来应对挑战,这个方法有如下几种
1)反射捕获:在一个特定位置捕获一张静态立方体贴图,这是预先计算出来的,结果是它非常快速,但是不太精准,并且只有局部效果。
2)平面反射:是动态的但是损耗很大;
3)屏幕空间反射(SSR),是唯一默认激活的反射,能反射所有对象,并且是实时反射。它很精准,但有点噪点,并且损耗很大,并且只能渲染出现在屏幕上二点内容。这是是三种方式中损耗最大的。
光照和反射一样很难在实时渲染中计算,它们非常复杂,需要占用大量硬件性能,并且计算速度很慢,因此会将光照的部分计算量分流到预计算或预渲染阶段,这就是所谓的静态光照。UE4中分静态光照和动态光照。
1)动态光照使用G缓存实现实时渲染
2)级联动态阴影:根据距离来渲染阴影,还会根据距离和贴图展示不同的分辨率;
3)几何体的面数会影响阴影的质量;
4)距离场阴影最适合与棱角分明的静态模型一起使用。
在虚幻中有两种类型的距离雾:大气雾和指数雾,还有一种雾是局部体积雾
1)什么是GBuffer?
A、用于存储所有纹理的缓冲区
B、几何体缓冲区
C、一组以不同方式渲染的场景图像,用于延迟渲染
2)分析GPU绑定的项目时有哪些方法可用(请选择2项)
A、识别负担繁重的蓝图,并将其迁移至C++
B、GPU性能分析工具
C、视口可视化工具
3)哪个渲染流程更适合提升性能?
A、正向渲染
B、延迟渲染
C、取决于游戏或项目所需的功能
4)哪个线程用于计算场景中的遮蔽?
A、GPU线程
B、绘制线程
C、游戏线程
5)哪个线程计算动画和处理逻辑?
A、GPU线程
B、绘制线程
C、游戏线程
6)在渲染的哪个步骤中在屏幕上对场景进行着色和绘制?
A、GPU线程
B、绘制线程
C、游戏线程
7)从性能角度而言,在场景中包含多个网格体或将这些网格体合并为单一网格体,哪一种做法更好?
A、正确,因为对象越小,全部同时渲染的可能性就越低。
B、错误,因为这样会增加绘制调用计数。
C、它取决于网格体的大小、其多边形计数、材质数量等。
8)为何控制场景中绘制调用数量对于性能而言如此重要?
A、绘制调用计数对于性能完全没有任何影响。
B、如果绘制调用过多,每次调用的开销就可能累积,从而对性能造成负面影响。
C、绘制调用过多可能带来分段故障的风险。
9)渲染场景时,网格体LOD如何帮助提升场景性能?
A、网格体LOD可减少绘制调用计数
B、网格体LOD可提高网格体质量
C、网格体LOD可减少远方网格体的多边形计数,同时保持近处的质量
10)您的场景具有一个大型湖泊,并且您希望在湖面上展现出尽可能最佳的天空反射效果。何种反射方法最适合用于实现此效果?
A、反射采集
B、平面反射
C、屏幕空间反射
11) 您正在为低端设备进行优化,但仍想要为室内实现精美的反射效果,该使用何种方法?
A、反射采集
B、平面反射
C、屏幕空间反射
12)以下哪两(2)个因素会影响静态光照的Lightmass烘焙时间?
A、光照强度和颜色
B、光源和衰减半径
C、环境中存在的人物/生物数量
D、光照贴图分辨率和烘焙设置
13)间接光照缓存(或体积光照贴图)有何用途?
A、对动态网格体给予光照
B、对地形给予光照
C、对静态网格体给予光照
14)建议采用何种方法来确定场景中对象的光照贴图分辨率?
A、尽可能选择最高的值,无论如何,该值上限即所需的分辨率。
B、按网格体为基础,对每个网格体进行试错,在每个步骤中间重新构建光照,直至满意为止。
C、根据网格体大小,靠近相机镜头、考虑内存约束并与其它网格体保持一致,选取不会对质量造成明显可见的牺牲的最低可行选项。
15)在以下哪两(2)种场景下会造成动态和CSM阴影方法开销增加?
A、具有较高多边形计数的场景
B、具有大量半透明表面的场景
C、在同一片区域存在大量投射阴影的光源
16)以下哪两(2)项解决方案可用于降低场景中透明度的开销?
A、使用着色器复杂性视图来查找开销巨大的像素。
B、将半透明网格体上的多边形数量减少到最小值
C、降低半透明材质的材质复杂性。