邊緣檢測效果動畫Shader實現
阿新 • • 發佈:2019-02-06
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第一張圖片顯示我們要檢測邊緣的圖片,第二張圖片就是我們邊框描繪的圖片。
邊框圖片大概就這樣,可以自己調整
效果就是這樣