Unity 后期处理保证背景颜色

 • 

Unity 后期处理中如果用了 Color Grading 之类的效果器同时要保证相机背景颜色不变(比如 Unity 作为一个 View 挂在手机客户端中),就要费些功夫,因为使用多相机(一个背景相机+一个实物渲染相机)仍然是无法保证相机背景不被 depth 较高的相机上的效果器处理的,因此写了个根据相机渲染深度信息来填充特定颜色,挂在 Color Grading 后面即可。

namespace FinGameWorks.Scripts.PostProcess
{
    using System;
    using UnityEngine;

    [RequireComponent(typeof(Camera))]
    [ExecuteInEditMode]
    public class MaskedFirstPass : MonoBehaviour
    {
        [Range(0f, 3f)] public float depthLevel = 0.5f;
        public Color backgroundColor = Color.white;

        public Shader _shader;

        private Shader shader
        {
            get { return _shader != null ? _shader : (_shader = Shader.Find("MaskedFirstPassShader")); }
        }

        private Material _material;

        private Material material
        {
            get
            {
                if (_material == null)
                {
                    _material = new Material(shader);
                    _material.hideFlags = HideFlags.HideAndDontSave;
                }

                return _material;
            }
        }

        private void Start()
        {
            if (!SystemInfo.supportsImageEffects)
            {
                print("System doesn't support image effects");
                enabled = false;
                return;
            }

            if (shader == null || !shader.isSupported)
            {
                enabled = false;
                print("Shader " + shader.name + " is not supported");
                return;
            }

            GetComponent<Camera>().depthTextureMode = DepthTextureMode.Depth;
        }

        private void OnDisable()
        {
            if (_material != null)
                DestroyImmediate(_material);
        }

        private void OnRenderImage(RenderTexture src, RenderTexture dest)
        {
            if (shader != null)
            {
                material.SetFloat("_DepthLevel", depthLevel);
                material.SetColor("_BGColor",backgroundColor);
                Graphics.Blit(src, dest, material);
            }
            else
            {
                Graphics.Blit(src, dest);
            }
        }
    }
}
Shader "MaskedFirstPassShader"
{
   Properties
     {
         _BGColor ("Background Color", COLOR) = (1.0,1.0,1.0,1.0)
         _DepthLevel ("Depth Level", Range(1, 3)) = 1
         _MainTex ("Source", 2D) = "white" {}
     }
     SubShader
     {
         Pass
         {
             CGPROGRAM
 
             #pragma vertex vert
             #pragma fragment frag
             #include "UnityCG.cginc"
             
             uniform sampler2D _CameraDepthTexture;
             uniform half4 _MainTex_TexelSize;
             uniform float4 _BGColor;
             uniform fixed _DepthLevel;
 
             struct input
             {
                 float4 pos : POSITION;
                 half2 uv : TEXCOORD0;
             };
 
             struct output
             {
                 float4 pos : SV_POSITION;
                 half2 uv : TEXCOORD0;
             };
 
               output vert(input i)
             {
                 output o;
                 o.pos = UnityObjectToClipPos(i.pos);
                 o.uv = MultiplyUV(UNITY_MATRIX_TEXTURE0, i.uv);
                 #if UNITY_UV_STARTS_AT_TOP
                 if (_MainTex_TexelSize.y < 0)
                         o.uv.y = 1 - o.uv.y;
                 #endif
 
                 return o;
             }
             
              sampler2D _MainTex;
                float4 _MainTex_ST;
         
             fixed4 frag(output o) : COLOR
             {
                 float depth = UNITY_SAMPLE_DEPTH(tex2D(_CameraDepthTexture, o.uv));
                 depth = pow(Linear01Depth(depth), _DepthLevel);
                 if (depth < 0.5)
                 {
                                float4 color = tex2D(_MainTex, 
                       UnityStereoScreenSpaceUVAdjust(
                       o.uv, _MainTex_ST));	
                       return color;
                 }
                  else
                 {
                    return     _BGColor;
                 }
             }
             ENDCG
         }
     } 
}