• 元宇宙:本站分享元宇宙相关资讯,资讯仅代表作者观点与平台立场无关,仅供参考.

腾讯天美技术美术分享:虚幻5卡通渲染

  • GameLook
  • 2022年12月11日09时

「点击上方"GameLook"↑↑↑,订阅微信」

最近几年,二次元游戏早已经从小众品类成为了手游市场举足轻重的大作来源之一。随着人们对游戏品质的要求越来越高,这对开发者的二次元渲染管线提出了更高的要求。

今年4月份发布的Unreal Engine 5无疑是业内最先进的游戏引擎之一,最近,腾讯天美技术美术工程师YivanLee在Unreal Openday上分享了虚幻5卡通渲染管线的一些基础理论,还谈到了虚幻5卡通渲染管线的扩展升级。

以下是Gamelook整理的完整演讲内容:

YivanLee:

大家好,我是YivanLee,是一名技术美术工程师,很开心可以来到Unreal Openday,今天我带来的分享题目是“虚幻5卡通渲染及渲染管线拓展”。

正如分享题目所示,我的分享分为两个大的部分,第一部分是虚幻5卡通渲染的基础理论,第二部分是虚幻5卡通渲染具体程序上的一些实现。第一部分可以分为四个大模块:卡通勾线(ToonOutline)、卡通shading,第三部分是场景shading,最后还有一点点动画。卡通渲染管线的实现主要是指对虚幻5渲染管线的定制,包括Material Shader的拓展、Global Shader的拓展,包括引擎管线内部的一些深度改造。

第一部分可能会比较适合TA和美术同学,第二部分也许可以对图形程序或引擎TA提供一些帮助。

第一部分:UE5的卡通渲染

因为我个人比较喜欢动漫和二次元,所以今年年初的时候我准备在虚幻引擎里研发一套深度定制卡通渲染效果,而且风格化渲染更好和UE的主攻方向相反,所以我预判不会出现我刚做完,UE就研发一套类似且更好的方案。

所以我从动漫的发展史开始着手研究,把一些二次元作品按照抽象和写实的关系从左往右排列,我们可以把画面分为两种方向:写实和写意。我们把游戏作品、影视作品、动漫、艺术作品按照写实写意从左往右排列找他们的规律,我们发现对于图形渲染来说,越写意画面越简单。简单的色块、线条、光影,风格化会对整个画面进行降频、抽象等操作,越写意,颜色越明快、简单,甚至没有明显的颜色和光影,有的只是简单的结构。

一个游戏、影视作品的画面写实写意占比多少可以根据艺术家的风格来决定,对于上述坐标来说,就是在哪个坐标范围。我发现大家比较认可的二次元范围是红框圈起来的范围,所以可以用它作为我们的真实数据(ground truth)区间进行探索。

我们得到的这个坐标轴还有很多值得深入思考的点,例如,如果在日式动漫中加入更多的光影和反射,这和迪士尼的渲染方向和人物建模之外的区别,它还有什么不同?所以我并不认为这就是下一代日式卡通渲染的方向,于是我们带着这些问题继续探索。

第一个技术模块:卡通勾线

卡通勾线是卡通渲染里最重要的效果之一,艺术家用线条来抽象世界里各个物体的结构。目前用于廉价实时勾线渲染的方案可以分为这四类:几何勾线、资源勾线、屏幕空间勾线和光线追踪勾线。

几何勾线常用的是backface勾线,即把模型向外挤出,也可以使用geometry shader(GS勾线)等方式进行边缘检测来生成几何线条。我在Unreal Engine中尝试了这几种方法,发现都可以获得比较好的效果。但是最终我放弃了GS勾线方案,所以几何勾线剩下的就是使用backface勾线。

资源勾线比较好理解,就是在资源贴图上做文章,比较直接的方法就是直接在贴图上画线条,但这样会受到多方面因素的干扰,如贴图分辨率、Mipmap、锯齿等等,为了解决这个问题,业界诞生了很多方法,比如本村线或者SDF之类的方法,但是这些对于美术工作量来说,其实是比较大的负担。

屏幕空间勾线就是利用一些屏幕渲染的空间数据进行边缘检测,常用的就是对深度、法线、ID等数据进行边缘检测,这也是我卡通渲染方案里面大量使用的方法。

几何勾线中,backface勾线是性价比极高的一种方法,只需要把模型再绘制一遍,把模型沿着法线方向挤出即可。为了克服断边问题,我们可以将法线进行平滑以后存为第二套法线,在UE中可以在batch mesh的时候再塞一个mesh进行二次绘制,也可以拓展一个mesh command,我这里使用了一个Primitive component,在add batch mesh的时候塞一次模型的方法实现二次绘制效果。

使用geometry shader也可以很轻松地查找出边缘然后绘制出geometry的几何线条,不过这种方法需要上传临边buffer,所以出于性价比的考虑,我并没有使用geometry shader进行线条生成。关于geometry shader的一些方法可以参考我在知乎专栏里的“Mesh Material Geometry Shader in UnrealEngine”这篇文章来实现。

在贴图资产上绘制线条是最直接的方式,不过考虑到分辨率、mipmap、抗锯齿等因素,使用本村线或SDF优化可以大幅减轻资源勾线的一些问题。本村线主要是工作量太大,SDF勾线需要提供一套高精度的SDF贴图,我们可以使用Substance Designer来快速制作SDF贴图,不过这都需要生产一些额外的资产,对美术工作量是一个负担。

接下来是屏幕空间勾线,它主要是利用很多屏幕空间数据来查找边缘来得出,因为Unreal Engine是以延迟渲染为主的渲染管线,所以这里我们有非常多的屏幕空间数据可以拿出来利用,例如深度、法线以及各种ID,都可以作为作为屏幕空间勾线的数据源。

在我的方案中,我会使用depth、normal还有ID这些屏幕空间数据对边缘进行查找,把边缘生成出来,这些数据也可以进行互补,把一些不以查找的边缘也可以生成出来,得到比较好的综合结果。

对于屏幕空间勾线的法线,我使用了顶点法线,因为贴图法线可能会被用来修整光影,所以如果把贴图法线用来勾线可能会和修整光影这个功能冲突。最后我的最终效果是多种勾线方式的复合体,包括Normal、depth、ID和backface等勾线方案的复合。可以看到,这些方案各有优缺点,但是我们把它综合以后可以得到一个各取所长的效果。

屏幕空间边缘检测其实有很多方法,我最终选择了Laplacian和Sobel算子进行屏幕空间检测,可以看到在不同权重和设置情况下,它的勾线其实是互补的,laplacian和sobel其实在不同的情况下各有所长,所以我最终取的是它们的复合结果。

对于Sobel或Laplacian算子来说,需要控制的一个重要参数就是它们的阈值,如果不对阈值进行区分可能就会产生很多杂线,例如脸部可能需要比较高的阈值来过滤掉杂线,但是对于头发来说,我们可能就是需要比较低的阈值来产出这些凌乱的线条,因为头发本身可能就是个会有很多线条的结构。所以对于阈值的控制,我们需要根据人物不同的部分,甚至是材质的不同部分进行精细化控制,可以看到控制前和控制后有明显的提升。

虽然法线+屏幕空间勾线的方式可以勾勒出大部分线条,但我们对其可控性很低,所以我增加了ID勾线的方式对勾线方案进行补充。我们可以对不同区域进行ID绘制然后检测这些ID的边缘来生成线条,这样可以让屏幕空间勾线的可控性大大提升。我想要使用的ID数据是三维的,其实也可以使用一维或二维的ID来精确地指出边界,比normal勾线可控性高很多,但缺点是ID数据需要一定的美术工作量,不过的确可以和normal、depth勾线进行互补。

通过各种方案产生了线条以后,还需要对其进行一些精细的控制,比如线条粗细、哪里有线条哪里没有线条?我这里使用了两种方法,第一个是在贴图上绘制线条的粗细然后传到Gbuffer里面,然后在屏幕空间勾线的时候读取这个粗细值进行控制。还有一个方法就是将全局权重暴露在postprocess里面去读取这个数据,然后对线条进行全局控制。

比较具有代表性的就是下颌线的绘制,可以看到下颌线是有变化的,当我们旋转的时候,下颌线有时候是不连续的、有时候又是连在一起的,这其实就是通过刚才一系列方案达到的效果。

我们可以通过指认线条粗细的区域,加上backface勾线对脸部线条进行补充,来达到这样的效果。

因为backface勾线天生是不对内部进行勾线的,那我们就用backface对脸部线条进行勾线,下颌线再使用刚提到的线条粗细在模型表面的权重控制来达到这样的效果。

解决线条生成以及粗细控制以后,我们还需要对线条进行上色,我们可以渲染一个outlinecolor render target对画面区域进行染色,还需要对outlinecolor render target的颜色进行外扩,以保证最边缘的线条是被染了色的。当然,也可以使用贴图来控制某个区域线条的颜色,对这个材质指认一个颜色进行染色。

处理了线条粗细和颜色之后,还需要处理线条的远近变化,对于屏幕空间勾线来说,如果画面拉到极远,线条会变得非常密集,覆盖掉人物。以往的勾线思路是越远线条就越细,但对于屏幕空间勾线,这条就不特别适用,因为像素最细就一两格,再细就没有了,所以我们需要转换思路:越远就越淡,这时候线条拉的越远就越接近basecolor或scenecolor的颜色。

除此以外,我们线条的LOD方案也是复合的,所以当距离大于一定程度的时候,我们可以将一部分勾线算法去掉,例如画面拉到极远的时候我们将内描边去掉,只留外描边,这样就可以保留最基本的线条信息,又不会因为拉的极远让线条把画面覆盖掉。

完成勾线功能之后,我们需要对FOV模型进行校正来模拟卡通渲染的扁平感觉。左边的图是未经FOV校正的,右边是经过校正的,可以看到校正以后整体画面更加扁平、更二次元卡通。

ToonShading

因为我想要大范围兼容卡通渲染效果,既支持非常风格化的赛璐璐,也支持像新海城一样稍微写实一点的风格化,所以我对UE原有的渲染管线进行了拓展,这对渲染管线无疑是有一定冗余的。如果项目风格可以确定的话,我们在原有的UE上进行改造即可,这样可以省掉大量的Gbuffer开销。

卡通材质因为是被艺术抽象过的,所以我们只能在有限的几个维度做文章。从卡通材质的表面属性出发,可以分为高光、亮部颜色、阴影过度、阴影颜色这几个维度,并且这几个维度是需要我们严格控制的,因为卡通材质可以控制的维度就这么几个,我们对这几个维度控制就可以做出不同的卡通材质效果。

例如对皮肤材质而言,我们需要控制它的高光、暗部的颜色和两部分之间的过度。我们可以通过预积分的方式精准控制阴影过度。除了上面讲的几点以外,卡通材质的形态也是它的表现重点,建模本身也是控制材质表现的重要一环。

例如我们对高光做好了控制之后,就可以很容易对金属和布料材质进行区分,这里演示一下动态效果: