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
}