mirror of
https://github.com/FriendshipIsEpic/FiE-Game.git
synced 2024-11-29 16:37:59 +01:00
192 lines
4.4 KiB
Text
192 lines
4.4 KiB
Text
Shader "Hidden/GlobalFog" {
|
|
Properties {
|
|
_MainTex ("Base (RGB)", 2D) = "black" {}
|
|
}
|
|
|
|
CGINCLUDE
|
|
|
|
#include "UnityCG.cginc"
|
|
|
|
uniform sampler2D _MainTex;
|
|
uniform sampler2D_float _CameraDepthTexture;
|
|
|
|
// x = fog height
|
|
// y = FdotC (CameraY-FogHeight)
|
|
// z = k (FdotC > 0.0)
|
|
// w = a/2
|
|
uniform float4 _HeightParams;
|
|
|
|
// x = start distance
|
|
uniform float4 _DistanceParams;
|
|
|
|
int4 _SceneFogMode; // x = fog mode, y = use radial flag
|
|
float4 _SceneFogParams;
|
|
#ifndef UNITY_APPLY_FOG
|
|
half4 unity_FogColor;
|
|
half4 unity_FogDensity;
|
|
#endif
|
|
|
|
uniform float4 _MainTex_TexelSize;
|
|
|
|
// for fast world space reconstruction
|
|
uniform float4x4 _FrustumCornersWS;
|
|
uniform float4 _CameraWS;
|
|
|
|
struct appdata_fog
|
|
{
|
|
float4 vertex : POSITION;
|
|
half2 texcoord : TEXCOORD0;
|
|
};
|
|
|
|
struct v2f {
|
|
float4 pos : SV_POSITION;
|
|
float2 uv : TEXCOORD0;
|
|
float2 uv_depth : TEXCOORD1;
|
|
float4 interpolatedRay : TEXCOORD2;
|
|
};
|
|
|
|
v2f vert (appdata_fog v)
|
|
{
|
|
v2f o;
|
|
v.vertex.z = 0.1;
|
|
o.pos = UnityObjectToClipPos(v.vertex);
|
|
o.uv = v.texcoord.xy;
|
|
o.uv_depth = v.texcoord.xy;
|
|
|
|
#if UNITY_UV_STARTS_AT_TOP
|
|
if (_MainTex_TexelSize.y < 0)
|
|
o.uv.y = 1-o.uv.y;
|
|
#endif
|
|
|
|
int frustumIndex = v.texcoord.x + (2 * o.uv.y);
|
|
o.interpolatedRay = _FrustumCornersWS[frustumIndex];
|
|
o.interpolatedRay.w = frustumIndex;
|
|
|
|
return o;
|
|
}
|
|
|
|
// Applies one of standard fog formulas, given fog coordinate (i.e. distance)
|
|
half ComputeFogFactor (float coord)
|
|
{
|
|
float fogFac = 0.0;
|
|
if (_SceneFogMode.x == 1) // linear
|
|
{
|
|
// factor = (end-z)/(end-start) = z * (-1/(end-start)) + (end/(end-start))
|
|
fogFac = coord * _SceneFogParams.z + _SceneFogParams.w;
|
|
}
|
|
if (_SceneFogMode.x == 2) // exp
|
|
{
|
|
// factor = exp(-density*z)
|
|
fogFac = _SceneFogParams.y * coord; fogFac = exp2(-fogFac);
|
|
}
|
|
if (_SceneFogMode.x == 3) // exp2
|
|
{
|
|
// factor = exp(-(density*z)^2)
|
|
fogFac = _SceneFogParams.x * coord; fogFac = exp2(-fogFac*fogFac);
|
|
}
|
|
return saturate(fogFac);
|
|
}
|
|
|
|
// Distance-based fog
|
|
float ComputeDistance (float3 camDir, float zdepth)
|
|
{
|
|
float dist;
|
|
if (_SceneFogMode.y == 1)
|
|
dist = length(camDir);
|
|
else
|
|
dist = zdepth * _ProjectionParams.z;
|
|
// Built-in fog starts at near plane, so match that by
|
|
// subtracting the near value. Not a perfect approximation
|
|
// if near plane is very large, but good enough.
|
|
dist -= _ProjectionParams.y;
|
|
return dist;
|
|
}
|
|
|
|
// Linear half-space fog, from https://www.terathon.com/lengyel/Lengyel-UnifiedFog.pdf
|
|
float ComputeHalfSpace (float3 wsDir)
|
|
{
|
|
float3 wpos = _CameraWS + wsDir;
|
|
float FH = _HeightParams.x;
|
|
float3 C = _CameraWS;
|
|
float3 V = wsDir;
|
|
float3 P = wpos;
|
|
float3 aV = _HeightParams.w * V;
|
|
float FdotC = _HeightParams.y;
|
|
float k = _HeightParams.z;
|
|
float FdotP = P.y-FH;
|
|
float FdotV = wsDir.y;
|
|
float c1 = k * (FdotP + FdotC);
|
|
float c2 = (1-2*k) * FdotP;
|
|
float g = min(c2, 0.0);
|
|
g = -length(aV) * (c1 - g * g / abs(FdotV+1.0e-5f));
|
|
return g;
|
|
}
|
|
|
|
half4 ComputeFog (v2f i, bool distance, bool height) : SV_Target
|
|
{
|
|
half4 sceneColor = tex2D(_MainTex, UnityStereoTransformScreenSpaceTex(i.uv));
|
|
|
|
// Reconstruct world space position & direction
|
|
// towards this screen pixel.
|
|
float rawDepth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, UnityStereoTransformScreenSpaceTex(i.uv_depth));
|
|
float dpth = Linear01Depth(rawDepth);
|
|
float4 wsDir = dpth * i.interpolatedRay;
|
|
float4 wsPos = _CameraWS + wsDir;
|
|
|
|
// Compute fog distance
|
|
float g = _DistanceParams.x;
|
|
if (distance)
|
|
g += ComputeDistance (wsDir, dpth);
|
|
if (height)
|
|
g += ComputeHalfSpace (wsDir);
|
|
|
|
// Compute fog amount
|
|
half fogFac = ComputeFogFactor (max(0.0,g));
|
|
// Do not fog skybox
|
|
if (dpth == _DistanceParams.y)
|
|
fogFac = 1.0;
|
|
//return fogFac; // for debugging
|
|
|
|
// Lerp between fog color & original scene color
|
|
// by fog amount
|
|
return lerp (unity_FogColor, sceneColor, fogFac);
|
|
}
|
|
|
|
ENDCG
|
|
|
|
SubShader
|
|
{
|
|
ZTest Always Cull Off ZWrite Off Fog { Mode Off }
|
|
|
|
// 0: distance + height
|
|
Pass
|
|
{
|
|
CGPROGRAM
|
|
#pragma vertex vert
|
|
#pragma fragment frag
|
|
half4 frag (v2f i) : SV_Target { return ComputeFog (i, true, true); }
|
|
ENDCG
|
|
}
|
|
// 1: distance
|
|
Pass
|
|
{
|
|
CGPROGRAM
|
|
#pragma vertex vert
|
|
#pragma fragment frag
|
|
half4 frag (v2f i) : SV_Target { return ComputeFog (i, true, false); }
|
|
ENDCG
|
|
}
|
|
// 2: height
|
|
Pass
|
|
{
|
|
CGPROGRAM
|
|
#pragma vertex vert
|
|
#pragma fragment frag
|
|
half4 frag (v2f i) : SV_Target { return ComputeFog (i, false, true); }
|
|
ENDCG
|
|
}
|
|
}
|
|
|
|
Fallback off
|
|
|
|
}
|