ToriaAssets/Sources/Shaders/UnderWaterFog.shader

157 lines
3.5 KiB
Plaintext
Raw Permalink Normal View History

2026-05-19 12:20:15 +02:00
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Hidden/UnderWaterFog" {
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;
uniform fixed4 _Color;
// for fast world space reconstruction
uniform float4x4 _FrustumCornersWS;
uniform float4 _CameraWS;
struct v2f {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float2 uv_depth : TEXCOORD1;
float4 interpolatedRay : TEXCOORD2;
};
v2f vert (appdata_img v)
{
v2f o;
half index = v.vertex.z;
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
o.interpolatedRay = _FrustumCornersWS[(int)index];
o.interpolatedRay.w = index;
return o;
}
// Applies one of standard fog formulas, given fog coordinate (i.e. distance)
half ComputeFogFactor (float coord)
{
float fogFac = 0.0;
fogFac = coord * _SceneFogParams.z + _SceneFogParams.w;
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, i.uv);
// Reconstruct world space position & direction
// towards this screen pixel.
float rawDepth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv_depth);
float dpth = Linear01Depth(rawDepth);
float4 wsDir = dpth * i.interpolatedRay;
float4 wsPos = _CameraWS + wsDir;
half fogMask = ComputeHalfSpace (wsDir);
half fogFac = ComputeFogFactor (max(0.0,fogMask + _DistanceParams.x));
// Do not fog skybox
if (rawDepth == _DistanceParams.y){
fogMask = 0.0;
}
fixed4 fogColor = lerp(_Color,sceneColor * _Color,fogFac);
return lerp(sceneColor,fogColor,saturate(fogMask * _Color.a));
}
ENDCG
SubShader
{
ZTest Always Cull Off ZWrite Off Fog { Mode Off }
// 0: distance + height
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#define DISTANCE
#define HEIGHT
half4 frag (v2f i) : SV_Target { return ComputeFog (i, true, true); }
ENDCG
}
}
Fallback off
}