Unity Shader学习笔记(5)基于摄像机深度和法线的后处理描边效果

文章目标 :

主要参考书籍为《Unity Shader入门精要》,本文主要注重于整理,方便后续直接调用。

渲染效果图:

后处理渲染边缘

主要相关代码:

摄像机脚本文件:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace UnityShaderLearnPostImageEffects
{
    
    
    class EdgeDetectNormalsAndDepth : PostEffectsBase
    {
    
    
        public Shader edgeDectectShader = null;
        private Material edgeDectectMaterial = null;

        [Range(0, 1)]
        public float edgesOnly = 0f;
        public Color edgeColor = Color.black;
        public Color backgroundColor = Color.white;
        [Range(0f, 0.004f)]
        public float sampleDistance = 0.001f;
        public float sensitivityDepth = 1.0f;
        public float sensitivityNormals = 1.0f;

        private void OnEnable()
        {
    
    
            GetComponent<Camera>().depthTextureMode |= DepthTextureMode.DepthNormals;
        }

        public Material material
        {
    
    
            get
            {
    
    
                edgeDectectMaterial = CheckShaderAndCreateMaterial(edgeDectectShader, edgeDectectMaterial);
                return edgeDectectMaterial;
            }
        }

        //[ImageEffectOpaque] //仅对不透明物体产生作用,在透明物体渲染之前执行 OnRenderImage 函数;
        private void OnRenderImage(RenderTexture src, RenderTexture dest)
        {
    
    
            if (material != null)
            {
    
    
                material.SetFloat("_EdgeOnly", edgesOnly);
                material.SetColor("_EdgeColor", edgeColor);
                material.SetColor("_BackgroundColor", backgroundColor);
                material.SetFloat("_SampleDistance", sampleDistance);
                material.SetVector("_Sensitivity", new Vector4(sensitivityNormals, sensitivityDepth, 0, 0));
                Graphics.Blit(src, dest, material);
            }
            else
            {
    
     
                Graphics.Blit(src, dest);
            }

        }
    }
}

Shader 文件代码:
//参考文件:《Unity Shader 入门精要》
//整理制作:嘿皮土豆
//渲染管线:默认渲染管线
Shader "UnityShaderLearn/EdgeDetectNormalsAndDepth"
{
    
    
    Properties
    {
    
    
        _MainTex("MainTex", 2D) = ""{
    
    }
        _EdgeOnly("EdgeOnly", float) = 1
        _EdgeColor("EdgeColor", color) = (0,0,0,1)
        _BackgroundColor("BackgroundColor", Color) = (1,1,1,1)
        _SampleDistance("SampleDistance", Range(0,0.004)) = 0.001
        _Sensitivity("Sensitivity", vector) = (1,1,1,1)
    }
    Subshader
    {
    
    
        CGINCLUDE
            #include "UnityCG.cginc"

            sampler2D _MainTex;
            float4 _MainTex_ST;
            fixed _EdgeOnly;
            fixed4 _EdgeColor;
            fixed4 _BackgroundColor;
            float _SampleDistance;
            float4 _Sensitivity;
            sampler2D _CameraDepthNormalsTexture;

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

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

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

                float2 diffDepth = abs(centerDepth - sampleDepth) * _Sensitivity;
                int isSameDepth = diffDepth < 0.1 * centerDepth;

                return isSameDepth * isSameNormal ? 1 : 0;

            }

            v2f vert (appdata_img v)
            {
    
    
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                half2 uv = v.texcoord;
                o.uv[0] = uv;

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

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

                return o;
            }

            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;

                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
        {
    
    
            ZTest Always
            Cull Off
            ZWrite Off

            CGPROGRAM
                
                #pragma vertex vert
                #pragma fragment frag

            ENDCG
        }
    }

}

猜你喜欢

转载自blog.csdn.net/m0_54122551/article/details/124660790