| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 | Shader "Hidden/UnderWaterFog" {Properties {	_MainTex ("Base (RGB)", 2D) = "black" {}}CGINCLUDE	#include "UnityCG.cginc"	uniform sampler2D _MainTex;	UNITY_DECLARE_DEPTH_TEXTURE(_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));	}ENDCGSubShader{	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}
 |