屏幕后处理-利用深度图构建出速度值制作运动模糊
using UnityEngine;

public class depthmohu : MonoBehaviour {

    public Material mat;

    [Range(0.0f,1.0f)]
    public float blurSize = 0.5f;

    private Matrix4x4 previousViewProjectionMatrix;  //上一次的视角投影矩阵
    private Camera c; //要实时获取它的视角矩阵和投影矩阵

	void Start () {
        c = this.GetComponent<Camera>();
        c.depthTextureMode = DepthTextureMode.Depth;
	}

    private void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
        if (mat != null)
        {
            mat.SetFloat("_BlurSize", blurSize); //模糊的程度,现在应该叫做幻影的程度
            mat.SetMatrix("_PreviousViewProjectionMatrix", previousViewProjectionMatrix);//上一帧的视角投影矩阵
            Matrix4x4 currentViewProjectionMatrix = c.projectionMatrix * c.worldToCameraMatrix;//当前帧的视角投影矩阵
            Matrix4x4 currentViewProjectionInverseMatrix = currentViewProjectionMatrix.inverse;//反转当前帧的视角投影矩阵

            mat.SetMatrix("_CurrentViewProjectionInverseMatrix", currentViewProjectionInverseMatrix);
            previousViewProjectionMatrix = currentViewProjectionMatrix; //保存当前帧的视角投影矩阵

            Graphics.Blit(source, destination, mat);
        }
        else
        {
            Graphics.Blit(source, destination);
        }
    }
}


Shader "Unlit/depthmohu"
{
	Properties
	{
		_MainTex ("Texture", 2D) = "white" {}
		_BlurSize("BlurSize",Float) = 0.5
	}
	SubShader
	{
		Tags { "RenderType" = "Opaque" }
		LOD 100

		CGINCLUDE
		#include "UnityCG.cginc"
		sampler2D _MainTex;
		half4 _MainTex_TexelSize;
		sampler2D _CameraDepthTexture;
		float4x4 _CurrentViewProjectionInverseMatrix;
		float4x4 _PreviousViewProjectionMatrix;
		half _BlurSize;
		struct v2f
		{
			float2 uv : TEXCOORD0;
			float2 uv_depth:TEXCOORD1;
			float4 vertex : SV_POSITION;
		};

		v2f vert(appdata_img v)
		{
			v2f o;
			o.vertex = UnityObjectToClipPos(v.vertex);
			o.uv = v.texcoord;
			o.uv_depth = v.texcoord;

			//平台差异化处理,贴图反转,防止开启了抗锯齿
			#if UNITY_UV_STARTS_AT_TOP
						if (_MainTex_TexelSize.y < 0)
							o.uv_depth.y = 1 - o.uv_depth.y;
			#endif

			return o;
		}

		fixed4 frag(v2f i):SV_Target
		{
			//深度贴图的取样
			float d = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv_depth);
			//当前NDC的坐标,映射到[-1,1]范围
			float4 H = float4(i.uv.x * 2 - 1, i.uv.y * 2 - 1, d * 2 - 1, 1);
			//通过视角和投影的逆矩阵来得到世界坐标
			float4 D = mul(_CurrentViewProjectionInverseMatrix, H);
			float4 worldPos = D / D.w;
			float4 currentPos = H;
			//通过上一帧的视角和投影矩阵,反构建上一帧的NDC坐标
			float4 previousPos = mul(_PreviousViewProjectionMatrix, worldPos);
			previousPos /= previousPos.w;

			//利用两个NDC坐标差异构建速度值
			float2 velocity = (currentPos.xy - previousPos.xy) / 2.0f; 
			float2 uv = i.uv;
			float4 c = tex2D(_MainTex, uv);
			for (int it = 1; it < 3; it++)
			{
				uv += velocity * _BlurSize;//速度值会决定模糊的程度,取样的偏差位置
				float4 currentColor = tex2D(_MainTex,uv);
				c += currentColor;
			}

			c /= 3;

			return fixed4(c.rgb, 1);
		}

		ENDCG

		Pass
		{
			ZTest Always Cull Off ZWrite Off

			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			ENDCG
		}
	}

	Fallback Off
}


因为这是根据相机的视角和投影矩阵来反推世界坐标的,所以这个只适合这两个矩阵改变的运动迷糊,也就是说适合场景静止的情况下,相机动的运动模糊。


首页 我的博客
粤ICP备17103704号