UnityShader---屏幕后处理之使用深度和法线纹理(内置渲染管线)---14

运动模糊之深度纹理:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MotinBlurWithDepthTexture : PostEffectBase
{
    [Range(0, 1f)]
    public float blurSize = 0.5f;

    public Camera currentCamera;

    private Matrix4x4 previousViewProjectionMatrix;

    private void OnEnable()
    {
        currentCamera.depthTextureMode |= DepthTextureMode.Depth;
        previousViewProjectionMatrix = currentCamera.projectionMatrix * currentCamera.worldToCameraMatrix;
    }

    private void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
        if (material != null)
        {
            material.SetFloat("_BlurSize", blurSize);

            material.SetMatrix("_PreviousViewProjectionMatrix",previousViewProjectionMatrix);

            Matrix4x4 currentViewProjectionMatrix = currentCamera.projectionMatrix * currentCamera.worldToCameraMatrix;

            Matrix4x4 currentViewProjectionInverseMatrix = currentViewProjectionMatrix.inverse;

            material.SetMatrix("_CurrentViewProjectionInverseMatrix",currentViewProjectionInverseMatrix);

            previousViewProjectionMatrix = currentViewProjectionMatrix;

            Graphics.Blit(source,destination,material);
        }
        else
        {
            Graphics.Blit(source, destination);
        }
    }
}
Shader "Unlit/311" {
	Properties{
		_MainTex("Base (RGB)", 2D) = "white" {}
		_BlurSize("Blur Size", Float) = 1.0
	}
		SubShader{
			//CGINCLUDE可以避免两个完全一样的frag函数
			//Unity会把 CGINCLUDE 和 ENDCG 之间的代码插入到每一个pass中,已达到声明一遍,多次使用的目的。
			CGINCLUDE

			#include "UnityCG.cginc"

			sampler2D _MainTex;
			half4 _MainTex_TexelSize;
			//Unity传进来的深度纹理
			sampler2D _CameraDepthTexture;
			//矩阵在这里写了,CS脚本可以直接赋值
			float4x4 _CurrentViewProjectionInverseMatrix;
			float4x4 _PreviousViewProjectionMatrix;
			half _BlurSize;

			struct v2f {
				float4 pos : SV_POSITION;
				half2 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;

				//当为DirectX平台时,需要做翻转
				#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 {
			//使用UV坐标对深度纹理采样得到深度值
			float d = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv_depth);
			//取NDC坐标 d*2-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;
			//上一帧位置
			float4 previousPos = mul(_PreviousViewProjectionMatrix, worldPos);
			// Convert to nonhomogeneous points [-1,1] by dividing by w.
			previousPos /= previousPos.w;

			//计算与上一帧的位置差,得到速度
			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;
			}
			c /= 3;

			return fixed4(c.rgb, 1.0);
		}

		ENDCG

	//下面是动态模糊所需要的Pass
	Pass {
		ZTest Always Cull Off ZWrite Off

		CGPROGRAM

		#pragma vertex vert  
		#pragma fragment frag  

		ENDCG
		}
	}
	FallBack Off
}

全局雾效:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FogWithDepthTexture : PostEffectBase
{
    private Camera myCamera;

    public Camera MyCamera
    {
        get
        {
            if (myCamera == null)
            {
                myCamera = GetComponent<Camera>();
            }

            return myCamera;
        }
    }


    private Transform cameraTransform;

    public Transform CameraTransform
    {
        get
        {
            if (cameraTransform == null)
            {
                cameraTransform = MyCamera.transform;
            }
            return cameraTransform;
        }
    }


    [Range(0, 3f)]
    public float fogDensity = 0.5f;

    public Color fogColor = Color.white;

    public float fogStart = 0;
    public float fogEnd = 2;

    private void OnEnable()
    {
        MyCamera.depthTextureMode |= DepthTextureMode.Depth;
    }

    private void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
        if (material != null)
        {
            Matrix4x4 frustumCorners = Matrix4x4.identity;

            float fov = MyCamera.fieldOfView;
            float near = MyCamera.nearClipPlane;
            float far = MyCamera.farClipPlane;
            float aspect = MyCamera.aspect;

            float halfHeight = near * Mathf.Tan(fov * 0.5f * Mathf.Deg2Rad);

            Vector3 toRight = CameraTransform.right * halfHeight * aspect;
            Vector3 toTop = CameraTransform.up * halfHeight;

            Vector3 topLeft = CameraTransform.forward * near + toTop - toRight;
            float scale = topLeft.magnitude / near;

            topLeft.Normalize();
            topLeft *= scale;

            Vector3 topRight = CameraTransform.forward * near + toTop + toRight;
            topRight.Normalize();
            toRight *= scale;

            Vector3 bottomLeft = CameraTransform.forward * near - toTop - toRight;
            bottomLeft.Normalize();
            bottomLeft *= scale;

            Vector3 bottomRight = CameraTransform.forward * near - toTop + toRight;
            bottomRight.Normalize();
            bottomRight *= scale;

            frustumCorners.SetRow(0, bottomLeft);
            frustumCorners.SetRow(1, bottomRight);
            frustumCorners.SetRow(2, topRight);
            frustumCorners.SetRow(3, topLeft);

            material.SetMatrix("_FrustumCornersRay", frustumCorners);
            material.SetMatrix("_ViewProjectionInverseMatrix", (MyCamera.projectionMatrix * MyCamera.worldToCameraMatrix).inverse);

            material.SetFloat("_FogDensity", fogDensity);
            material.SetColor("_FogColor", fogColor);
            material.SetFloat("_FogStart", fogStart);
            material.SetFloat("_FogEnd", fogEnd);

            Graphics.Blit(source, destination, material);

        }
        else
        {
            Graphics.Blit(source, destination);
        }
    }
}
Shader "Unlit/32"
{
	Properties
	{
		_MainTex("Base (RGB)", 2D) = "white" {}
		_FogDensity("FogDensity",Float) = 1.0
		_FogColor("FogColor",Color) = (1,1,1,1)
		_FogStart("FogStart",Float) = 0.0
		_FogEnd("FogEnd",Float) = 2.0
	}
	SubShader
	{
		CGINCLUDE

		#include "UnityCG.cginc"

		float4x4 _FrustumCornersRay;

		sampler2D _MainTex;
		half4 _MainTex_TexelSize;
		sampler2D _CameraDepthTexture;
		half _FogDensity;
		fixed4 _FogColor;
		float _FogStart;
		float _FogEnd;

		struct v2f {
			float4 pos : SV_POSITION;
			half2 uv : TEXCOORD0;
			half2 uv_depth : TEXCOORD1;
			float4 interpolatedRay : TEXCOORD2;
		};

		v2f vert(appdata_img v)
		{
			v2f o;

			o.pos = UnityObjectToClipPos(v.vertex);

			o.uv = v.texcoord;
			o.uv_depth = v.texcoord;

#if UNITY_UV_STATS_AT_TOP
			if (_MainTex_TexelSize.y < 0)
				o.uv_depth.y = 1 - o.uv_depth.y;
#endif

			int index = 0;
			if (v.texcoord.x < 0.5 && v.texcoord.y < 0.5)
			{
				index = 0;
			}
			else if (v.texcoord.x > 0.5 && v.texcoord.y < 0.5)
			{
				index = 1;
			}
			else if (v.texcoord.x > 0.5 && v.texcoord.y > 0.5)
			{
				index = 2;
			}
			else
			{
				index = 3;
			}

#if UNITY_UV_STARTS_AT_TOP
			if (_MainTex_TexelSize.y < 0)
				index = 3 - index;
#endif

			o.interpolatedRay = _FrustumCornersRay[index];

			return o;
		}

		fixed4 frag(v2f i) :SV_Target
		{
			float linearDepth = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv_depth));

			float3 worldPos = _WorldSpaceCameraPos + linearDepth * i.interpolatedRay.xyz;

			float fogDensity = (_FogEnd - worldPos.y) / (_FogEnd - _FogStart);
			fogDensity = saturate(fogDensity * _FogDensity);

			fixed4 finalColor = tex2D(_MainTex,i.uv);
			finalColor.rgb = lerp(finalColor.rgb, _FogColor.rgb, fogDensity);

			return finalColor;
		}

		ENDCG

		Pass
		{
			ZTest Always Cull Off ZWrite Off

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

边缘检测:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EdgeDetectNormalAndDepth : PostEffectBase
{

    public float edgesOnly = 0;
    public Color edgeColor = Color.black;
    public Color backgroundColor = Color.white;
    public float sampleDistance = 1f;
    public float sensitivityDepth = 1f;
    public float sensitivityNormals = 1f;

    public Vector2 v1;

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

    [ImageEffectOpaque]
    private void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
        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(source, destination, material);
        }
        else
        {
            Graphics.Blit(source, destination);
        }
    }
}
Shader "Unlit/33"
{
	Properties
	{
		_MainTex("Texture", 2D) = "white" {}		
		_EdgeOnly("EdgeOnly",Float) = 1.0
		_EdgeColor("EdgeColor",Color) = (1,1,1,1)
		_BackgroundColor("BackgroundColor",Color) = (1,1,1,1)
		_SampleDistance("SampleDistance",Float) = 1.0
		_Sensitivity("Sensitivity",Vector) = (1,1,1,1)
	}
	SubShader
	{
		CGINCLUDE

		#include "UnityCG.cginc"

		sampler2D _MainTex;
		half4 _MainTex_TexelSize;
		fixed _EdgeOnly;
		fixed4 _EdgeColor;
		fixed4 _BackgroundColor;
		float _SampleDistance;
		half4 _Sensitivity;
		sampler2D _CameraDepthNormalsTexture;

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

		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_TexelSize.y < 0)
				uv.y = 1 - uv.y;
#endif

			//Robert算子
			o.uv[1] = uv + _MainTex_TexelSize.xy * half2(1, 1) * _SampleDistance;
			o.uv[2] = uv + _MainTex_TexelSize.xy * half2(-1, -1) * _SampleDistance;
			o.uv[3] = uv + _MainTex_TexelSize.xy * half2(-1, 1) * _SampleDistance;
			o.uv[4] = uv + _MainTex_TexelSize.xy * half2(1, -1) * _SampleDistance;

			return o;
		}

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

			half2 sampleNormal = sample.xy;
			float sampleDepth = DecodeFloatRG(sample.zw);

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

			float diffDepth = abs(centerDepth - sampleDepth) * _Sensitivity.y;
			int isSameDepth = diffDepth < 0.1 * centerDepth;				

			return isSameNormal * isSameDepth ? 1.0 : 0;
		}

		fixed4 frag(v2f i) :SV_Target
		{
			half4 sample1 = tex2D(_CameraDepthNormalsTexture, i.uv[1]);
			half4 sample2 = tex2D(_CameraDepthNormalsTexture, i.uv[3]);
			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
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值