1. 程式人生 > >邊緣檢測效果動畫Shader實現

邊緣檢測效果動畫Shader實現

AR專案中在掃描識別圖時需要加上掃描識別效果,加上邊緣識別後看起來效果更好,所以就需要這樣一個邊緣檢測效果的動畫Shader。
Shader "Unlit/AnimateEdgeShader"
{
	Properties
	{
		_MainTex ("Texture", 2D) = "white" {}
		_EdgeOnly ("Edge Only",Range(0,1)) = 1
		_EdgeColor ("Edge Color",Color) = (1,0,0,1)
		_BackgroundColor ("Background Color",Color) = (1,1,1,1)

		_AnimateTex ("Texture", 2D) = "white" {}
		_ScrollX ("Speed",Float) = 0.5
	}
	SubShader
	{
		Tags { "RenderType"="Opaque" }
		LOD 100
		Blend SrcAlpha OneMinusSrcAlpha

		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			
			#include "UnityCG.cginc"

			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
			};

			struct v2f
			{		
				float4 vertex : SV_POSITION;
				float2 uv : TEXCOORD0;
			};

			sampler2D _MainTex;
			float4 _MainTex_ST;

			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.uv = TRANSFORM_TEX(v.uv, _MainTex);

				return o;
			}

			fixed4 frag (v2f i) : SV_Target
			{
				return tex2D(_MainTex, i.uv);
			}
			ENDCG

		}

		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			
			#include "UnityCG.cginc"

			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
			};

			struct v2f
			{
			
				float4 vertex : SV_POSITION;
				float2 uv[9] : TEXCOORD0;
				
			};

			sampler2D _AnimateTex;
			float4 _AnimateTex_ST;
			float _ScrollX;

			sampler2D _MainTex;
			half4 _MainTex_TexelSize;
			float4 _MainTex_ST;
			fixed _EdgeOnly;
			fixed4 _EdgeColor;
			fixed4 _BackgroundColor;

			fixed luminance(fixed4 color)
			{
				return 0.2125 * color.r + 0.7154 * color.g + 0.0721 * color.b;
			}

			half Sobel(v2f i)
			{
				const half Gx[9] = {
								     -1,-2,-1,
									 0,0,0,
									 1,2,1
								   };

				const half Gy[9] = {
								     -1,0,1,
									 -2,0,2,
									 -1,0,1
								   };

				half texColor;
				half edgeX = 0;
				half edgeY = 0;
				for (int it = 0;it < 9;it++)
				{
					texColor = luminance(tex2D(_MainTex,i.uv[it]));
					edgeX += texColor * Gx[it];
					edgeY += texColor * Gy[it];
				}

				half edge = 1 - abs(edgeX) - abs(edgeY);

				return edge;
			}
			
			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				
				o.uv[0] = v.uv + _MainTex_TexelSize.xy * half2(-1,-1);
				o.uv[1] = v.uv + _MainTex_TexelSize.xy * half2(0,-1);
				o.uv[2] = v.uv + _MainTex_TexelSize.xy * half2(1,-1);
				o.uv[3] = v.uv + _MainTex_TexelSize.xy * half2(-1,0);
				o.uv[4] = v.uv + _MainTex_TexelSize.xy * half2(0,0);
				o.uv[5] = v.uv + _MainTex_TexelSize.xy * half2(1,0);
				o.uv[6] = v.uv + _MainTex_TexelSize.xy * half2(-1,1);
				o.uv[7] = v.uv + _MainTex_TexelSize.xy * half2(0,1);
				o.uv[8] = v.uv + _MainTex_TexelSize.xy * half2(1,1);

				o.uv[4] = TRANSFORM_TEX(v.uv, _AnimateTex) + frac(float2(0.0,-_ScrollX) * _Time.y);


				return o;
			}
			
			fixed4 frag (v2f i) : SV_Target
			{
			
				half edge = Sobel(i);

				fixed4 withEdgeColor = lerp(_EdgeColor,tex2D(_MainTex, i.uv[4]),edge);
				fixed4 onlyEdgeColor = lerp(_EdgeColor,_BackgroundColor,edge);

				fixed4 finalColor = lerp(withEdgeColor,onlyEdgeColor,_EdgeOnly);

				fixed4 col = tex2D(_AnimateTex, i.uv[4]);

				return fixed4(finalColor.rgb,(finalColor.a * (1.0 - col.r)));
			}
			ENDCG
		}
	}
}

這裡用Easy AR 實驗效果。呼叫攝像機,顯示畫面,並描繪邊框


這裡的第二個材質球RealityPlane就是 Easy AR實時獲取的手機攝像機畫面,第一個材質球就是我們的邊緣檢測Shader,Animate第一張圖片顯示我們要檢測邊緣的圖片,第二張圖片就是我們邊框描繪的圖片。

邊框圖片大概就這樣,可以自己調整


效果就是這樣