-
边缘检测算子
即用于边缘检测的卷积核。判断边缘可以是颜色、亮度、纹理等变换差异大小,也就是判断相邻像素之间的差值(梯度,gradient)。Gx表示检测水平方向的变化梯度,得出竖直方向的边缘线。
每次卷积得到两个方向上的梯度值Gx和Gy,整体梯度值:G = | Gx | + | Gy |。 -
Shader:
Shader "_MyShader/9_PostScreenEffect/1_MyEdgeDetection"
{
Properties
{
_MainTex ("MainTex", 2D) = "white" {}
//_EdgeOnly ("EdgeOnly", Range(0,1)) = 0
//_EdgeColor ("EdgeColor", COLOR) = (0,0,0,1)
//_BackgroundColor ("BackgroundColor", COLOR) = (1,1,1,1)
}
SubShader
{
Pass
{
ZTest Always
ZWrite off
Cull off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f
{
float4 vertex : SV_POSITION;
float2 uv[9] : TEXCOORD0;
};
sampler2D _MainTex;
float4 _MainTex_TexelSize;
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 j = 0;j < 9;j++){
texColor = luminance(tex2D(_MainTex,i.uv[j]));
edgeX += texColor * Gx[j];
edgeY += texColor * Gy[j];
}
half edge = 1 - abs(edgeX) - abs(edgeY);
return edge;
}
v2f vert (appdata_img v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv[0] = v.texcoord + _MainTex_TexelSize.xy * float2(-1,1);
o.uv[1] = v.texcoord + _MainTex_TexelSize.xy * float2(0,-1);
o.uv[2] = v.texcoord + _MainTex_TexelSize.xy * float2(1,-1);
o.uv[3] = v.texcoord + _MainTex_TexelSize.xy * float2(-1,0);
o.uv[4] = v.texcoord + _MainTex_TexelSize.xy * float2(0,0);
o.uv[5] = v.texcoord + _MainTex_TexelSize.xy * float2(1,0);
o.uv[6] = v.texcoord + _MainTex_TexelSize.xy * float2(-1,1);
o.uv[7] = v.texcoord + _MainTex_TexelSize.xy * float2(0,1);
o.uv[8] = v.texcoord + _MainTex_TexelSize.xy * float2(1,1);
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 col = lerp(withEdgeColor,onlyEdgeColor,_EdgeOnly);
return col;
}
ENDCG
}
}
FallBack off
}
- C#:
using UnityEngine;
using System.Collections;
public class MyEdgeDetection : ScreenEffectBase {
[Range(0,1)]
public float edgeOnly;
public Color edgeColor;
public Color backgroundColor;
public Shader shader;
private Material edgeDetectionMat;
public Material material{
get{
edgeDetectionMat = CheckShaderAndCreateMaterial (shader, edgeDetectionMat);
return edgeDetectionMat;
}
}
void OnRenderImage(RenderTexture src, RenderTexture dest){
if (material != null) {
material.SetFloat ("_EdgeOnly", edgeOnly);
material.SetColor ("_EdgeColor", edgeColor);
material.SetColor ("_BackgroundColor", backgroundColor);
Graphics.Blit (src, dest,material);
} else {
Graphics.Blit (src, dest);
}
}
}