当前位置:   article > 正文

[UnityShader笔记] 卡通Shader_toonbasicoutline

toonbasicoutline

[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"

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63

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

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

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

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;
			}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

原理:

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"
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70

对比发现: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;
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

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

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

SubShader {
		Tags { "RenderType"="Opaque" }
		UsePass "Toon/Basic/BASE"
  • 1
  • 2
  • 3

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"
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

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"
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

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

效果如下:

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/107714
推荐阅读
相关标签
  

闽ICP备14008679号