Unity无缝大世界实现调研

无缝大世界的技术要求

  • 世界足够大,一个地图就完整包含一个非常大的世界,如魔兽世界的整块卡利姆多大陆。面积从几平方公里到数十乃至上百平方公里。包含室外地形,城镇,也包含一定量的室内场景。室外地形包含各种地表,植被,河流,道路,山峰山谷,天空,云雾,光线。城镇场景包含大量的建筑和装饰物。室内场景也可能非常庞大,包含多个层次。
  • 无缝衔接,狭义的无缝大世界指魔兽世界那种,无论是室外场景连绵不绝,还是室外室内之间的直接进出,都是没有Loading的,连续无缝衔接的。广义的无缝世界近室外是无缝的,室外到室内还是要载入的。
  • 自由视角,远视距渲染。渲染更多的物体,以及更远处的地形,物体,阴影。

需要研究的技术点

地形制作和场景编辑的工作流

如何制作一个几十平方公里的大地形?

  • 问题1:工作的可拆分性。不可能同时一个人编辑整个世界,世界必须是可以拆分开并行开发的。

  • 问题2:程序化制作工作流。纯人力的地形编辑以及场景种树等成本太高,且迭代速度太慢。考虑程序化制作,使用Houdini制作地形以及道路河流和树草的撒点,且工作流是可迭代的,即根据gamelpay的反馈要能调节Houdini的参数使之程序生成的节点满足特定的需求。

地形和场景数据的管理

由于地形和场景数据是要分块加载的,所以要使用工具将其处理成游戏中使用的格式。这个包含地形的分块和场景的分块,另外还可以能包含lightmap的分块,导航网格的分块,以及occlusion culling data的分块。Unity默认的方案里面这些都是以scene为单位进行管理的,没有提供分块和将分块连接的方式。而具体使用什么数据,还要看具体使用的渲染技术。

关于地图分块的烘焙数据
地图分块载入后,lightmap和lightprobe数据如何应用,现在一个场景只能设置一套数据,但是大地图情况下,scene中存在多个分块,会分别使用不同的烘焙数据。

地形和场景数据的动态加载以及内存管理

具体加载的内容和选择的技术有关,但基本思路就是根据camera当前位置和方向决定要动态加载的块,使用一个cache来存储块避免频繁的加载和释放。可以参考魔兽世界的方式。

地形渲染优化问题

三角形渲染效率

Unity默认的地形是CPU上的四叉树LOD,支持GPU Instancing渲染,早期不支持Instancing时,draw call数量太多导致效率低,不能在移动平台上使用。现在支持了Instancing,draw call数量减少了,但是实际还是要看地形的复杂度,如果复杂度很高,即便是instancing之后也还是有很多draw call。在移动设备上,一般是使用插件如T4M将地形切分为Mesh,并设置LOD,将地形当做mesh渲染。而现在由于新的硬件和技术的发展,地形面的处理已经向GPU方向发展。如使用compute shader进行剔除,以及使用硬件的曲面细分,这些Unity都不支持,且对于移动端还是有一定限制。这方面是需要研发的重点。如果目标为移动VR,那么肯定目标是高端手机了,也具备了一定的硬件能力,比如普遍支持Comput Shader,那么也可以考虑GPU Driven的方法了。另外要看是否支持DrawInstanceIndirect。

像素着色器效率

除了draw call以及三角面数的问题,地形渲染更大的性能热点来源于贴图采样,因为地形不同于普通模型,并不是使用预先设置的uv去采样预先绘制好的贴图,而是采用笔刷编辑的方式,将多个图层在地图上进行绘制混合,这样每个着色点可能使用了多张贴图,并且具体使用了哪几个贴图,以及各个贴图的权重也是存储在一个贴图中,这个在Unity中称为Splat Alpha贴图,一张splat alpha贴图的4个通道分别对应4个图层。如果图层数超过4,那么就要继续增加splat alhpa贴图的数量。这种渲染方式下由于贴图采样数过多,造成性能极度紧张。在T4M方法中,会重新处理图层,减少采样数,当然这也会牺牲一定的效果。而新技术方面,基本指向Virtual Texture,而VT又分软件VT和硬件VT,使用VT技术可以减少采样次数,其原理是将屏幕中实际会用到的贴图烘焙出来,然后使用虚拟的贴图给整个地形使用,实际上该技术也有多个进化版本。

阴影渲染

大世界的阴影的优化问题,尽量使用Lightmap,对于实时阴影,需要控制按距离渲染,以及CSM,这些都可以使用Unity内置方案,但是仍然可能需要优化,比如CSM的分级别更新,远处的阴影可以不必每帧都更新,对于静态物体和静态光源,也可以缓存shadow map。另外还可以关注VSM(Voxelized shadow map),但貌似不适用移动设备。另外关于混合lightmap阴影和实时阴影,要考虑Unity自带的Mix Lighting Mode方案是否合适,基准是在保证效果的前提下,尽量少计算动态光照和实时阴影,能使用烘焙数据就使用烘焙数据。

动态物体GI

对于动态物体的GI光照,一般是使用SH数据,在Unity中是通过放置Light Probe然后进行烘焙采集SH参数。对于大世界来说,放置Probe本身也是一个很大的工作量,需要研发相应的编辑器工具去方便的放置。另外Unity基于Engliten的实时GI也是可用的(基于辐射度技术),但是实时GI本身也会有不小的消耗,对于移动端还是考虑Probe比较好。

遮挡剔除

对于自由视角,远视距,且场景中有大量物体的情况,除了考虑渲染地形时(包括草树等)的GPU剔除技术,如HiZ,GPU视锥剔除+DrawInstanceIndirect,也还是要考虑这种数量不是极端多,但是面积大的物体的剔除,比如房子和各种室内物件,那么仍然要考虑CPU的遮挡剔除。由于是动态的无缝大地图,这些预先烘焙的OC数据也需要动态流式加载。

LOD技术

  • 地形的LOD包含在地形的绘制中,比如Unity自带的地形使用基于四叉树的LOD,地形LOD时要处理不同LOD层级之间的接缝问题,一般是限制相邻的LOD层级最多差一级,然后连线接缝。
  • 物体的LOD一方面可以用Unity已有的Simple LOD插件。另外还可以考虑的是HLOD这类系统,Unity内部有这个方案,但是没开放出来。HLOD系统将物体重新打散后组装,减少draw call。总体思路就是用一个模型代替多个物体。这个也是一个研发的点。
  • Shader LOD,这个使用Unity Shader自带的LOD层级就可以,不需要研发,但设计Shader系统时要考虑,简单说远处物体使用简单Shader。

TOD和天气系统

主要考虑效率问题,结合Lightmap和SH实现TOD,再结合后处理。粒子则要研究GPU粒子。

浮点数精度问题

当世界坐标特别大时,渲染时浮点数精度就会不够用,Unity HDRP支持camera-relative rendering来解决,思路就是用局部坐标代替全局坐标。如果遇到这个问题可以参考修改URP解决。

框架级优化

  • Unity DOTS 支持大量物体的逻辑和渲染,采用优化的内存管理方式和批量渲染。包含最新的BatchRendererGroup。
  • DOTS中技术,如JobSystem, BRG都是可以单独使用的。

参考资料

收集的zhihu文章: https://www.zhihu.com/collection/807524893

Unity官方方案(非公开):https://mp.weixin.qq.com/s/4h_DrYLdvGLUtWKzsdt8QQ

魔兽世界地图: https://blog.csdn.net/trcj1/article/details/6163753

猜你喜欢

转载自blog.csdn.net/n5/article/details/128560986