UnityShader 学习笔记 22 屏幕后期之边缘检测

  • 边缘检测算子
    即用于边缘检测的卷积核。判断边缘可以是颜色、亮度、纹理等变换差异大小,也就是判断相邻像素之间的差值(梯度,gradient)。Gx表示检测水平方向的变化梯度,得出竖直方向的边缘线。
    UnityShader 学习笔记 22 屏幕后期之边缘检测_第1张图片
    每次卷积得到两个方向上的梯度值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);

        }

    }



}


你可能感兴趣的:(UnityShader)