Shader屏幕後處理效果
- 2019 年 12 月 2 日
- 筆記
版權聲明:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
本文鏈接:https://blog.csdn.net/CJB_King/article/details/78881896
Shader屏幕後處理效果
邊緣檢測:
邊緣檢測的原理是利用一些邊緣檢測算子對圖像進行卷積操作(卷積操作就是使用一個卷積核對一張圖像的每一個像素進行一系列的操作,倦急核通常是一個四方形網格結構,例如2×2,3×3的方形區域,該區域內每個方格都有一個權重值。當對圖像中的某個像素進行卷積時,我們會把卷積核的中心放置在該像素上,如下圖,翻轉之後再依次進行計算核中的每個元素和其覆蓋的圖像像素值的乘積並求和,得到的結果就是改為只的新像素值)

常見的邊緣檢測算子
卷積操作的神奇指出 在於選擇的卷積核,用於邊緣檢測的卷積核(邊緣檢測算子)是什麼? 首先想一下 如果相鄰像素之間存在差別明顯的顏色,亮度等屬性,那麼他們之間應該有一條邊界。這種相鄰像素之間的差值可以用梯度來表示,邊緣處的梯度絕對值比較大,所以,就出現下面幾種邊緣檢測算子;

下面請看注釋:
Shader "MyShader/OutLine" { Properties{ _MainTex("MainTexture",2D) = "White"{} _LineColor("OutLineColor",color) = (1,1,1,1) _BackGroundColor("BackGroundColor",color) = (1,1,1,1) _EdgeOnly("EdgeOnly",float)=3 } SubShader{ Tags{"RenderType" = "Transparent"} Pass { Cull off ZTest Always ZWrite off CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" sampler2D _MainTex; float4 _MainTex_TexelSize; fixed4 _LineColor; fixed4 _BackGroundColor; float _EdgeOnly; struct a2v { fixed4 vertex : POSITION; fixed2 uv : TEXCOORD; }; struct v2f { fixed4 pos : SV_POSITION; fixed2 uv[9]:TEXCOORD;//對應了使用Sobel算子採樣是需要的 //九個領域紋理坐標 }; fixed luminance(fixed4 color) { return color.r*0.21 + color.g*0.37 + color.b*0.44; } half sobel(v2f v) { 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 i = 0; i < 9; i++) { texColor = luminance(tex2D(_MainTex, v.uv[i])); edgeX += texColor*Gx[i]; edgeY += texColor*Gy[i]; } return 1 - abs(edgeX) - abs(edgeY); } v2f vert(a2v v) { v2f o; o.pos = UnityObjectToClipPos(v.vertex); o.uv[0] = v.uv + _MainTex_TexelSize.xy*fixed2(-1,1); o.uv[1] = v.uv + _MainTex_TexelSize.xy*fixed2(0, 1); o.uv[2] = v.uv + _MainTex_TexelSize.xy*fixed2(1, 1); o.uv[3] = v.uv + _MainTex_TexelSize.xy*fixed2(-1,0); o.uv[4] = v.uv + _MainTex_TexelSize.xy*fixed2(0, 0); o.uv[5] = v.uv + _MainTex_TexelSize.xy*fixed2(1, 0); o.uv[6] = v.uv + _MainTex_TexelSize.xy*fixed2(-1, -1); o.uv[7] = v.uv + _MainTex_TexelSize.xy*fixed2(0, -1); o.uv[8] = v.uv + _MainTex_TexelSize.xy*fixed2(1,-1); return o; } fixed4 frag(v2f v):SV_Target { half edge = sobel(v); //計算梯度值edge fixed4 withEdgeColor = lerp(_LineColor, tex2D(_MainTex, v.uv[0]), edge); fixed4 onlyEdgeColor = lerp(_LineColor, _BackGroundColor,edge); return lerp(withEdgeColor, onlyEdgeColor, _EdgeOnly); } ENDCG } } }