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
}
}
}