13.2 获取深度和法线纹理 运动模糊

代码来源于 冯乐乐 shader 入门精要

13.2 获取深度和法线纹理 运动模糊_第1张图片

 

Shader "Unlit/MyMotionBlurWithDepthTexture"
{
	Properties
	{
		_MainTex ("Texture", 2D) = "white" {}
		_BlurSize("Blur Size",Float) = 0.5
	}
	SubShader
	{
		CGINCLUDE
		#include "UnityCG.cginc"

		sampler2D _MainTex;
		half4 _MainTex_TexelSize;
		// Unity 赋值的     camera.depthTextureMode |= DepthTextureMode.Depth;
		sampler2D _CameraDepthTexture; 
		float4x4 _CurrentViewProjectionMatrix;
		float4x4 _CurrentViewProjectionInverseMatrix;
		float4x4 _PreviousViewProjectionMatrix;
		half _BlurSize;
		
		struct v2f
		{
			float4 pos : SV_POSITION;
			float2 uv : TEXCOORD0;
			half2 uv_depth : TEXCOORD1;
		};

		v2f vert(appdata_img v) {
			v2f o;
			o.pos = 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
		{
			// 得到该像素的深度缓存值 由NDC下的坐标映射而来
			float d = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv_depth);
			// H 是在这个像素的视口坐标 范围在(-1,1)
			// 我们想要构建像素的NDC坐标 H,就需要把这个深度值重新映射回NDC原映射的反函数即可,即 d *2-1。
			// 同样,NDC的 xy 分量可以由像素的纹理坐标映射而来(NDC下的 xyz 分量范围均为[-1,1])
			float4 H = float4(i.uv.x*2 -1,i.uv.y*2-1,d *2-1,1);
			//使用当前帧的视角*投影矩阵的逆矩阵对其进行变换,并把结果值除以它的 w分量来得到世界空间下的坐标表示worldPos
			float4 D = mul(_CurrentViewProjectionInverseMatrix,H);
			float4 worldPos = D/D.w;

			float4 currentPos = H;
			//使用前一帧的视角*投影矩阵对它进行变换,得到前一帧在NDC下的坐标previousPos
			float4 previousPos = mul(_PreviousViewProjectionMatrix,worldPos);
			previousPos /= previousPos.w;
			//计算前一帧和当前帧在屏幕空间下的位置差,得到该像素的速度velocity
			float2 velocity = (currentPos.xy - previousPos.xy)/2.0f;
			float2 uv = i.uv;

			float4 c = tex2D(_MainTex,uv);
			//使用该速度值对它的邻域像素进行采样,相加后取平均值得到一个模糊的效果
			uv += velocity * _BlurSize;
			for(int it = 1; it<3;it++, uv += velocity* _BlurSize){
				float4 currentColor = tex2D(_MainTex,uv);
				c += currentColor;
			}
			// 上面3个邻域元素相加 这边需要 /3 得平均值
			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
}

 

using UnityEngine;

public class MyMotionBlurWithDepthTexture : PostEffectsBase
{
public Shader motionBlurShader;
	private Material motionBlurMaterial = null;

	public Material material {  
		get {
			motionBlurMaterial = CheckShaderAndCreateMaterial(motionBlurShader, motionBlurMaterial);
			return motionBlurMaterial;
		}  
	}

	private Camera myCamera;
	public Camera camera {
		get {
			if (myCamera == null) {
				myCamera = GetComponent();
			}
			return myCamera;
		}
	}

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

	private Matrix4x4 previousViewProjectionMatrix;
	
	void OnEnable() {
		camera.depthTextureMode |= DepthTextureMode.Depth;

		previousViewProjectionMatrix = camera.projectionMatrix * camera.worldToCameraMatrix;
	}
	
	void OnRenderImage (RenderTexture src, RenderTexture dest) {
		if (material != null) {
			material.SetFloat("_BlurSize", blurSize);

			material.SetMatrix("_PreviousViewProjectionMatrix", previousViewProjectionMatrix);
			Matrix4x4 currentViewProjectionMatrix = camera.projectionMatrix * camera.worldToCameraMatrix;
			Matrix4x4 currentViewProjectionInverseMatrix = currentViewProjectionMatrix.inverse;
			material.SetMatrix("_CurrentViewProjectionInverseMatrix", currentViewProjectionInverseMatrix);
			previousViewProjectionMatrix = currentViewProjectionMatrix;

			Graphics.Blit (src, dest, material);
		} else {
			Graphics.Blit(src, dest);
		}
	}
}
using UnityEngine;
using System.Collections;

[ExecuteInEditMode]
[RequireComponent (typeof(Camera))]
public class PostEffectsBase : MonoBehaviour {

	// Called when start
	protected void CheckResources() {
		bool isSupported = CheckSupport();
		
		if (isSupported == false) {
			NotSupported();
		}
	}

	// Called in CheckResources to check support on this platform
	protected bool CheckSupport() {
		if (SystemInfo.supportsImageEffects == false || SystemInfo.supportsRenderTextures == false) {
			Debug.LogWarning("This platform does not support image effects or render textures.");
			return false;
		}
		
		return true;
	}

	// Called when the platform doesn't support this effect
	protected void NotSupported() {
		enabled = false;
	}
	
	protected void Start() {
		CheckResources();
	}

	// Called when need to create the material used by this effect
	protected Material CheckShaderAndCreateMaterial(Shader shader, Material material) {
		if (shader == null) {
			return null;
		}
		
		if (shader.isSupported && material && material.shader == shader)
			return material;
		
		if (!shader.isSupported) {
			return null;
		}
		else {
			material = new Material(shader);
			material.hideFlags = HideFlags.DontSave;
			if (material)
				return material;
			else 
				return null;
		}
	}
}

 

你可能感兴趣的:(Shader)