Hello大家好,我是雷宇航,知乎上写卡通渲染眼镜篇和面部篇那个MIZI,目前是网易的技术美术,非常荣幸受邀给大家带来卡通渲染的分享。
雷老师的知乎个人主页:
https://www.zhihu.com/people/zi-xie-42-53
本次内容我会围绕卡通渲染中角色使用到trick来解析其中的技巧。由于时长的原因,本次只会对卡通渲染中经常使用到的方法做一些罗列,讲解的不会特别深入,内容也不是很复杂,对其中细节感兴趣的同学可以会后一起交流一下。我们正式开始。
本次主要讨论两个话题,一个是卡通渲染的trick,另一个是NPR和PBR的结合。这是详细的目录。
卡通渲染在动画和游戏中的制作思路是不同的,动画中相机经常是固定角度,可以去手动修正瑕疵,而游戏中的卡通渲染会更加注重在不同环境与角度下效果表现的合理性。
因为2D画面在3D画面中并不是完全成立的,所以在卡通渲染中各种trick就是难以避免的。前半部分我会首先来概述一下卡通渲染的基本内容,这一部分会相对比较简单。
另外因为基于PBR的可能仍然是现在的大方向之一,后半部分内容我们就讨论一下卡通渲染和PBR结合的问题,以及目录中这些Shading Model中存在的trick。
让我们开始第一个话题,基于trick的卡通世界。
从2015年罪恶装备在GDC上分享卡通渲染的方法大现在,卡通渲染的发展非常迅速,有基于赛璐璐的动画还原,比如说《罪恶装备》,《赛马娘》这些,还有基于PBR的风格化,像是《鹿鸣》、《奇迹暖暖》,也有不那么PBR,但是使用了PBR制作,比如《碧兰幻想》《蓝色协议》等,再到更加风格化的探索,像是《破晓传说》。
卡通渲染的风格表现力是越来越广,对于卡通渲染来说,不像PBR那样有标准流程和衡量准则,卡渲很大程度上会依赖于美术方面的造型和色彩,所以美术风格的处理在卡通宣传中是比较重要的。
另外卡通渲染是人们主观审美与现实环境抽象的结合,不同人对卡通渲染概念理解不同,这就产生了各式各样的制作流程,不过还是有一定固定思路在其中的。然后我们就来看一下游戏开发者们为了好看的卡通渲染画面都做了哪些努力?
首先列一下概念,卡通渲染常见的有两个名称,就是Cel Shading和Toon Shading,Cel是赛璐璐celluloid的缩写,而Toon就是cartoon的简写。最简单的我们只需要阴影、描边和高光,就可以组合成具有卡通感的画面。
不过就像刚刚所说的,这些并不是必须的。随着卡通渲染的发展,卡通渲染这个概念在逐渐的泛化,在美术上有对应的形态和色彩表现,就可以有卡通风格的感觉了。
首先是卡通渲染的基础表现,下面先来快速过一遍卡通宣传的基本技巧,这一段内容会比较简单。
卡通渲染第一步就是修改光照模型,对NDotL计算兰伯特光照进行修改,常见的有使用Step函数,RampMap贴图的方式。
首先是Step阶跃函数。单独的Step很简单,就是给另外一个A值,大于该值的为1,小于该值的为0,而Smoohstep就是平滑的阶跃函数,图中的紫色曲线就是Smoohstep的函数图像,右边是对应的光照结果,在给定的a值和b值之间会有一段平滑的过渡,兰伯特计算结果,将兰伯特的计算结果通过step重新映射,我们就可以控制阴影的边界软硬和位置了。
然后是RampMap,ramp图修改光照的方式和阶跃函数类似,将兰伯特光照作为映射值去采用ramp图就可以得到对应的风格化光照。中间的图就是ramp图(又称LUT查找表)。阴影的软硬和颜色变化可以通过ramp图的色彩过渡来实现。
然后是边缘光,这是常见的效果之一,动画中的边缘光更偏向软硬两层边缘光混合的情况。常见的实现方式主要有两种,菲涅尔和深度偏移,也有使用边缘检测的方式,不过不太常见。
基础的边缘光可以由法线和视角方向点积获得,基于NDotV,同时这也是Shader Graph中Fresnel节点的计算。
对于深度偏移的边缘光可以获得等宽的硬边缘。这对于一些转折比较少的模型,比如立方体的支持会更好一点。原理就是将模型顶点偏移,重新采样深度,然后与原模型的深度进行比较,深度差大于某一值域,那么就是边缘。《原神》中的人物边缘的亮边应该就是使用了这种方式。
明暗交界线是动画中经常会出现的特征,这是绘画中常见的处理。基于这些特征,不少画师会在明暗交界线上做特殊的偏色处理,动画中也都有体现,在物理的渲染中比较接近这些效果的是SSS表面散射,这一表现可以看作是对SSS的夸张。
那么对于明暗交界线的计算,我们只需要找到明暗交界线区域的亮度范围就可以了。
如果使用ramp图来计算光照,就可以直接将交界区域在ramp图中画出来。另外也可以使用数学的方法,比如之前的阶跃函数用两个Smoohstep,一正一反相乘,就可以求得中间明暗交界的位置,然后填充颜色。或者也可以使用高斯函数,也叫正态分布函数来选中明暗交界线区域过渡的位置。
最后是描边,描边也叫轮廓边,早期描边主要的作用是补充动画中色块的细节,把转折的结构表现出来,所以这个时候描边叫做轮廓边会更合适一点。另外轮廓边并不一定是黑色的,在动画的场景中轮廓边大多以亮线的高光形态来表示,就像右图中的亮线勾边一样,人物上则一般是以黑色的轮廓线偏多一点。
然后到现在的描边除了强调主体这样的用途之外,更多的就是承载风格化表现的特征了。像《无主之地》这种就是直接将描边作为自身的风格。
常见的描边方式有这几种,前面说的边缘光,RimLight也是可以作为内描边的一种,而Backface和边缘检测是游戏中最常应用的描边,基于轮廓边的检测是离线渲染中经常会使用到的方式,本村氏线是一种特殊的描边,我也一起加到描边方式里面了。
先说一下Backface。这种描边方式是将物体渲染两遍,一次正面,一次背面,背面渲染时向外挤出就可以获得边缘描边了,值得一提的是法线是否合并会影响这种描边的连续性,所以经常要去存一份平滑的法线数据来计算描边。
边缘检测是图像处理的操作,通过算子对图像卷积就可以获得描边,常见的Sobel算子是行动卷积和,这种方式在不同场景下的消耗比较统一。
另外对于卡通渲染来说,我们会想要整洁的边缘线,对整个图像进行边缘检测就会出现多余的描边信息,所以常见的技巧就是会在边缘检测区域做不同色块的纯色填充,这样在进行边缘处理时,就可以得到右图中这样一个比较干净的结果,就像右边这个图中,上面的图是对应区域的色块填充,下面的图是边缘检测的结果。
基于模型拓扑的轮廓边检测是离线渲染中经常使用到的方式,这种方式的消耗比较高,但是可以获得一些很风格化的表现。
最后就是本村线了,这个装备中分享的角色表面描边的方法,并不是外描边,它是将模型的UV打直,只绘制于垂直于U轴或者V轴的直线,避免斜线线条的采样问题,从而获得锐利的线条表现,就像左图中对比一样,不过这种方式对模型的制作要求很高,它的制作周期会比较长。
现在我们已经快速过了一遍卡通渲染的基础知识了,那么运用这些知识,我们就可以轻松的做出一个卡通渲染的角色了。不过想要提升角色的质感,还需要另外一块拼图,那就是PBR,这张图是我在Unity中测试的效果,使用的是《少女前线二》闪电姐的MMD模型。
我们来开始进行第二个话题,就是基于PBR的卡通表现,基于物理的光照,PBR是对现实的还原,而NPR则是非真实感渲染。虽然它们名称上是对立的,不过为了效果的提升,我们可以各取相关的特征缝合起来表现效果。使用PBR的优势在于PBR是艺术导向的,它能让美术同学用直观的参数,标准化的工作流,快速的实现大量材质的真实感渲染,把NPR的特征迁移到PPR中,并且保留这种易用性就是我们的目标。
但实际操作中由于卡通渲染的特征涉及非物理属性的方面太多,这种易用性是比较难以保持的,需要根据项目对不同的特征的参数进行取舍。不过PBR所带来的环境光照和PBR的质感是比较容易保留的。
左图是Unlit的材质,右图是基于PBR魔改的NPR,混合PBR的NPR就可有一部分卡通效果,同时也具有PBR的质感了。
PBR中存在的间接光照计算可以比较方便的适配不同环境下的光照表现。不管是夜晚、白天、森林或者是在其他的一些环境下,在不同的环境中都可以有对应的光照反馈,这对角色与环境的适配是十分有利的。
我用Shader Graph做了一个典型的PBR材质。
众所周知,PBR是由直接光照与间接光照组成,这里的黄色和橙色区域就是直接光的镜面反射与漫反射,绿色区域是间接光的镜面反射与漫反射,蓝色区域就是数据初始化的计算。比如NdotL 、NDotV这些
这是这个典型的PBR是在不同的粗糙度与金属度下的表现。
将PBR与卡通表现混合在一起的思路并不复杂,简单的来说将之前讲述的特征插入到PBR的计算流程中就可以了。但是怎么混合两者的特征,在什么节点去插入计算,这是一个见仁见智的事情,对于不同的风格,不同的管线流程都会有不同的结论。
我将对应的卡通特征插入到PBR流程中,大概长这个样子,稍微有点凶残。当然了这个shader只是为了讲解做的测试,项目制作中不会这样用ShaderGraph直接做PBR。
首先是魔改NPR特征后PBR整体计算流程并没有改变,依旧是直接光与间接光的镜面反射和漫反射叠加。下面就简单来讲述一下需要修改的部分。
首先是蓝色区域中数据初始化阶段的处理,最主要的是对法线N进行的操作,NDotL和相关的应用计算都可以在这里进行重新映射和合并,比如二值化阴影,面部阴影、头发投影、影贴图之类的阴影相关的操作,然后把它们合入到NDotL的结果之中。同时NDotV的控制也可以改变一部分菲尼尔的效果。
之后来看黄色区域的DFG项,这里效果比较明显的更改项就是法线分布函数D项,比如对GGX高光的范围进行重新映射,或者更改计算各项异性高光,并且加入遮罩偏移之类的操作,然后是橙色区域的diffuse计算,这个地方进行的操作,基本上可以当做emission自发光来添加。
对于卡通渲染来说,一些色彩混合操作需要在这里加入,比如头发、高光,如果要使用颜色叠加的方式加入到计算结果中,就像柔光、线性光这些操作就需要在这里加入了,虽然不那么物理,但是可以保证效果。
之后就是绿色区域的间接光部分了,间接光的加入会显著提高模型的质感与立体感,但是对于卡通渲染来说,立体感的提升并不一定是好事,所以最直接的修改方式就是按照不同部分减少间接光的权重,比如对皮肤、面部这些需要平面表现的部分去减少间接光的比例。 其他还有蓝色协议使用了整体向上的法线,计算统一颜色的间接光也是一种方式。
最后就是紫色区域了,这里的计算是直接当作自发光来添加的,比如说眼睛的高光,Matcap反射,边缘光之类的。经过对PBR整体架构的模改,我们就可以得到混合了PBR的卡通表现。这里它长这个样子,这是 PBR魔改后在不同粗糙度和金属度下的表现(下图中右图)。
和默认的PBR的对比,因为自定义了阴影颜色和一些自发光的原因,它整体会更加明亮一点,卡通渲染插入到PBR中,并不会完全能量守恒。
不过对于卡通渲染来说,很多不守恒的表现是可以接受的。所以虽然并不完全能量守恒,但是也适合于卡通渲染的表现。
这样我们就有了混合PBR的NPR表现,之后就要为不同区域去定制对应特征的Shading Model了,比如头发、眼睛、皮肤这些。
本文节选「Unity大咖作客」,分享内容为网易 TA 大咖雷宇航的《走近卡通渲染-关于 Trick 的两三事》,完整内容请查看:
https://developer.unity.cn/projects/cel-shading-trick