前言
卡通渲染是[[非真实感渲染(Non-Photorealistic Rendering)]]的一个常见分支,这一渲染风格的目的是把最终渲染结果表现的如同动画(Cartoon)一样。
值得注意的是,如果想要把握好卡通渲染,应当对于真实的物理世界有着充足的了解,因为动画这一形式本身就是一种对于真实世界的简化,并通过简化次要细节这一手段突出表达作者的想要着重表达的物体,细节乃至情感。
卡通渲染的常见渲染技巧综述
为了实现卡通风格的渲染风格,需要实现一些特殊的trick。这里列出一些本人知道的卡通渲染技巧,做一次概述。本文暴论频出,如果错漏欢迎指正。(如无特殊指明,均为日式卡通风格)
明暗调子
明暗调子是一个美术上的概念,有二分调,三分调,五分调等类型,相较于真实的光影带来的细腻柔和的物理变化,卡通渲染会更偏向于大色块和明显的分界线。通常来说,会使用阈值的方法实现,即NdotL > _Threshold ? LightColor : DarkColor 这样的形式,但是当美术希望使用例如五调子的渲染形式时,便会导致频繁的阈值比较。
窗函数控制法
我们对NdotL项进行偏移后相减,可以得到一个窗函数。这个窗函数只会在指定部分为正,其余部分均为0,可以用这种方法控制在不同的光照区域下显示不同的颜色。不过这套思想的实现比较吃美术经验,需要美术或TA确定一组偏移值。
Ramp
俗话说得好,实时渲染就是一个巨大的打表()。遇事不决打张表出来就行了,直接让美术绘制一张Ramp(渐变)纹理。根据NdotL决定采样位置,就可以实现柔和的光照渐变。还可以将多张Ramp合并为一张纹理,比如原神的Ramp就是四合一,根据白天黑夜进行不同位置的采样。
细节贴图
由于我们美术资产最终产生的是低模,缺乏足够的几何细节,可以考虑在烘焙时额外烤一张细节贴图出来,只需要单通道的明暗关系,类似于AO贴图。
描边
外描边
平滑法线挤出
一个模型渲染两次,第一次正面渲染,背面剔除。第二次就是描边Pass,正面剔除,将整个模型依照法线方向挤出,然后渲染为黑色(或其他指定颜色)。这套算法需要预计算平滑法线,因为模型自带的顶点法线是面朝向的,我们使用的平滑法线需要把顶点所在各个面法线加权得出来。最好再向摄像机朝向方向偏移一下,不然部分位置会有很丑陋的描边(嘴角)。想要不同的描边宽度可以刷顶点色控制。
基于深度偏移效果
在后处理Pass向外偏移,比较两次深度的差值,过大则认为是边缘。
内描边
绘制纹理
直接画在纹理上何尝不是一张好方法(,不过这套方法会出现锯齿感,所以为了解决这个问题就有了2015年的本村线做法,但是这个方法非常耗美术,需要艺术家打直纹理里的边缘的UV。
材质检测
不同材质相交的边缘可以通过绘制一次材质ID后跑一个Sobel算子进行计算。
后处理
通过法线的跳变检测内边缘。依旧通过后处理跑边缘检测实现。
头发
基于面片的毛发 基于体块的毛发
本人好像没见过面片毛发,基本都是写实项目用。好处是天然具有一套合适的UV来扰动。基于体块的头发,其实就是一个模型,走正常的渲染就可以。
拆刘海
做眼透的时候可以把刘海拆成一个单独mesh去做模板测试。
高光
黑话应该叫天使环。个人拙见,头发用Kajiya-Kay高光基本就可以了,不需要写实的细节而去用物理模型(,而且KK高光也可以做多层,之前看BenClowad的Unity官方示例里有介绍。
当然也有直接画一张高光贴图的,用来做特殊形状的高光很有用。
刘海投影
有两种,一种是把刘海整个mesh沿着光源方向偏移,然后和脸相交的部分就是投影。还有一种是直接插片,终末地的模型就是这个做法。
面部
面部是整个人物的一个特殊部分,因为卡通角色的面部通常是被特殊处理的,不同于真实物理世界的模样。比如伦勃朗光,真实世界只需要正常渲染就可以出现三角区域,二次元的鼻子是经过简化的,这可能需要一些日本卡通作画画风的变化的历史课,这里推荐一个视频: 二次元风格怎么演变来的?你的画风属于哪个阶段?|画风演变史-二次元-总集篇 。
阴影
SDF/阈值图
由米哈游在2018年提出,通过一张贴图,描述脸部的阴影的变化,可以理解脸部采样点的NdotL距离阴影的距离或者说阴影阈值,可以由美术绘制多角度阴影后合成。目前常见方案不支持光源的上下方向的变化。
掰法线
用一个圆柱体/球去代理整个脸部的阴影,将圆柱体/球的法线映射到脸部,也可以形成大色块的阴影效果。
眼部
眉影
即眼部上半会暗一些的效果,我所知道的方法是用一个插片,然后开启半透明渲染混合暗色。
眼透
- 模板测试,通过不同stencil值比较,然后replace。不过要注意要加深度限制,某些特殊角度渲染出来眼睛还是很诡异的(
- 深度偏移,通过更改深度通过ZTest以渲染眼睛覆盖头发的效果。
瞳
- 视差实现眼部折射
- 做两层mesh来渲染
表情
- 基于形态键,可以做各类效果,但是要额外存多个mesh
- 基于骨骼蒙皮,可以做涉及运动的表情
服饰
双面渲染
开Cull Off,检测是否为背面并反转法线。
基于PBR的效果
一般来说,卡通渲染不适合表示金属材质。一般会直接用PBR,给一个很低的系数。就我所知道的,原神就已经有了金属表现了。之前在知乎看技术分享的时候,也看到了战双也有一些PBR的效果。
一些其他杂七杂八的
边缘光
想了半天不知道放哪块干脆放这里了,也是用深度偏移,或者直接VdotN检测边缘。
顶点偏移表示速度线
很常见,但是我没做过,UE有相关的插件,可以去看实现。
逆tonemapping
场景需要tonemapping,人物不可以有tonemmaping(怕发灰),可以在最后算一个tonemapping反函数。
角色阴影
- 高精度角色阴影需要单独开一个摄像机来算
- 用圆柱体投射到地面也可以基本表示一个接触效果,至少不显得飘。
模型矫正
- 基于不同的FOV要矫正
- 动画演出时把骨骼偏移可以给出来更好的效果
- 形变不同部位获得画面冲击感和强调
柔光
可以专门对角色做的一个低阈值低强度的Bloom。人物在场景里看起来不会那么硬。
场景
- 场景太物理,纹理高频细节太多。可以做一次卷积,有一个专门的方法,名字忘了。
- 后处理也有一些卡通化的滤镜,比如桑原滤镜。
- 世界坐标取frac然后当成UV去画SDF,可以出来类似于漫画里的那些波点风格。详情见Hifi-Rush的GDC,我也写过笔记。
- 光源可以在某个角度截断,给出来一个硬边,给聚光灯用。