UE4实时渲染——几何结构渲染二

本文详细介绍了UE4中绘制调用drawcall的影响,通过RenderDoc工具可视化分析场景渲染过程。讨论了模块化网格体与一整块网格体的工作流方式,以及各自的优缺点。提出了模块化网格体作为平衡方案,以减少工作量、优化性能。此外,还讲解了实例化静态网格体渲染和细节层次LOD技术,用于提高渲染效率,尤其是在大规模场景中的应用。
摘要由CSDN通过智能技术生成

上一节:UE4实时渲染——几何结构渲染一

上一节我们探讨了绘制调用drawcall的概述,以及对性能的影响。

绘制调用drawcall的可视化

现在让我们看一下绘制调用drawcall在场景中可视化展现出来。
使用RenderDoc插件,开启使用后,貌似要重启一下UE4才可以使用,这样做好,这里会多出一个小按钮。
在这里插入图片描述
点击按钮后,会将当前场景捕捉到RenderDoc中,通常要5-10秒的等待时间,然后出现这样的画面,这是一个可以免费下载的程序:
在这里插入图片描述
中间是编辑器输出的帧画面,你可以输出多个帧画面,然后双击帧画面,就会出现许多关于该帧画面的标签页,
如果点击“渲染管线状态(Pipeline States)”,我们可以看到各个着色器经历的步骤。
在这里插入图片描述
左侧的区域,列出了所有的渲染内容,展开场景,就得到了按顺序排列的渲染过程:
在这里插入图片描述
当我们点击预通道prepass,这是首先完成的环节:
在这里插入图片描述
我们目前处于基础通道BasePass:
基础通道属于主要环节,负责渲染几何体,
打开这个基础通道环节,里面包含了3个步骤,其中采用了2种静态遮挡,还使用了动态遮挡,
在这里插入图片描述
而且第二组静态遮挡里相比而言,包含了最多的模型,这些模型就是我们在这一帧中能看到的所有内容,虽然看起来是按照名称排序,实际上是按照材质排序的(因为多数使用相同材质的模型名称会类似),这个列表中,每一个都是一次绘制调用drawcall,一步一步的你会看到逐对象渲染,所以这个过程将会很慢,
在这里插入图片描述
你可以点击这个时钟按钮,来看绘制调用的耗时,
在这里插入图片描述
这个耗时是根据渲染当时的硬件情况,以及调度使用情况,来计算的,所以就算是同一帧,相同的对象,渲染耗时也是可能有偏差的。但我们还是可以有个大致的了解,比如中间的雕像损耗性能最大。
在这里插入图片描述
其他步骤这里暂时不深究。
--------------------------------------分割------------------------------------------

两种工作流方式及其优缺点

需要注意的是:
1、蓝图中的每个静态网格体,仍然需要一次绘制调用,组件也是逐个进行遮挡和渲染的。
2、如果想减少绘制调用drawcall,最好使用少量的大模型,而非大量的小模型。但大模型使用也要适量,大模型使用太多,也会导致一些问题,比如a、遮挡会变得复杂;b、光照贴图lightmapping会变得复杂;c、碰撞检测也会变得复杂;d、对于内存来说负担也更重

你有两种工作流方式:
1、模块化方式创建场景(类似搭乐高)
在这里插入图片描述
2、一整块网格体
在这里插入图片描述
两种方式区别对比:
1、对于“一整块网格体”这种方式而言,对之前提到过的四种剔除方式之一的“遮挡剔除”很不友好,但凡有一个像素点出现在画面里,这整块网格体都将渲染出来,即使它出现在背后。
2、“一整块网格体”这种方式,对于光照贴图lightingmapping更加糟糕,光照贴图会在后面讲述。
3、还有对碰撞检测而言:

  • 对于模块化方式而言,碰撞检测就是,比如说,当你在房间中丢出一个小球,当这个球碰到房间内的立柱(单个模块),它必须从立柱那里查询碰撞信息,来确定它击中的位置,以及下一步该怎么做,它会从立柱那里得到一个面数非常低的碰撞模型,这个碰撞模型就是它使用的碰撞盒。
  • 但是对于“一整块网格体”方式而言,相同的球击中网格体内的立柱,小球会得到整个网格体的碰撞数据,仅仅因为它击中了立柱,虽然这种影响很复杂但不会特别厉害,但仍然会产生影响。
    4、内存的话,一个立柱模型可能只有410KB的内存,但“一整块网格体”占用了7.5MB的内存。

所以综上所述,我们可以看到,不论是用大模型,还是小模型,都均有利弊。

解决方案:
为了解决“单独模块”的弊端、“大型整块网格体”的弊端,选择折中的办法,就是模块化网格体,这样可以:
1、节省工作量、时间和内存
2、容易放置、光照、遮挡、碰撞检测、LOD都会有所改善
3、但是绘制调用drawcall的次数会更高

所谓模块化网格体,其实就是,模块不要单独放置,也不要合的过于庞大,可以几个单独的模块合成一个中型大小的模块,这样就是模块化网格体了,同时也中和了两个极端的优缺点。
--------------------------------------分割------------------------------------------

模块化网格体(独立模块的轻量合成)

需要注意的是:小心合并它们,一旦合并后,我们就没办法简单的撤销合并。
我们应该遵循以下合并规则:
(最好用相同材质的独立模块,这样可以使绘制调用drawcall一次性绘制)
1、越常用的网格体,并且面数越低越好。
我们可以从“窗口”菜单选择“统计”
在这里插入图片描述
这里显示SM_TrimWall_U使用了164次,每次有268个多边形
在这里插入图片描述
我们可以选择常用且面数低的网格体,面数较低的网格体合在一起之后面数也不会变得过高,这就很合理。
2、合并同一区域内的网格体。
如果在不同的区域内的网格体合并,这对遮挡没有好处,对碰撞来说也很糟糕,网格体应处于同一区域或房间内。
3、只合并拥有相同材质的网格体,否则性能不会提升太多。
每一种材质都会有绘制调用drawcall,所以如果合并不同材质的,仍然会有相同的绘制调用次数。
4、没有碰撞,或者只有简单碰撞的网格体,更适合合并。
5、非常小,或者只接受动态光照的网格体。
如果网格体太小,我们就不用担心光照贴图。
6、远距离几何体更适合合并。

实际上我们合并与否,都是为了性能、帧率能更好,所以当帧率达到了我们心里的目标帧率比如30FPS,我们就没有必要再去想着如何合并网格体了。

在一些低端硬件上,比如vr、ar、移动端设备上,可能最终我们需要合并所有网格体,所有内容。
--------------------------------------分割------------------------------------------

实例化静态网格体渲染

默认情况下,UE4中的网格体会实例化并保存在内存中,但它们不会在渲染时实例化。内存中实例化、实例化渲染的区别如下。

内存中实例化:
模型只在内存中实例化,并不会在渲染时实例化。
导入模型(如422kb),只在内存中存在1次,如果我把它放到场景中2次,意味着它渲染了2次,但是在内存中仍然只占用422kb。

实例化渲染:
内存中、渲染时都实例化。
比如,将相同的立柱添加到实例化静态网格体组件中,按组进行渲染,它们实例化后仿佛就是一个单一模型,但有4个对象那么大,这样我们就可以一次性渲染一组网格体了。

但实际上我们并不会默认对所有对象,做实例化渲染,因为在做实例化渲染之前,渲染器会依次询问,这两个网格体是否是同一个,依次询问对比会带来大量的损耗,所以有时其性能并不如直接渲染来的更高效。
所以我们只把相同对象放到实例化静态网格体组件中,相当于给它一个简短的列表,告诉它只比较这个列表中的对象即可,因为他们有可能是一样的。

山地上的植被,就是实例化静态网格体组件中渲染的,海量对象渲染出来,也不会消耗多少性能。最好就是用在这种海量(几十个几百个以上)相同对象的情况中,若是场景中相同的四个柱子,也没有太大必要使用这个方式了。
--------------------------------------分割------------------------------------------

细节层次LOD

按距离使用不同细节层次的网格体,比如较远距离时,使用较少网格的网格体,既达到了渲染要求,又减少了渲染开销。

LOD的分层,一般后一个细节层次级别,是前一个的50%或者更多。这个差别要大一些,大到足以抵消为了使用LOD而额外占用的内存,诸如此类。

LOD是减少网格体中网格的数量,还有一个是HLOD。
LOD虽然已经很好用了,但如果一个网格体由多种材质的对象合在一起,那么LOD也会进行N次绘制调用drawcall,而HLOD是到一定距离后,以一个简单的整体,直接替代原有的混合体,直接替换这一组对象。

HLOD近距离观察,你仍能观察到N个单独的模型,但是一定距离后,这N个单独的模型,将被一个整体低面数的模型所取代,这样一来,绘制调用drawcall和面数都将变少。

LOD、HLOD最适合在户外环境使用,除了距离剔除外。

下一节:UE4实时渲染——几何结构渲染三

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值