using System;
using UnityEngine;
namespace DefaultNamespace
{
public class FogWithDepthTexture : PostEffectBase
{
[SerializeField]
private Shader _fogShader;
private Material _fogMaterial;
private Camera _camera;
[Range(0f, 1f)]
public float fogDensity = 1.0f;
public Color fogColor = Color.white;
public float fogStart = 0f;
public float fogEnd = 2f;
public Material FogMaterial
{
get
{
_fogMaterial = CheckShaderAndCreateMaterial(_fogShader, _fogMaterial);
return _fogMaterial;
}
}
public Camera MyCamera
{
get
{
if (_camera == null)
_camera = GetComponent<Camera>();
return _camera;
}
}
private void OnEnable()
{
MyCamera.depthTextureMode |= DepthTextureMode.Depth;
}
private void OnRenderImage(RenderTexture src, RenderTexture dest)
{
if (FogMaterial != null)
{
float fov = MyCamera.fieldOfView;
float near = MyCamera.nearClipPlane;
float aspect = MyCamera.aspect;
float halfHeight = near * Mathf.Tan(fov * 0.5f * Mathf.Deg2Rad);
var cameraTransform = MyCamera.transform;
Vector3 toTop = cameraTransform.up * halfHeight;
Vector3 toRight = cameraTransform.right * halfHeight * aspect;
Vector3 f = cameraTransform.forward * near;
Vector3 topLeft = f + toTop - toRight;
float scale = topLeft.magnitude / near;
topLeft = topLeft.normalized * scale;
Vector3 topRight = (f + toTop + toRight).normalized * scale;
Vector3 bottomLeft = (f - toTop - toRight).normalized * scale;
Vector3 bottomRight = (f - toTop + toRight).normalized * scale;
Matrix4x4 frustumCorners = Matrix4x4.identity;
frustumCorners.SetRow(0, bottomLeft);
frustumCorners.SetRow(1, bottomRight);
frustumCorners.SetRow(2, topLeft);
frustumCorners.SetRow(3, topRight);
FogMaterial.SetMatrix("_FrustumCornersRay", frustumCorners);
FogMaterial.SetFloat("_FogDensity", fogDensity);
FogMaterial.SetColor("_FogColor", fogColor);
FogMaterial.SetFloat("_FogStart", fogStart);
FogMaterial.SetFloat("_FogEnd", fogEnd);
Graphics.Blit(src, dest, FogMaterial);
}
else
{
Graphics.Blit(src, dest);
}
}
}
}
Shader "Hidden/FogWithDepthTexture"
{
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
{
CGINCLUDE
#include "UnityCG.cginc"
float4x4 _FrustumCornersRay;
sampler2D _MainTex;
half4 _MainTex_TexelSize;
sampler2D _CameraDepthTexture;
half _FogDensity;
fixed4 _FogColor;
float _FogStart;
float _FogEnd;
struct a2v
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float2 uv_depth : TEXCOORD1;
float4 interpolatedRay : TEXCOORD2;
};
v2f vert (a2v v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.uv.xy;
o.uv_depth = v.uv.xy;
#if UNITY_UV_STARTS_AT_TOP
if (_MainTex_TexelSize.y < 0)
o.uv_depth.y = 1 - o.uv_depth.y;
#endif
int index = 0;
if (v.uv.x < 0.5 && v.uv.y < 0.5) {
index = 0;
} else if (v.uv.x > 0.5 && v.uv.y < 0.5) {
index = 1;
} else if (v.uv.x > 0.5 && v.uv.y > 0.5) {
index = 3;
} else {
index = 2;
}
#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 linerDepth = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv_depth));
float3 worldPos = _WorldSpaceCameraPos + linerDepth * i.interpolatedRay.xyz;
float fogDensity = (_FogEnd - worldPos.y) / (_FogEnd - _FogStart);
fogDensity = saturate(fogDensity * _FogDensity);
fixed4 color = tex2D(_MainTex, i.uv);
color.rgb = lerp(color.rgb, _FogColor.rgb, fogDensity);
return color;
}
ENDCG
Pass
{
Cull Off ZWrite Off ZTest Always
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
ENDCG
}
}
}