一直对卡通渲染非常感兴趣,前后翻找了不少的文档,做了一些工作。前段时间《从零开始》的手游上线了,试着渲染了一下的其中模型,觉得效果很不错。打算写一个专栏记录其中的渲染技术。在后面的篇章中也想展示一下各个项目中卡通渲染技术的变迁,以及讨论未来的一些发展方向。
卡通渲染属于非真实感渲染(Non-photorealistic rendering,简称NPR)。对应的还有真实感渲染(Photorealistic rendering)。后者旨在渲染真实感的画面,而前者则追求更加有艺术感的画面效果,例如手绘风格的画面。
NPR也有各种各样的类型。比如像油画,铅笔画,水墨画风格的画面。这里主要探讨像日本动画那样的卡通渲染风格,目前一般称之为Cel Shading。卡通渲染在日本那边很早就在主机游戏上使用,经过了很多尝试和变迁,最终在《GUILTY GEAR Xrd》系列游戏达到了非常不错的水准。国内的厂商在吸收了日本同行的经验以后,也制作了非常好的作品,并且在此之上创新,提出了更多的解决方案。
说了很多,现在回归正题。描边是卡通渲染的一个非常重要的主题。目前比较流行的描边方法有两种,一个是通过两次绘制,一次绘制角色,一次绘制描边。还有一种是基于后处理的描边。基于后处理的描边相对不容易定制,比较适用于对复杂场景进行描边。这里讲述通过2次绘制来绘制描边的方法。在《GUILTY GEAR Xrd》中称其为Back Facing法。
Back facing描边法
基本思路是通过两次绘制,第一次绘制角色,第二次绘制描边。绘制描边的时候,在顶点着色器将顶点沿着法线方向位移一段距离,使得模型轮廓放大,渲染作为描边。同时描边绘制时使用cull front。这样描边和角色重叠的部分会因为不能通过深度检测而cull掉,保证描边不会遮挡角色。两次绘制颠倒顺序也是可以的,不过后绘制描边,可以通过深度检测过滤掉很多描边绘制的像素,效率会更好。这里先实现最简单的方法,然后逐步进行优化。
Shader "Unlit/Ouline"
{
Properties
{
_OutlineWidth ("Outline Width", Range(0.01, 1)) = 0.24
_OutLineColor ("OutLine Color", Color) = (0.5,0.5,0.5,1)
}
SubShader
{
Tags { "RenderType"="Opaque" }
pass
{
Tags {"LightMode"="ForwardBase"}
Cull Back
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
float4 vert(appdata_base v): SV_POSITION
{
return UnityObjectToClipPos(v.vertex);
}
half4 frag() : SV_TARGET
{
return half4(1,1,1,1);
}
ENDCG
}
Pass
{
Tags {"LightMode"="ForwardBase"}
Cull Front
CGPROGRAM
#pragma vertex vert
#pragma fragment frag