Unity自带卡通shader(toon shader)分析
发表于2018-04-17
Unity Standard Assets中自带4个卡通相关的shader,可以通过导入Effects Package导入:





然后我们可以在Assets->Standard Assets/Effects/ToonShading/Shaders中找到这四个shader

首先来看一下ToonBasic这个shader,我从asset store上下载了一个名叫Tiger的免费模型,下面就用这个模型来做实验。下图是刚放进场景的prefab:

然后我们使用ToonBasic替换Tiger身上的原材质,效果如下:

可以发现,ToonBasic并没有描边,但是模型的色彩产生了明显的变化,色块之间的边界更为明显了。
ToonBasic的代码如下所示:
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Toon/Basic" { Properties { _Color ("Main Color", Color) = (.5,.5,.5,1) _MainTex ("Base (RGB)", 2D) = "white" {} _ToonShade ("ToonShader Cubemap(RGB)", CUBE) = "" { } } SubShader { Tags { "RenderType"="Opaque" } Pass { Name "BASE" Cull Off CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma multi_compile_fog #include "UnityCG.cginc" sampler2D _MainTex; samplerCUBE _ToonShade; float4 _MainTex_ST; float4 _Color; struct appdata { float4 vertex : POSITION; float2 texcoord : TEXCOORD0; float3 normal : NORMAL; }; struct v2f { float4 pos : SV_POSITION; float2 texcoord : TEXCOORD0; float3 cubenormal : TEXCOORD1; UNITY_FOG_COORDS(2) }; v2f vert (appdata v) { v2f o; o.pos = UnityObjectToClipPos (v.vertex); o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex); o.cubenormal = mul (UNITY_MATRIX_MV, float4(v.normal,0)); UNITY_TRANSFER_FOG(o,o.pos); return o; } fixed4 frag (v2f i) : SV_Target { fixed4 col = _Color * tex2D(_MainTex, i.texcoord); fixed4 cube = texCUBE(_ToonShade, i.cubenormal); fixed4 c = fixed4(2.0f * cube.rgb * col.rgb, col.a); UNITY_APPLY_FOG(i.fogCoord, c); return c; } ENDCG } } Fallback "VertexLit" }
在这里先忽略雾效相关代码,我们发现,该材质需要两个贴图,一张老虎原来的贴图和一张控制色彩变化的cubemap贴图,分别对应
_MainTex ("Base (RGB)", 2D) = "white" {} _ToonShade ("ToonShader Cubemap(RGB)", CUBE) = "" { }:

然后让我们来看一下顶点函数:
v2f vert (appdata v) { v2f o; o.pos = UnityObjectToClipPos (v.vertex); -- 将顶点从模型空间转化到裁剪空间 o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex); -- 获取贴图uv o.cubenormal = mul (UNITY_MATRIX_MV, float4(v.normal,0)); -- 获取控制toon的cubemap的法线 UNITY_TRANSFER_FOG(o,o.pos); return o; }
然后是片元函数:
fixed4 frag (v2f i) : SV_Target { fixed4 col = _Color * tex2D(_MainTex, i.texcoord); -- 获取2D贴图上对应uv处的颜色 fixed4 cube = texCUBE(_ToonShade, i.cubenormal); -- 获取cubemap上对应的颜色(控制颜色块) fixed4 c = fixed4(2.0f * cube.rgb * col.rgb, col.a); -- 用2倍的toon控制色乘上源颜色 UNITY_APPLY_FOG(i.fogCoord, c); return c; }
可以得出结论,ToonBasic的原理其实就是用一个cubemap来控制色彩边界的变化,使色彩块之间有明显的界限。
来自:https://blog.csdn.net/rickshaozhiheng/article/details/73442369