![574bb3af7307ccdc1e8a0271305d5f25.png](https://img-blog.csdnimg.cn/img_convert/574bb3af7307ccdc1e8a0271305d5f25.png)
记得上次写小作文的时候还在上学,转眼都工作一年多了。这一年里发生了蛮多事情吧,辗转已经经历了三个项目了(算上mini的话有四个了),还有一个常年跟着旁听的项目,至今没有尝到过项目上线的滋味,甚至连工位都平均一个月搬一次。
其中经历最长的一个项目是是个卡通渲染的项目,作为一个死宅(划掉),卡渲当然是最感兴趣的一个东西。大概做了半年多,结果因为一些原因不得不离开。前两天又听说到了一些事情,还是蛮唏嘘的。所以突然想总结下这半年多做过的东西,权当纪念一下吧。
废话说完了,开始正经的。卡通渲染作为一个比较大的话题,还是存在着各种各样的流派的,或者应该称之为风格化渲染更为恰当。这篇文章大概就记录一下风格化渲染的一些流派和思路吧,复杂的原理和算法就不展开讲了,毕竟我写文章的水平也不太行。
光照(Shading)
1.赛璐璐
赛璐璐光照也是人们常说的最基础的卡通渲染,特点是硬切的明暗面,风格化的阴影,风格化的高光,就像2D的插画一样。
![eced5c860f172ddd9d807303534f259a.png](https://img-blog.csdnimg.cn/img_convert/eced5c860f172ddd9d807303534f259a.png)
实现方式也很简单,计算普通的漫反射光照,并用光照强度去采样一张Ramp即可。想要怎样的变化,怎样的色阶都可以。当然实际在项目中应用的话,有时为了减少贴图采样,也会通过数学计算去拟合一个Ramp出来。
此外,展开来看,由于是风格化渲染,不存在所谓的物理正确,所以其实每个部分的效果都可以开放出来让艺术家来控制。例如阴影颜色,高光颜色,边缘光颜色,亮暗面边界软硬程度等等,都可以通过添加一张图或者给出颜色参数来实现可自定义的颜色,最终渲出来能像原画一样就是成功。开放可调整的参数越多,越容易做出艺术化的效果,但对于美术能力的要求就会更高,具体的度就需要不同项目根据实际情况去把握了。
最后贴一个大佬的卡通渲染shader详解,讲得可以说是超详细了
http://sorumi.xyz/posts/unity-toon-shader/sorumi.xyz另外Unity Japan做的Unity Chan着色器也是功能蛮完善的,可以用来学习参考
https://github.com/unity3d-jp/UnityChanToonShaderVer2_Projectgithub.com2.次时代卡通渲染
传统的赛璐璐渲染缺点在于无法表现出材质的质感,只能表现平涂的感觉,于是风格化渲染又诞生了一种不那么“卡通”的卡通渲染。这种感觉是最近几年才火起来的一种风格,从米忽悠的琪亚娜极乐净土开始,到最近刚上线的闪耀暖暖,都是基于pbr的光照模型,外加一些ramp、笔触贴图之类的风格化处理(Ramp大法好),具体制作起来也和普通的次时代流程差别不大。至于实际使用到项目中,可以考虑一下相关的取舍。例如IBL是否使用,选择哪种光照模型,是否要使用Matcap等等。关于渲染相关的实现看下米忽悠和叠纸的分享就好。
游戏葡萄:米哈游技术总监首次分享:移动端高品质卡通渲染的实现与优化方案zhuanlan.zhihu.com![ad9330dad47e2c72ff8e8cc88907fc35.png](https://img-blog.csdnimg.cn/img_convert/ad9330dad47e2c72ff8e8cc88907fc35.png)
![77aed4942510f9a3988fc7d465585ad1.png](https://img-blog.csdnimg.cn/img_convert/77aed4942510f9a3988fc7d465585ad1.png)
勾线(Silhouette)
在卡通渲染中,勾线一般分为内勾线和外勾线两种。对于大多数情况下的游戏中来说,外轮廓勾线已经足够,但是若想得到高品质的卡通渲染效果,还是需要内部轮廓线的。这两类轮廓线的实现方法不太相同,内部勾线相对更难实现一些。
外勾线:
1.类似边缘光的实现方式,计算模型世界法线与视线的点乘,取垂直部分变成黑色。优点是性能消耗较少,实现简单,缺点是除了性能消耗小之外哪都不好,粗细无法控制,内部轮廓也会出现杂乱的线条。
2.多加一个pass,将模型正面剔除,沿顶点方向外扩,俗称Backface,也是比较常规的做法。在此基础上可以做出一些扩展:
- 通过顶点色控制描边粗细
- 某些时候勾线色调适合与diffuse保持一致,可以考虑采一次图或者把diffuse烘焙到顶点色中
- 勾线近细远粗,可以在裁剪空间对模型外扩,也可以在模型空间外扩,并将摄像机到模型的举例作为权重
- 模型内部出现杂乱的线的话,可以使用stencil buffer将内部的线去除
3.后处理勾线
基于屏幕空间进行勾线,通过输出屏幕深度和法线,并基于一些滤波算法寻找出图像中的边缘,能够同时实现内勾线和外勾线。缺点是对forward rendering不太友好,而且无法单独控制某物体的勾线。
照例是提供一篇大佬的参考资料,里面有比较详细的实现
https://www.cnblogs.com/alps/p/7606028.htmlwww.cnblogs.com内勾线:
1.最简单粗暴的方法,画到贴图上,美术也方便,技术也简单。缺点就是锯齿马赛克。
2.方案1的进阶版本,通过对UV特殊处理,将边缘线排布在UV横平竖直的位置上,从而不会出现由于贴图精度不足造成的马赛克,这就是传说中让美术闻风丧胆的本村线。
![c6b18fc8885de299a94e3ac16a30eb5b.png](https://img-blog.csdnimg.cn/img_convert/c6b18fc8885de299a94e3ac16a30eb5b.png)
这样的做法难度在于美术很难在保证diffuse正常绘制的情况下还把uv拆得这么碎。实际应用中可以使用UV2来降低制作难度。详细介绍可以看他们在GDC的分享视频:
https://www.youtube.com/watch?v=yhGjCzxJV3Ewww.youtube.com3.后处理勾线,上面提过就不说了
4.基于几何着色器,通过相邻三角形的法线判断线是否为边缘线并绘制。目前在unity内支持可能不太好,具体可以看这篇论文:
http://cg.iit.bme.hu/~szecsi/cikkek/crease12/crease_hajagos_final.pdfcg.iit.bme.hu5.一个比较粗暴的办法,提取模型尖锐边缘,挤出,保存成mesh,用勾线的颜色将提取出的mesh在引擎中再渲染一遍。
6.二之国中使用的勾线方案,通过在角色身上不同部分刷出不同的顶点色,然后在顶点色变化的交界处勾线。
![9c57f93fc35332e82ac6ee7da1007b73.png](https://img-blog.csdnimg.cn/img_convert/9c57f93fc35332e82ac6ee7da1007b73.png)
这种方法可能也需要在屏幕空间中处理,但可控性较高,而且效果拔群,值得学习。
7.运行时提取模型边缘信息并计算轮廓线,性能消耗很大,常用于离线渲染,效果拔群。例如pencil+这个渲染器便是基于这个方法实现的
其他(Others)
还有一些不好分类的杂项,一起总结在这里
1.眼睛渲染
眼睛主要是参考了崩坏3分享时提到的折射,优化从侧面看时眼睛的效果。
![88cbbee2245f810f850c80d8ddf9ed2c.png](https://img-blog.csdnimg.cn/img_convert/88cbbee2245f810f850c80d8ddf9ed2c.png)
当时看了给出的两行代码有点头大,没看懂offset是怎么用的,后来研究出来了(虽然不知道对不对)
half3 offset = half3(dot(V,IN.uWorld),dot(V,IN.vWorld),dot(V,IN.front));
uv += clamp(abs(offset.xy) * (1-offset.z) * 0.1,-0.05,0.05))* _RefrationIntensity;
![8f1d8ce11402c69c5d11ecc7c3c15160.png](https://img-blog.csdnimg.cn/img_convert/8f1d8ce11402c69c5d11ecc7c3c15160.png)
2.面部三角光
当初第一次听到这个需求的时候我是迷惑的,并听不懂这是什么东西。于是美术给我塞了两张参考图
![ac73868030900dac50d76fdec67f8ecc.png](https://img-blog.csdnimg.cn/img_convert/ac73868030900dac50d76fdec67f8ecc.png)
仔细看他们的鼻子旁边,会有一块三角形状的高光。虽然看起来很像菲涅尔,然而它的形状非常风格化,菲涅尔很难实现出合适的效果。于是最终采用的方案是一张mask + 特别敏感的菲涅尔计算,实现了脸稍稍侧过去就会出现三角光的效果。
![2d2eddd95962b549e9ee7a7ddaaa79c6.png](https://img-blog.csdnimg.cn/img_convert/2d2eddd95962b549e9ee7a7ddaaa79c6.png)
3.边缘光
其实是一个比较常规的需求,但是磨效果磨了很久,大概有试用过这几个方案
- NdotV,缺点是全身周围都有光,而且效果总调不好
- Matcap,使用了这样一张图
![787188eac0944ffca7ca40792387b348.png](https://img-blog.csdnimg.cn/img_convert/787188eac0944ffca7ca40792387b348.png)
基于相机空间的法线去采样这张图,优点是想要什么样的边缘光就可以要什么样的,比如想要一个方向的光就擦掉一半,想要什么颜色就有什么颜色。缺点是要采一次图。
- 再打一个光。当然这样太费了,于是可以在shader里写死一个和主光成某个角度的光,可以模拟背面的轮廓光效果,但缺点也是不太好调。
4.头发
头发其实还是比较常规的做法了,使用了Kajiya-Kay 的光照模型,然后加了个ramp(ramp大法好),然后再把高光搞硬点儿,风格化头发就出来了。
![a276597846e18f0ccda40dafbf46b101.png](https://img-blog.csdnimg.cn/img_convert/a276597846e18f0ccda40dafbf46b101.png)
最后总结一下,卡通渲染就是这样充满trick的快乐。只要它看起来对,那就是对的。
当然,快乐完之后现在还是要乖乖滚回去做写实的东西,物理正确也是有物理正确的浪漫的。
最后悄悄问一句,有没有人想来杭州做游戏,让我混点内推红包吧。