[Unity] Amplify Shader EditorでMatCapシェーダーを作る

#概要
前回、Shader Forgeを使用してMatCapシェーダーを作成した。
http://qiita.com/akerusoft/items/d58416d608cb3c76c153

しかしピクセルシェーダー内の処理が少し重く感じたので
同じノードベースシェーダーエディターのASEを使用してMatCapシェーダーを作成し違いがあるのか確認する。

#環境
Unity 5.5.2p4
Amplify Shader Editor v1.2.1 dev 01
(バージョンをどこでみればいいかわからなかったのでChangeLogより)

#実装内容
前回同様にFree MatCap ShadersのアセットをMatCapの基準とする。
https://www.assetstore.unity3d.com/jp/#!/content/8221

このアセットの「MatCap/Vertex/Plain」と同じ見た目になるように実装する。

実装内容

![image.png](https://qiita-image-store.s3.amazonaws.com/0/36154/788dcb8c-11b8-1674-9ded-ac02f3794ba4.png)

処理内容はShader Forgeと同じ。

#実行結果

![image.png](https://qiita-image-store.s3.amazonaws.com/0/36154/e3cc375b-2277-7bb8-e381-934069b7a7b1.png)

左から「MatCap/Vertex/Plain」のもの、Shader ForgeでのMatCapシェーダー、ASEでのMatCapシェーダー。

自動生成されたコード

```glsl
Shader "ASEMatCap"
{
	Properties
	{
		[HideInInspector] __dirty( "", Int ) = 1
		_MatCap("MatCap", 2D) = "white" {}
	}

	SubShader
	{
		Tags{ "RenderType" = "Opaque"  "Queue" = "Geometry+0" "IsEmissive" = "true"  }
		Cull Back
		CGINCLUDE
		#include "UnityShaderVariables.cginc"
		#include "UnityPBSLighting.cginc"
		#include "Lighting.cginc"
		#pragma target 2.0
		#ifdef UNITY_PASS_SHADOWCASTER
			#undef INTERNAL_DATA
			#undef WorldReflectionVector
			#undef WorldNormalVector
			#define INTERNAL_DATA half3 internalSurfaceTtoW0; half3 internalSurfaceTtoW1; half3 internalSurfaceTtoW2;
			#define WorldReflectionVector(data,normal) reflect (data.worldRefl, half3(dot(data.internalSurfaceTtoW0,normal), dot(data.internalSurfaceTtoW1,normal), dot(data.internalSurfaceTtoW2,normal)))
			#define WorldNormalVector(data,normal) fixed3(dot(data.internalSurfaceTtoW0,normal), dot(data.internalSurfaceTtoW1,normal), dot(data.internalSurfaceTtoW2,normal))
		#endif
		struct Input
		{
			float3 worldNormal;
		};

		uniform sampler2D _MatCap;

		void surf( Input i , inout SurfaceOutputStandard o )
		{
			float2 componentMask6 = mul( UNITY_MATRIX_V , float4( i.worldNormal , 0.0 ) ).xy;
			o.Emission = tex2D( _MatCap, ( 0.5 + ( 0.5 * componentMask6 ) ) ).rgb;
			o.Alpha = 1;
		}

		ENDCG
		CGPROGRAM
		#pragma surface surf Standard keepalpha fullforwardshadows exclude_path:deferred 

		ENDCG
		Pass
		{
			Name "ShadowCaster"
			Tags{ "LightMode" = "ShadowCaster" }
			ZWrite On
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma target 3.0
			#pragma multi_compile_shadowcaster
			#pragma multi_compile UNITY_PASS_SHADOWCASTER
			#pragma skip_variants FOG_LINEAR FOG_EXP FOG_EXP2
			# include "HLSLSupport.cginc"
			#if ( SHADER_API_D3D11 || SHADER_API_GLCORE || SHADER_API_GLES3 || SHADER_API_METAL || SHADER_API_VULKAN )
				#define CAN_SKIP_VPOS
			#endif
			#include "UnityCG.cginc"
			#include "Lighting.cginc"
			#include "UnityPBSLighting.cginc"
			sampler3D _DitherMaskLOD;
			struct v2f
			{
				V2F_SHADOW_CASTER;
				float3 worldPos : TEXCOORD6;
				float4 tSpace0 : TEXCOORD1;
				float4 tSpace1 : TEXCOORD2;
				float4 tSpace2 : TEXCOORD3;
				UNITY_VERTEX_INPUT_INSTANCE_ID
			};
			v2f vert( appdata_full v )
			{
				v2f o;
				UNITY_SETUP_INSTANCE_ID( v );
				UNITY_INITIALIZE_OUTPUT( v2f, o );
				UNITY_TRANSFER_INSTANCE_ID( v, o );
				float3 worldPos = mul( unity_ObjectToWorld, v.vertex ).xyz;
				half3 worldNormal = UnityObjectToWorldNormal( v.normal );
				o.worldPos = worldPos;
				TRANSFER_SHADOW_CASTER_NORMALOFFSET( o )
				return o;
			}
			fixed4 frag( v2f IN
			#if !defined( CAN_SKIP_VPOS )
			, UNITY_VPOS_TYPE vpos : VPOS
			#endif
			) : SV_Target
			{
				UNITY_SETUP_INSTANCE_ID( IN );
				Input surfIN;
				UNITY_INITIALIZE_OUTPUT( Input, surfIN );
				float3 worldPos = IN.worldPos;
				fixed3 worldViewDir = normalize( UnityWorldSpaceViewDir( worldPos ) );
				surfIN.worldNormal = float3( IN.tSpace0.z, IN.tSpace1.z, IN.tSpace2.z );
				SurfaceOutputStandard o;
				UNITY_INITIALIZE_OUTPUT( SurfaceOutputStandard, o )
				surf( surfIN, o );
				#if defined( CAN_SKIP_VPOS )
				float2 vpos = IN.pos;
				#endif
				SHADOW_CASTER_FRAGMENT( IN )
			}
			ENDCG
		}
	}
	Fallback "Diffuse"
	CustomEditor "ASEMaterialInspector"
}
```

ピクセルシェーダー内からサーフェースシェーダー関数を呼んでいるので結果として
Shader Forgeと同じでピクセルシェーダー内で計算処理してますね。

早いシェーダーを書きたいなら手書きで書け、ということでしょうか。


#感想
Shader Forgeになれているので、ASEの操作感はいまいち。
細かい設定はASEの方ができる感じがしてますが、どっちがどうなんでしょうね？