描边效果后处理 - Shader

  • 脚本
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EdgeDetectNormalAndDepth : PostEffectBase
{
    
    
    [SerializeField] private Shader _edgeSgader;
    private Material _edgeMaterial;
    
    [Range(0f, 1f)]
    public float edgeOnly = 0f;
    public Color edgeColor = Color.black;
    public Color backgroundColor = Color.white;
    public float sampleDistance = 1.0f;
    public float sensitivityDepth = 1.0f;
    public float sensitivityNormal = 1.0f;

    private void OnEnable()
    {
    
    
        GetComponent<Camera>().depthTextureMode |= DepthTextureMode.DepthNormals;
    }
    
    public Material EdgeMaterial
    {
    
    
        get
        {
    
    
            _edgeMaterial = CheckShaderAndCreateMaterial(_edgeSgader, _edgeMaterial);
            return _edgeMaterial;
        }
    }

    private void OnRenderImage(RenderTexture src, RenderTexture dest)
    {
    
    
        if (EdgeMaterial != null)
        {
    
    
            EdgeMaterial.SetFloat("_EdgeOnly", edgeOnly);
            EdgeMaterial.SetColor("_EdgeColor", edgeColor);
            EdgeMaterial.SetColor("_BackgroundColor", backgroundColor);
            EdgeMaterial.SetFloat("_SampleDistance", sampleDistance);
            EdgeMaterial.SetVector("_Sensitivity", new Vector4(sensitivityNormal, sensitivityDepth, 0f, 0f));
            
            Graphics.Blit(src, dest, EdgeMaterial);
        }
        else
        {
    
    
            Graphics.Blit(src, dest);
        }
    }
}

  • Shader
Shader "Hidden/EdgeDetectNormalAndDepth"
{
    
    
    Properties
    {
    
    
        _MainTex ("Texture", 2D) = "white" {
    
    }
        _EdgeOnly ("Edge Only", Float) = 1.0
		_EdgeColor ("Edge Color", Color) = (0, 0, 0, 1)
		_BackgroundColor ("Background Color", Color) = (1, 1, 1, 1)
		_SampleDistance ("Sample Distance", Float) = 1.0
		_Sensitivity ("Sensitivity", Vector) = (1, 1, 1, 1)
    }
    SubShader
    {
    
    
        CGINCLUDE

        #include "UnityCG.cginc"

        sampler2D _MainTex;
        half4 _MainTex_TexelSize;
        sampler2D _CameraDepthNormalsTexture;
        float _EdgeOnly;
        fixed4 _EdgeColor;
        fixed4 _BackgroundColor;
        float _SampleDistance;
        half4 _Sensitivity;

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

        struct v2f
        {
    
    
            float4 pos : SV_POSITION;
            float2 uv[5] : TEXCOORD0;
        };

        v2f vert (a2v v)
        {
    
    
            v2f o;
            o.pos = UnityObjectToClipPos(v.vertex);

            half2 uv = v.uv;
            o.uv[0] = uv;

            #if UNITY_UV_STARTS_AT_TOP
            if (_MainTex_TexelSize.y < 0)
                uv.y = 1 - uv.y;
            #endif

            o.uv[1] = uv + _MainTex_TexelSize.xy * half2(-1, 1) * _SampleDistance;
            o.uv[2] = uv + _MainTex_TexelSize.xy * half2(1, -1) * _SampleDistance;
            o.uv[3] = uv + _MainTex_TexelSize.xy * half2(1, 1) * _SampleDistance;
            o.uv[4] = uv + _MainTex_TexelSize.xy * half2(-1, -1) * _SampleDistance;
            
            return o;
        }

        half CheckSame(half4 center, half4 sample)
        {
    
    
            half2 centerNormal = center.xy;
            float centerDepth = DecodeFloatRG(center.zw);
            half2 sampleNormal = sample.xy;
            float sampleDepth = DecodeFloatRG(sample.zw);

            half2 diffNormal = abs(centerNormal - sampleNormal) * _Sensitivity.x;
            int isSameNormal = (diffNormal.x + diffNormal.y) < 0.1;

            float diffDepth = abs(centerDepth - sampleDepth) * _Sensitivity.y;
            int isSameDepth = diffDepth < 0.1 * centerDepth;

            return isSameNormal * isSameDepth ? 1.0 : 0.0;
        }
        
        fixed4 frag (v2f i) : SV_Target
        {
    
    
            half4 sample1 = tex2D(_CameraDepthNormalsTexture, i.uv[1]);
            half4 sample2 = tex2D(_CameraDepthNormalsTexture, i.uv[2]);
            half4 sample3 = tex2D(_CameraDepthNormalsTexture, i.uv[3]);
            half4 sample4 = tex2D(_CameraDepthNormalsTexture, i.uv[4]);

            half edge = 1.0;

            edge *= CheckSame(sample1, sample2);
            edge *= CheckSame(sample3, sample4);

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

            return lerp(withEdgeColor, onlyEdgeColor, _EdgeOnly);
        }
        
        ENDCG

        Pass
        {
    
    
            Cull Off ZWrite Off ZTest Always
            
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            ENDCG
        }
    }
}

猜你喜欢

转载自blog.csdn.net/m0_52361859/article/details/128268436