屏幕后处理-基于高度的全局雾效
using UnityEngine;

public class BackWu : MonoBehaviour {

    public Material mat;

    private Camera cam;

    [Range(0.0f, 3.0f)]
    public float fogDensity = 1.0f;//雾效强度

    public Color fogColor = Color.white;//雾的颜色

    public float fogStart = 0.0f; //开始高度
    public float fogEnd = 2.0f; //结束高度

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

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

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

            //近剪裁面中心到top边的垂直距离
            float halfHeight = near * Mathf.Tan(fov * 0.5f * Mathf.Deg2Rad);
            //近剪裁面中心垂直指向左边
            Vector3 toRight = cam.transform.right * halfHeight * aspect;
            //近剪裁面中心垂直指向上边
            Vector3 toTop = cam.transform.up * halfHeight;

            Vector3 topLeft = cam.transform.forward * near - toRight + toTop;
            float scale = topLeft.magnitude / near;//计算一个depth值转换成真实长度的scale

            //相机指向近剪裁面的左上角
            topLeft.Normalize();
            topLeft *= scale;

            //相机指向近剪裁面的右上角
            Vector3 topRight = cam.transform.forward * near + toRight + toTop;
            topRight.Normalize();
            topRight *= scale;

            //相机指向近剪裁面的右下角
            Vector3 bottomRight = cam.transform.forward * near + toRight - toTop;
            bottomRight.Normalize();
            bottomRight *= scale;

            //相机指向近剪裁面的左下角
            Vector3 bottomLeft = cam.transform.forward * near - toRight - toTop;
            bottomLeft.Normalize();
            bottomLeft *= scale;

            //存储在一个矩阵中
            frustumCorners.SetRow(0, bottomLeft);
            frustumCorners.SetRow(1, bottomRight);
            frustumCorners.SetRow(2, topRight);
            frustumCorners.SetRow(3, topLeft);

            mat.SetMatrix("_FrustumCornersRay", frustumCorners);
            mat.SetFloat("_FogDensity", fogDensity);
            mat.SetColor("_FogColor", fogColor);
            mat.SetFloat("_FogStart", fogStart);
            mat.SetFloat("_FogEnd", fogEnd);

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


Shader "Unlit/BackMohu"
{
	Properties
	{
		_MainTex ("Texture", 2D) = "white" {}
		_FogDensity("Fog Density",Float) = 1.0
		_FogColor("Fog Color",Color) = (1,1,1,1)
		_FogStart("Fog Start",Float) = 0.0
		_FogEnd("Fog End",Float) = 1.0
	}
	SubShader
	{
		Tags { "RenderType" = "Opaque" }
		LOD 100

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

		#include "UnityCG.cginc"

		struct v2f {
			float4 pos:SV_POSITION;
			half2 uv:TEXCOORD0;
			half2 uv_depth:TEXCOORD1;
			float4 interpolateRay: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_STARTS_AT_TOP
						if (_MainTex_TexelSize.y < 0)
							o.uv_depth = 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
			
			//根据uv位置 来决定使用哪个Ray 并会线性插值到片元
			o.interpolateRay = _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.interpolateRay.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
}


blob.png


首页 我的博客
粤ICP备17103704号