[UnityShader笔记] 卡通Shader

[UnityShader笔记] 卡通Shader

Unity的Standard Assets的Effects下面有个ToonShadering的文件夹专门用来处理卡通Shader。

在这里插入图片描述

ToonBasic

这里我们先看看其中的ToonBasic。首先导入一个Car资源模型

在这里插入图片描述

然后我们用ToonBasic这个Shader替换掉模型中的所有Shader,先看最终的结果:

在这里插入图片描述
右边是使用了ToonBase之后的显示效果,发现卡通的效果还不错。下面我们来研究一下这个Shader的源码。

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"

}

我们查看一下这个Shader的材质球

在这里插入图片描述
发现有三个参数供我们使用

_Color ("Main Color", Color) = (.5,.5,.5,1)
_MainTex ("Base (RGB)", 2D) = "white" {}
_ToonShade ("ToonShader Cubemap(RGB)", CUBE) = "" { }

V&F函数为

			v2f vert (appdata v)
			{
				v2f o;
				//将顶点从模型空间转换到裁剪空间
				o.pos = UnityObjectToClipPos(v.vertex);
				//获取贴图的UV
				o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
				//获取cubemap的法线
				o.cubenormal = mul (UNITY_MATRIX_MV, float4(v.normal,0));
				UNITY_TRANSFER_FOG(o,o.pos);
				return o;
			}

			fixed4 frag (v2f i) : SV_Target
			{
				//获取贴图的UV颜色
				fixed4 col = _Color * tex2D(_MainTex, i.texcoord);
				//获取cubemap的颜色
				fixed4 cube = texCUBE(_ToonShade, i.cubenormal);
				//将cubemap上的颜色*贴图的颜色*2,透明度直接取贴图的alpha
				fixed4 c = fixed4(2.0f * cube.rgb * col.rgb, col.a);
				UNITY_APPLY_FOG(i.fogCoord, c);
				return c;
			}

原理:

ToonBasic主要就是通过cubemap来控制颜色的变化,这里为什么将颜色乘以2。我们改为乘以1来做个测试。

在这里插入图片描述
发现卡车颜色变暗了,说明2用来控制颜色的亮度。

ToonBasicOutline

接下来我们使用ToonBasicOutline这个Shader进行对比

在这里插入图片描述
我们发现ToonBasicOutline就如它的名字一样,和ToonBasic相比多了一个描边效果。同样看一下源码

Shader "Toon/Basic Outline" {
	Properties {
		_Color ("Main Color", Color) = (.5,.5,.5,1)
		_OutlineColor ("Outline Color", Color) = (0,0,0,1)
		_Outline ("Outline width", Range (.002, 0.03)) = .005
		_MainTex ("Base (RGB)", 2D) = "white" { }
		_ToonShade ("ToonShader Cubemap(RGB)", CUBE) = "" { }
	}
	
	CGINCLUDE
	#include "UnityCG.cginc"
	
	struct appdata {
		float4 vertex : POSITION;
		float3 normal : NORMAL;
	};

	struct v2f {
		float4 pos : SV_POSITION;
		UNITY_FOG_COORDS(0)
		fixed4 color : COLOR;
	};
	
	uniform float _Outline;
	uniform float4 _OutlineColor;
	
	v2f vert(appdata v) {
		v2f o;
		o.pos = UnityObjectToClipPos(v.vertex);

		float3 norm   = normalize(mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal));
		float2 offset = TransformViewToProjection(norm.xy);

		#ifdef UNITY_Z_0_FAR_FROM_CLIPSPACE //to handle recent standard asset package on older version of unity (before 5.5)
			o.pos.xy += offset * UNITY_Z_0_FAR_FROM_CLIPSPACE(o.pos.z) * _Outline;
		#else
			o.pos.xy += offset * o.pos.z * _Outline;
		#endif
		o.color = _OutlineColor;
		UNITY_TRANSFER_FOG(o,o.pos);
		return o;
	}
	ENDCG

	SubShader {
		Tags { "RenderType"="Opaque" }
		UsePass "Toon/Basic/BASE"
		Pass {
			Name "OUTLINE"
			Tags { "LightMode" = "Always" }
			Cull Front
			ZWrite On
			ColorMask RGB
			Blend SrcAlpha OneMinusSrcAlpha

			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma multi_compile_fog
			fixed4 frag(v2f i) : SV_Target
			{
				UNITY_APPLY_FOG(i.fogCoord, i.color);
				return i.color;
			}
			ENDCG
		}
	}
	
	Fallback "Toon/Basic"
}

对比发现:ToonBasicOutline相对于ToonBasic增加了一个描边和描边颜色的显示。具体如下:

uniform float _Outline;
	uniform float4 _OutlineColor;
	
	v2f vert(appdata v) {
		v2f o;
		o.pos = UnityObjectToClipPos(v.vertex);

		float3 norm   = normalize(mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal));
		float2 offset = TransformViewToProjection(norm.xy);

		#ifdef UNITY_Z_0_FAR_FROM_CLIPSPACE //to handle recent standard asset package on older version of unity (before 5.5)
			o.pos.xy += offset * UNITY_Z_0_FAR_FROM_CLIPSPACE(o.pos.z) * _Outline;
		#else
			o.pos.xy += offset * o.pos.z * _Outline;
		#endif
		o.color = _OutlineColor;
		UNITY_TRANSFER_FOG(o,o.pos);
		return o;
	}

描边的颜色直接是使用变量_OutlineColor控制,ToonBasicOutline获取边缘位置增加一层偏移即可。

ToonBasicOutline后面的Pass使用的是ToonBasic的Pass代码块。

SubShader {
		Tags { "RenderType"="Opaque" }
		UsePass "Toon/Basic/BASE"

ToonLit

采用同样的方法使用Toonlit批量替换模型的Shader,效果如下:
在这里插入图片描述

ToonLit的Shader源码如下:

Shader "Toon/Lit" {
	Properties {
		_Color ("Main Color", Color) = (0.5,0.5,0.5,1)
		_MainTex ("Base (RGB)", 2D) = "white" {}
		_Ramp ("Toon Ramp (RGB)", 2D) = "gray" {} 
	}

	SubShader {
		Tags { "RenderType"="Opaque" }
		LOD 200
		
CGPROGRAM
#pragma surface surf ToonRamp

sampler2D _Ramp;

// custom lighting function that uses a texture ramp based
// on angle between light direction and normal
#pragma lighting ToonRamp exclude_path:prepass
inline half4 LightingToonRamp (SurfaceOutput s, half3 lightDir, half atten)
{
	#ifndef USING_DIRECTIONAL_LIGHT
	lightDir = normalize(lightDir);
	#endif
	
	half d = dot (s.Normal, lightDir)*0.5 + 0.5;
	half3 ramp = tex2D (_Ramp, float2(d,d)).rgb;
	
	half4 c;
	c.rgb = s.Albedo * _LightColor0.rgb * ramp * (atten * 2);
	c.a = 0;
	return c;
}


sampler2D _MainTex;
float4 _Color;

struct Input {
	float2 uv_MainTex : TEXCOORD0;
};

void surf (Input IN, inout SurfaceOutput o) {
	half4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
	o.Albedo = c.rgb;
	o.Alpha = c.a;
}
ENDCG

	} 

	Fallback "Diffuse"
}

ToonLitOutline

ToonLitOutline是ToonLit的基础上增加了描边的显示

Shader "Toon/Lit Outline" {
	Properties {
		_Color ("Main Color", Color) = (0.5,0.5,0.5,1)
		_OutlineColor ("Outline Color", Color) = (0,0,0,1)
		_Outline ("Outline width", Range (.002, 0.03)) = .005
		_MainTex ("Base (RGB)", 2D) = "white" {}
		_Ramp ("Toon Ramp (RGB)", 2D) = "gray" {} 
	}

	SubShader {
		Tags { "RenderType"="Opaque" }
		UsePass "Toon/Lit/FORWARD"
		UsePass "Toon/Basic Outline/OUTLINE"
	} 
	
	Fallback "Toon/Lit"
}

里面的两个pass分别使用ToonLit的Forward和ToonBasic的OUTLINE

效果如下:

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值