UE4实时渲染基础及深入探究

本文详细介绍了UE4实时渲染的基础与深入探究,包括目标帧率、帧时间、性能问题,以及延迟渲染与前向渲染的区别。文章还探讨了渲染流程中的遮挡处理、几何结构、着色器、光照、反射、静态与动态光照、阴影、雾和透明度等关键环节,并提供了性能优化建议。通过对各种渲染技术的讲解,帮助读者深入理解实时渲染的复杂性和性能考量。
摘要由CSDN通过智能技术生成

实时渲染基础:link
实时渲染深入探究:link


实时渲染基础

实时渲染是一个混合了多种不同解决方案的复杂过程,从本质上可以将其看作两个阶段:预计算阶段和具体的实时渲染阶段。

要了解会影响实时渲染性能的因素,首先需要清楚以下的基础概念:

实时渲染基础

目标帧率与毫秒

与目标帧率相关的一个重要概念是ms(毫秒),它代表渲染一帧所用的时间,数值越低则帧率越高。如30FPS对应的ms即为1000/30 = 33.33毫秒,60FPS对应的ms即为1000/60 = 16.67毫秒。在引擎的各种性能工具显示中都以ms为标准。

在评估性能时,应去掉引擎限制的帧率上限。可以用以下控制台命令来解除限制。

t.MaxFPS 600

另外,通过GPU Visualizer工具(快捷键Ctrl+Shift+,)可以查看渲染中的哪些过程耗费了大量的时间。


帧时间与GPU/CPU

使用stat unit命令时,主要关注Game和GPU这两个的渲染时长,效率最低的一方会决定游戏的性能。

在这里插入图片描述

从上图可以看出,CPU(Game)处理的主要是逻辑和变换方面的计算,而GPU处理的主要是渲染方面的计算,二者并行(后文有详解)。

stat rhistat enginestat scenerendering等命令可以看到更细致的性能数据。


最常见的四大性能问题

  • 半透明
    半透明物体由于要进行多层像素的叠加绘制,会导致较大开销。当半透明物体在屏幕空间上占比越大时,消耗也越大。

  • 绘制调用(Draw Call)
    Draw Calls绘制调用是实时引擎的渲染方式,它是逐对象渲染而非逐面渲染,所以如果场景中网格体数量很多,即使单个网格体面数很低,渲染消耗依旧很大,相比于场景中只有一个面数极高的网格体渲染要慢很多。同时,单个对象上材质数量越多,draw calls也越多。

  • 动态阴影
    要注意性能开销大的是动态阴影而非动态光照,当开启动态阴影时,保持场景中对象数量不变,增加每个网格体的面数,帧率会大幅下降,这是因为网格体的多边形数量会影响阴影的计算,所以动态光照下模型面数也是影响性能的一大因素。(当使用静态光照时面数并不会影响性能)

  • 像素/顶点着色器
    引擎要依赖像素着色器完成几乎所有的渲染工作,不光材质,包括光照、反射和雾等都由像素着色器驱动。输出分辨率越高,材质越复杂,性能影响就越大。






实时渲染深入探究

首先了解一下实时渲染的整体流程:

在这里插入图片描述

在这里插入图片描述
注意上述步骤并不是完全依次执行的,有些会同步执行,如步骤3、4、5、6。

另外要记住,实时渲染性能最好的时候是当场景里什么都没有的时候。所以,实时渲染流程的本质是管理性能的损耗。(RTR = Real Time Rendering)

在这里插入图片描述
有获得必有牺牲,功能Features、品质Quality、性能Performance三者不可兼得。所以制定严格的资源和内容规范(如模型面数、贴图尺寸)就成为了很重要的一件事,因为可以提前预估将会产生的性能损耗。


延迟渲染与前向渲染

延迟渲染的特点:

在这里插入图片描述

前向渲染的特点:

在这里插入图片描述
从游戏角度看:
前向渲染适合制作简单的手游或VR游戏,且能够提供更好的效果,但当功能和场景越来越复杂时,每加入一些新资源都会导致性能大幅下降。

延迟渲染则更适合制作一些复杂的大型游戏,虽然一开始性能就会低一截,但再继续添加内容时,性能基本保持稳定,不会下降很多。






渲染之前和遮挡


CPU和GPU工作流

上文提到,CPU和GPU是并行工作,下面就详细解释一下:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

由图可知,CPU和GPU会顺序对每一帧的画面进行处理,但二者之间会存在一定的时间差。

  • 首先CPU进行计算,计算内容包括所有逻辑和变换,因为知道一切对象所在的位置是渲染对象的前提;
  • 然后CPU和部分GPU会计算遮挡过程,剔除所有不可见对象,将所有可见对象记录在一个列表中。剔除方法包括距离剔除、视锥剔除、预计算可视性、遮挡剔除。这四种剔除方式性能消耗依次增大,引擎会优先使用消耗低的剔除方式来节约性能;
    (注:预计算可视性需要在世界设置中勾选Precompute Visibility,并使用PrecomputeVisibilityVolume,它是通过构建光照将场景划分为许多个立方体空间,在每一个立方体内根据玩家或摄像机的位置,记录哪些Actor可见而哪些不可见,即把Actor位置的可视性状态存储在场景中)

在这里插入图片描述

  • GPU开始实际的渲染过程

补充:遮挡剔除属于硬件剔除,部分移动端设备无法支持,则可以通过模型LOD实现软件剔除,对应模型属性中的LOD For Occluder Mesh,此功能并不常用。

遮挡相关性能提升须知

在这里插入图片描述

  1. 始终开启距离剔除(用CullDistanceVolume),例如当制作一个大楼的室内场景时,视线距离本身受限,此时是否用距离剔除虽然看不出差别,但如果不用,引擎就会使用其他消耗更高的剔除方式如遮挡剔除,产生不可见的性能损耗。
  2. 当场景中的对象数量超过1-1.5万时,基本就会开始对性能造成可见的损耗(与计算机硬件性能有关),达到3-6万个对象时,则性能损耗会很明显。因为无论此时屏幕空间中有多少可见对象,只要是有那么多的对象存在于场景中,引擎就会耗费性能去计算是否要剔除这些对象,所以这个计算过程就将对性能产生影响。用stat initviews命令可以看到这些开销。
  3. 上述消耗主要在CPU上,也有部分在GPU上。
  4. 大型开放场景无法很好地遮挡,因为很容易看到所有对象。
  5. 几乎任何可见对象都能被遮挡,包括粒子(通过Bounding Box计算遮挡)。
  6. 大型模型很少会被遮挡,因此会增加GPU的损耗。
  7. 将小模型合并起来变为大模型虽然会降低CPU的损耗,因为减少了引擎计算是否遮挡的次数,但是一旦屏幕空间中出现合并后模型的哪怕一个像素,这一整个模型都会被渲染。


以上是预计算阶段,下面将开始真正的实时渲染阶段




几何结构渲染

在正式渲染几何体之前,还要处理另外一个问题,即模型的渲染顺序。


前期Z通道

在这里插入图片描述
因为渲染是按模型逐个进行的,而非逐像素或逐线条渲染,所以当模型产生重叠的时候,会渲染大量冗余的像素。而解决方法则是依靠一个前期的深度Z通道进行测试。用很少量的信息去预先渲染环境,预先渲染几何体,知道每一个对象占画面的具体像素位置,由此来得到一个遮罩信息,其余被挡在后面的模型就根本不会渲染这块区域了。


绘制调用Drawcalls

在这里插入图片描述

  • 一组共享相同属性的多边形(即一个对象)称作为一个drawcall。
  • 一个对象有几种材质就会有几个drawcalls。
  • 蓝图中每个静态网格体组件都要算作一个drawcall。
  • 开启灯光也会增加drawcalls以及三角面。
  • drawcall会成为最大的性能损耗,所以数量必须合理,2000-3000较为合理。
  • stat rhi命令中的DrawPrimitiveCalls就是Drawcalls。

在这里插入图片描述


下面是一个简单场景的drawcall绘制流程,总共分了6步,即6个drawcalls。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值