204 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
		
		
			
		
	
	
			204 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| 
								 | 
							
								## ToonShader
							 | 
						|||
| 
								 | 
							
								书中案例使用了2个Pass来实现效果。
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								### OutlinePass
							 | 
						|||
| 
								 | 
							
								模型外面边
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								Pass {
							 | 
						|||
| 
								 | 
							
										NAME "OUTLINE"
							 | 
						|||
| 
								 | 
							
										
							 | 
						|||
| 
								 | 
							
										Cull Front
							 | 
						|||
| 
								 | 
							
										
							 | 
						|||
| 
								 | 
							
										CGPROGRAM
							 | 
						|||
| 
								 | 
							
										
							 | 
						|||
| 
								 | 
							
										#pragma vertex vert
							 | 
						|||
| 
								 | 
							
										#pragma fragment frag
							 | 
						|||
| 
								 | 
							
										
							 | 
						|||
| 
								 | 
							
										#include "UnityCG.cginc"
							 | 
						|||
| 
								 | 
							
										
							 | 
						|||
| 
								 | 
							
										float _Outline;
							 | 
						|||
| 
								 | 
							
										fixed4 _OutlineColor;
							 | 
						|||
| 
								 | 
							
										
							 | 
						|||
| 
								 | 
							
										struct a2v {
							 | 
						|||
| 
								 | 
							
											float4 vertex : POSITION;
							 | 
						|||
| 
								 | 
							
											float3 normal : NORMAL;
							 | 
						|||
| 
								 | 
							
										}; 
							 | 
						|||
| 
								 | 
							
										
							 | 
						|||
| 
								 | 
							
										struct v2f {
							 | 
						|||
| 
								 | 
							
										    float4 pos : SV_POSITION;
							 | 
						|||
| 
								 | 
							
										};
							 | 
						|||
| 
								 | 
							
										
							 | 
						|||
| 
								 | 
							
										v2f vert (a2v v) {
							 | 
						|||
| 
								 | 
							
											v2f o;
							 | 
						|||
| 
								 | 
							
											
							 | 
						|||
| 
								 | 
							
											float4 pos = mul(UNITY_MATRIX_MV, v.vertex); 
							 | 
						|||
| 
								 | 
							
											//IT_MV rotates normals from object to eye space
							 | 
						|||
| 
								 | 
							
											float3 normal = mul((float3x3)UNITY_MATRIX_IT_MV, v.normal);  
							 | 
						|||
| 
								 | 
							
											normal.z = -0.5;
							 | 
						|||
| 
								 | 
							
											pos = pos + float4(normalize(normal), 0) * _Outline;
							 | 
						|||
| 
								 | 
							
											o.pos = mul(UNITY_MATRIX_P, pos);
							 | 
						|||
| 
								 | 
							
											
							 | 
						|||
| 
								 | 
							
											return o;
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										
							 | 
						|||
| 
								 | 
							
										float4 frag(v2f i) : SV_Target { 
							 | 
						|||
| 
								 | 
							
											return float4(_OutlineColor.rgb, 1);               
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										
							 | 
						|||
| 
								 | 
							
										ENDCG
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								### ToonShader
							 | 
						|||
| 
								 | 
							
								颜色计算:
							 | 
						|||
| 
								 | 
							
								`Ramp颜色=tex2D(_Ramp, float2(dot(worldNormal, worldLightDir))).rgb`
							 | 
						|||
| 
								 | 
							
								`diffuse=贴图颜色*指定颜色*灯光颜色*(Ramp贴图)`
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								fixed4 c = tex2D (_MainTex, i.uv);
							 | 
						|||
| 
								 | 
							
								fixed3 albedo = c.rgb * _Color.rgb;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								fixed diff =  ;
							 | 
						|||
| 
								 | 
							
								diff = (diff * 0.5 + 0.5) * atten;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								fixed3 diffuse = _LightColor0.rgb * albedo * tex2D(_Ramp, float2(diff, diff)).rgb;
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								高光计算:
							 | 
						|||
| 
								 | 
							
								使用fwidth与smooth主要是用于抗锯齿。https://blog.csdn.net/candycat1992/article/details/44673819
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								fixed spec = dot(worldNormal, worldHalfDir);
							 | 
						|||
| 
								 | 
							
								fixed w = fwidth(spec) * 2.0;
							 | 
						|||
| 
								 | 
							
								fixed3 specular = _Specular.rgb * lerp(0, 1, smoothstep(-w, w, spec + _SpecularScale - 1)) * step(0.0001, _SpecularScale);
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								Pass代码
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								Pass {
							 | 
						|||
| 
								 | 
							
										Tags { "LightMode"="ForwardBase" }
							 | 
						|||
| 
								 | 
							
										
							 | 
						|||
| 
								 | 
							
										Cull Back
							 | 
						|||
| 
								 | 
							
									
							 | 
						|||
| 
								 | 
							
										CGPROGRAM
							 | 
						|||
| 
								 | 
							
									
							 | 
						|||
| 
								 | 
							
										#pragma vertex vert
							 | 
						|||
| 
								 | 
							
										#pragma fragment frag
							 | 
						|||
| 
								 | 
							
										
							 | 
						|||
| 
								 | 
							
										#pragma multi_compile_fwdbase
							 | 
						|||
| 
								 | 
							
									
							 | 
						|||
| 
								 | 
							
										#include "UnityCG.cginc"
							 | 
						|||
| 
								 | 
							
										#include "Lighting.cginc"
							 | 
						|||
| 
								 | 
							
										#include "AutoLight.cginc"
							 | 
						|||
| 
								 | 
							
										#include "UnityShaderVariables.cginc"
							 | 
						|||
| 
								 | 
							
										
							 | 
						|||
| 
								 | 
							
										fixed4 _Color;
							 | 
						|||
| 
								 | 
							
										sampler2D _MainTex;
							 | 
						|||
| 
								 | 
							
										float4 _MainTex_ST;
							 | 
						|||
| 
								 | 
							
										sampler2D _Ramp;
							 | 
						|||
| 
								 | 
							
										fixed4 _Specular;
							 | 
						|||
| 
								 | 
							
										fixed _SpecularScale;
							 | 
						|||
| 
								 | 
							
									
							 | 
						|||
| 
								 | 
							
										struct a2v {
							 | 
						|||
| 
								 | 
							
											float4 vertex : POSITION;
							 | 
						|||
| 
								 | 
							
											float3 normal : NORMAL;
							 | 
						|||
| 
								 | 
							
											float4 texcoord : TEXCOORD0;
							 | 
						|||
| 
								 | 
							
											float4 tangent : TANGENT;
							 | 
						|||
| 
								 | 
							
										}; 
							 | 
						|||
| 
								 | 
							
									
							 | 
						|||
| 
								 | 
							
										struct v2f {
							 | 
						|||
| 
								 | 
							
											float4 pos : POSITION;
							 | 
						|||
| 
								 | 
							
											float2 uv : TEXCOORD0;
							 | 
						|||
| 
								 | 
							
											float3 worldNormal : TEXCOORD1;
							 | 
						|||
| 
								 | 
							
											float3 worldPos : TEXCOORD2;
							 | 
						|||
| 
								 | 
							
											SHADOW_COORDS(3)
							 | 
						|||
| 
								 | 
							
										};
							 | 
						|||
| 
								 | 
							
										
							 | 
						|||
| 
								 | 
							
										v2f vert (a2v v) {
							 | 
						|||
| 
								 | 
							
											v2f o;
							 | 
						|||
| 
								 | 
							
											
							 | 
						|||
| 
								 | 
							
											o.pos = mul( UNITY_MATRIX_MVP, v.vertex);
							 | 
						|||
| 
								 | 
							
											o.uv = TRANSFORM_TEX (v.texcoord, _MainTex);
							 | 
						|||
| 
								 | 
							
											o.worldNormal  = UnityObjectToWorldNormal(v.normal);
							 | 
						|||
| 
								 | 
							
											o.worldPos = mul(_Object2World, v.vertex).xyz;
							 | 
						|||
| 
								 | 
							
											
							 | 
						|||
| 
								 | 
							
											TRANSFER_SHADOW(o);
							 | 
						|||
| 
								 | 
							
											
							 | 
						|||
| 
								 | 
							
											return o;
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										
							 | 
						|||
| 
								 | 
							
										float4 frag(v2f i) : SV_Target { 
							 | 
						|||
| 
								 | 
							
											fixed3 worldNormal = normalize(i.worldNormal);
							 | 
						|||
| 
								 | 
							
											fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
							 | 
						|||
| 
								 | 
							
											fixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
							 | 
						|||
| 
								 | 
							
											fixed3 worldHalfDir = normalize(worldLightDir + worldViewDir);
							 | 
						|||
| 
								 | 
							
											
							 | 
						|||
| 
								 | 
							
											fixed4 c = tex2D (_MainTex, i.uv);
							 | 
						|||
| 
								 | 
							
											fixed3 albedo = c.rgb * _Color.rgb;
							 | 
						|||
| 
								 | 
							
											
							 | 
						|||
| 
								 | 
							
											fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
							 | 
						|||
| 
								 | 
							
											
							 | 
						|||
| 
								 | 
							
											UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
							 | 
						|||
| 
								 | 
							
											
							 | 
						|||
| 
								 | 
							
											fixed diff =  dot(worldNormal, worldLightDir);
							 | 
						|||
| 
								 | 
							
											diff = (diff * 0.5 + 0.5) * atten;
							 | 
						|||
| 
								 | 
							
											
							 | 
						|||
| 
								 | 
							
											fixed3 diffuse = _LightColor0.rgb * albedo * tex2D(_Ramp, float2(diff, diff)).rgb;
							 | 
						|||
| 
								 | 
							
											
							 | 
						|||
| 
								 | 
							
											fixed spec = dot(worldNormal, worldHalfDir);
							 | 
						|||
| 
								 | 
							
											fixed w = fwidth(spec) * 2.0;
							 | 
						|||
| 
								 | 
							
											fixed3 specular = _Specular.rgb * lerp(0, 1, smoothstep(-w, w, spec + _SpecularScale - 1)) * step(0.0001, _SpecularScale);
							 | 
						|||
| 
								 | 
							
											
							 | 
						|||
| 
								 | 
							
											return fixed4(ambient + diffuse + specular, 1.0);
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
									
							 | 
						|||
| 
								 | 
							
										ENDCG
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								### 素描风格
							 | 
						|||
| 
								 | 
							
								通过`hatchFactor=max(0,dot(worldLightDir,worldNormal))*7`获取因子。之后计算各个图层的混合因子:
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								if (hatchFactor > 6.0) {
							 | 
						|||
| 
								 | 
							
									// Pure white, do nothing
							 | 
						|||
| 
								 | 
							
								} else if (hatchFactor > 5.0) {
							 | 
						|||
| 
								 | 
							
									o.hatchWeights0.x = hatchFactor - 5.0;
							 | 
						|||
| 
								 | 
							
								} else if (hatchFactor > 4.0) {
							 | 
						|||
| 
								 | 
							
									o.hatchWeights0.x = hatchFactor - 4.0;
							 | 
						|||
| 
								 | 
							
									o.hatchWeights0.y = 1.0 - o.hatchWeights0.x;
							 | 
						|||
| 
								 | 
							
								} else if (hatchFactor > 3.0) {
							 | 
						|||
| 
								 | 
							
									o.hatchWeights0.y = hatchFactor - 3.0;
							 | 
						|||
| 
								 | 
							
									o.hatchWeights0.z = 1.0 - o.hatchWeights0.y;
							 | 
						|||
| 
								 | 
							
								} else if (hatchFactor > 2.0) {
							 | 
						|||
| 
								 | 
							
									o.hatchWeights0.z = hatchFactor - 2.0;
							 | 
						|||
| 
								 | 
							
									o.hatchWeights1.x = 1.0 - o.hatchWeights0.z;
							 | 
						|||
| 
								 | 
							
								} else if (hatchFactor > 1.0) {
							 | 
						|||
| 
								 | 
							
									o.hatchWeights1.x = hatchFactor - 1.0;
							 | 
						|||
| 
								 | 
							
									o.hatchWeights1.y = 1.0 - o.hatchWeights1.x;
							 | 
						|||
| 
								 | 
							
								} else {
							 | 
						|||
| 
								 | 
							
									o.hatchWeights1.y = hatchFactor;
							 | 
						|||
| 
								 | 
							
									o.hatchWeights1.z = 1.0 - o.hatchWeights1.y;
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								之后在片元着色器中将因子与6张素描贴图的采样结果相乘以及计算白色区域光照,最后相加:
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								fixed4 hatchTex0 = tex2D(_Hatch0, i.uv) * i.hatchWeights0.x;
							 | 
						|||
| 
								 | 
							
								fixed4 hatchTex1 = tex2D(_Hatch1, i.uv) * i.hatchWeights0.y;
							 | 
						|||
| 
								 | 
							
								fixed4 hatchTex2 = tex2D(_Hatch2, i.uv) * i.hatchWeights0.z;
							 | 
						|||
| 
								 | 
							
								fixed4 hatchTex3 = tex2D(_Hatch3, i.uv) * i.hatchWeights1.x;
							 | 
						|||
| 
								 | 
							
								fixed4 hatchTex4 = tex2D(_Hatch4, i.uv) * i.hatchWeights1.y;
							 | 
						|||
| 
								 | 
							
								fixed4 hatchTex5 = tex2D(_Hatch5, i.uv) * i.hatchWeights1.z;
							 | 
						|||
| 
								 | 
							
								fixed4 whiteColor = fixed4(1, 1, 1, 1) * (1 - i.hatchWeights0.x - i.hatchWeights0.y - i.hatchWeights0.z - 
							 | 
						|||
| 
								 | 
							
											i.hatchWeights1.x - i.hatchWeights1.y - i.hatchWeights1.z);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								fixed4 hatchColor = hatchTex0 + hatchTex1 + hatchTex2 + hatchTex3 + hatchTex4 + hatchTex5 + whiteColor;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
							 | 
						|||
| 
								 | 
							
												
							 | 
						|||
| 
								 | 
							
								return fixed4(hatchColor.rgb * _Color.rgb * atten, 1.0);
							 | 
						|||
| 
								 | 
							
								```
							 |