《秦时明月世界》手游如何用Unity定制化渲染管线?

Unity官方平台 2020-12-08
由玄机科技正版授权、魔方工作室群研发的经典国漫IP改编手游《秦时明月世界》,收获了广大玩家和原著粉丝们的一致好评,在TapTap上评分高达8.6。这款游戏是魔方工作室对3D大世界MMO的首次尝试,也融汇了他们在玩法和技术方面的探索。

11月16日,腾讯魔方工作室高级工程师王毅以“《秦时明月世界》手游的定制渲染管线”为主题在Unity线上技术大会上发表演讲,介绍了《秦时明月世界》手游如何借助Unity实现定制渲染管线技术,具体包括相机与颜色空间、深度图、Grab Pass、后处理和多光源几个方面。

本次演讲也已经上传至Unity B站官方,大家可以前往观看:
https://space.bilibili.com/386224375

以下为王毅的演讲内容:


《秦时明月世界》手游是一款大型MMO手游。首先给大家展示一下游戏中残月谷的一段关卡战斗,整个战斗过程结合Unity的TimeLine,我们做到了一镜到底,无缝切换的战斗和动画的表现形式。


今天主要是给大家带来《秦时明月世界》定制化渲染管线技术相关的一些介绍。主要分几个维度,包括相机与颜色空间、深度图、Grab Pass、后处理和多光源这几项。


《秦时明月世界》中基于相机和颜色空间表现的准备工作,主要是分辨率的分离,UI高清,场景动态,平衡效果与效率。

我们在整个3D游戏世界中,经常会基于PBR的高清的线性空间制作,但是常规的UI美术平时习惯于在Gamma空间工作,导致两边的工作流程有一些冲突。UI的美术不太适应线性空间的流程,也不太适用线性空间下的颜色在他们的自产工具里制作。

但是,我们游戏中要使用在线性空间下的流程。为了他们的统一,我们会将分辨力进行分离,把UI进行高清的分辨率显示,场景进行动态控制,场景中使用线性空间的流程,UI使用Gamma空间的流程进行绘制,这样就可以保证场景基于不同的机型、不同的表现形式进行一个动态分辨率的调整,保证UI的高清化。同时也使UI的资产可以在Gamma空间下进行正确的显示,保证游戏中场景的线性空间的显示和UI的Gamma空间的显示可以在一个正确的流程下工作。

我们的过程就是场景中使用一个线性空间的表现形式,它有单独的相机区进行绘制,同时在与UI相机进行blender,输出到屏幕上。然后场景空间的相机进行Gamma校正,而UI本身就是在Gamma空间的流程进行工作的,所以它不需要Gamma校正。


接下来再说一下我们基于深度图的改造。

Unity为我们提供了深度Pass这个过程,帮助开发者可以在游戏项目中快速的某一阶段获取深度图来进行绘制及采样深度进行渲染。

《秦时明月世界》进行了定制化的改造,在非透明物体中如果需要使用深度图,就会采用深度Pass这种方式去获取深度图,如果在非透明的物体下不需要使用深度图,我们就会采用深度图获取的方式,直接从深度Buffer中拷贝出来深度图进行使用,这样可以有效地减少额外的DC造成的渲染消耗,尤其是对一些低端手机或者是对于DC特别敏感的手机来讲,这种使用方式效率会更高。结合这两种方式,我们就会更高效地使用Unity的深度图。

我们在Unity的PC版、Unity的Editor,包括iOS版本都会使用翻转的Depth这种结构来表示深度Buffer,但是在安卓平台,由于OpenGL ES的限制,并没有使用这种方式。为了统一这个方式,我们进行了改造,在安卓平台也使用深度翻转的这部分使用深度Buffer。

主要原因在于,我们的美术,尤其是关卡设计师和模型师在进行关卡设计和资产设计的时候,他们基本上是在PC平台或者是在非移动端进行关卡的组合以及关卡的布置,这样往往会出现一些因为经度问题,导致关卡进入到实际的手机或者是移动端的版本上,尤其是安卓的平台,由于精度的问题,会出现一些关卡上显示的瑕疵。这个时候美术师或者是关卡设计师就需要反复调整关卡的结构,来保证显示效果的正确,相对来讲是一个漫长耗时的过程,因为移动端要涉及手机端的APK的打包,这些过程都会影响到整个关卡制作的进度。

为了统一这个方法,我们就在安卓端也使用了深度翻转的技术,保证和在PC端以及iOS端使用相同的Buffer处理形式,这样就可以大大地缓解关卡设计师在制作阶段因为深度冲突导致的显示中的瑕疵,统一关卡设计中因为平台化造成的精度问题引起的显示上的瑕疵。整体来讲,缩短了关卡制作的难度以及周期。


下面再说一下《秦时明月世界》定制管线中关于Grab Pass的定制过程。

首先,Unity本身的Grab Pass是按照传统的形式,如果是相同的名字命名,它会使用同一张Grab Pass,如果是不同的名字命名,它会分别使用不同的Grab Pass。如果是项目中使用不慎,就会出现很多Grab Pass造成的一些RT的爆增,导致内存爆增的问题。《秦时明月世界》这里面采用了单一的控制方式,可以有效地缓解这种处理方式。

首先,它会收集需求,Grab Pass的Renderer,禁止绘制,然后计算每个Renderer的可见性,判断需要哪些RT,同时根据具体的需求,我们可以使用全分辨率的RT,也可以使用不同情况缩小屏幕空间的一些RT动作,这样可以有效地控制RT的分辨率,节约内存。

在整个绘制阶段,利用Unity提供的CommandBuffer,我们可以快速地截取屏幕,并且在特定的阶段会去使用这个Grab截图,然后进行特殊的效果。


下面介绍一下我们《秦时明月世界》中定制管线的后处理流程。

《秦时明月世界》使用的是Unity为我们提供的后处理组件,传统的后处理组件整个的流程是这样的形式,首先通过一个屏幕空间的分辨率,经过若干个后处理的流程,进入到一个Unity提供的UberShader,然后再经过FinalPass整个的阶段,为了兼容传统的后处理流程OnRender Image的方法来保证传统的全屏处理绘制显示,最终再绘制到屏幕上,然后融合到UI相机显示到屏幕上。


可以看到整个过程会产生大量的RT切换,相当于硬件FBO的切换,在Tile GPU上会造成额外的内存的回读,性能大量地消耗,而且至少会有两到三次的全屏幕的操作,这样会大大地影响整体的性能,使得后处理阶段会是一个在《秦时明月世界》项目中非常重要的性能消耗点。

基于这个,我们优化了后处理的流程,降低了它整个渲染的过程。首先,我们去掉了UberShader的过程,将UberShader及FinalPass和绘制屏幕这个过程三个全屏的操作统一到一起,同时又将传统的基于屏幕空间的绘制移除掉,这样就可以保证我们后处理的流程仅仅使用标准的一个全屏幕处理就可以直接与UI相机融合,绘制到屏幕上,不会造成额外的FBO的切换,也不会造成额外的FBO的回读操作,大大降低了内存中的回读以及全屏幕的运算操作,从而提升了后处理本身的效率。


接下来讲《秦时明月世界》的定制渲染管线的多光源。

Unity中多光源的处理方式在传统的渲染管线中使用的是ForwardAdd这种方式,采用多个Pass绘制多个光源。《秦时明月世界》采用了单Pass多光源的方式绘制。

首先,使用静态分支去优化设备,同时控制内存,使用光照的位置来定义光源类型,Shader中也会根据区域进行划分。《秦时明月世界》中对于多光源主要使用的是点光源和聚光灯,整个过程会采用单Pass多光源的方式绘制。基于这种方式,就可以减少ForwardAdd增加Pass的这种情况,也就是说在多光源的情况下整个绘制过程,一个Pass会把所有灯光绘制到这个物体上,可以保证我们在对于DC特别敏感的设备上不会使用多Pass这种方式来增加系统的消耗,提升整个多光源效果上整体性能的开销。


给大家展示一下效果。主要展示的是我们在使用多光源的同时使用的一个单Pass多光源的效果。可以看到在技能释放的过程中,在技能相关的位置会有多个点光源去影响整个场景以及人物。但同时多个光源又是因为一个Pass来绘制的,会大大节省性能。

技能多光源

这是一个色相分离效果。

色相分离

这个是后处理的边缘模糊和多点旋转的效果。

边缘模糊&多点旋转

这是一个帧混的效果。

帧混效果

这是《秦时明月世界》中轻功的色相分离以及径向模糊的后处理展示。

色相分离&径向模糊

这是水面效果的展示。这里面就用到了刚才提到的Grab Pass,用来做折射处理。

水面效果

感谢大家!

来源:Unity官方平台
原文:https://mp.weixin.qq.com/s/3p7az4cJkLfDKyaW-K0Wew

最新评论
暂无评论
参与评论

商务合作 查看更多

编辑推荐 查看更多