继续来研究卡通渲染,上一篇已经了解卡通渲染两个核心了,比较重要的point就是“具有艺术风格的光线渲染算法”,上次我们直接使用的diffuse去计算光照,严格来说不算“艺术风格”,这里就来介绍一个学术界推崇的卡通渲染光线计算:Cel-shading,首先贴上维基百科cel-shading
cel-shading的核心思想:Cel-shading is often used to mimic the style of a comic book or cartoon and/or give it a characteristic paper-like texture
那么怎么处理cel-shading呢?如下:
Cel Shading is a style of computer rendering that replaces the shading gradient of conventional rendering with flat colors and shadows (as seen at right)
上面的意思就是将颜色丰富的渐变色彩变成单调的平面色彩,简单来说操作上就是降低色阶数量,达到一种卡通的光照效果,比如下面的表情包:
可以认为就是白灰双色阶的光照,至于片段光照权重就是用N·L,也就是单位法向量与单位光源朝向向量的点积,得到的权重weight去判断采样白色或者灰色。
当然为了丰富Cel-shading的细节,可以使用多层次渐变的采样贴图,而不是直接去代码赋值颜色,比如维基的贴图,如下:
这时候为了采样uv两个方向上的像素值,使用N·L和N·V两个数值去组建uv采样。
接下来就来写shader实现了,如下:
Shader "Custom/CelShader"
{
Properties
{
_PaletteTex("Pallette Tex",2D) = "white" {}
_PaletteFactor("Pallette Factor",Range(0,2)) = 1
_Extsn("Extsn Value", Range(0,1)) = 1
_OutColor("Outline Color", Color) = (0,0,0,1)
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
struct appdata
{
float4 vertex : POSITION;
float4 normal : NORMAL;
};
struct v2f
{
float4 vertex : SV_POSITION;
float3 worldNormal : TEXCOORD1;
float3 worldP2S : TEXCOORD2;
float3 worldP2V : TEXCOORD3;
};
sampler2D _PaletteTex;
float _PaletteFactor;
v2f vert (appdata v)
{
v2f o;
o.worldNormal = UnityObjectToWorldNormal(v.normal.xyz);
o.worldP2S = normalize(WorldSpaceLightDir(v.vertex));
o.worldP2V = normalize(WorldSpaceViewDir(v.vertex));
o.vertex = UnityObjectToClipPos(v.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
float u = dot(i.worldNormal,i.worldP2S);
float v = dot(i.worldNormal, i.worldP2V);
//采样调色板颜色时顺便*光源颜色
fixed4 celcol = fixed4(tex2D(_PaletteTex, float2(u, v)).rgb*_LightColor0.rgb*_PaletteFactor, 1);
return celcol;
}
ENDCG
}
Pass
{
Cull front
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float4 normal : NORMAL;
};
struct v2f
{
float4 vertex : SV_POSITION;
};
float _Extsn;
float4 _OutColor;
v2f vert(appdata v)
{
v2f o;
v.vertex += v.normal * _Extsn;
o.vertex = UnityObjectToClipPos(v.vertex);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
fixed4 col = _OutColor;
return col;
}
ENDCG
}
}
}
效果图如下:
和普通的standard相比,是不是更加卡通化?Cel-shading可以看得出来,是代码较简洁,运行效率较高的一种卡通风格算法,当然还有其他更复杂效果更好的算法了,后面再聊。