You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
449 lines
14 KiB
Plaintext
449 lines
14 KiB
Plaintext
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
|
|
|
|
|
|
|
|
Shader "Hidden/SuimonoUnderwaterFog" {
|
|
Properties {
|
|
_MainTex ("Base (RGB)", 2D) = "white" {}
|
|
}
|
|
|
|
CGINCLUDE
|
|
|
|
#pragma target 3.0
|
|
#include "UnityCG.cginc"
|
|
|
|
sampler2D _suimono_TransTex;
|
|
//sampler2D _suimono_CausticTex;
|
|
//sampler2D _suimono_underwaterMaskTex;
|
|
sampler2D _underwaterDistort;
|
|
sampler2D _distort1Mask;
|
|
sampler2D _distort2Mask;
|
|
//sampler2D _bgReflectTex;
|
|
|
|
uniform sampler2D _MainTex;
|
|
uniform sampler2D_float _CameraDepthTexture;
|
|
uniform float4 _HeightParams;
|
|
uniform float4 _DistanceParams;
|
|
|
|
int4 _SceneFogMode;
|
|
float4 _SceneFogParams;
|
|
uniform float4 _MainTex_TexelSize;
|
|
|
|
// for fast world space reconstruction
|
|
uniform float4x4 _FrustumCornersWS;
|
|
uniform float4 _CameraWS;
|
|
float _Suimono_IsUnderwater;
|
|
float _lightFactor;
|
|
float4 _suimono_lightColor;
|
|
half4 _BlurOffsets;
|
|
|
|
float4 _underwaterColor;
|
|
float4 _cameraBGColor;
|
|
float _distortAmt;
|
|
float _distortSpeed;
|
|
float _distortScale;
|
|
float _trans1;
|
|
float _trans2;
|
|
float _dropOffx;
|
|
float _dropOffy;
|
|
float _showScreenMask = 0.0;
|
|
//float _useUnderSurfaceView = 0.0;
|
|
float _enableUnderwater;
|
|
float _Suimono_isLinear;
|
|
float _blur;
|
|
float _hDepth;
|
|
float _transStrength;
|
|
|
|
|
|
|
|
struct v2f {
|
|
float4 pos : SV_POSITION;
|
|
float2 uv : TEXCOORD0;
|
|
float2 uv_depth : TEXCOORD1;
|
|
float4 interpolatedRay : TEXCOORD2;
|
|
float3 lightDir : TEXCOORD3;
|
|
half2 taps[4] : TEXCOORD4;
|
|
};
|
|
|
|
|
|
|
|
v2f vert (appdata_tan 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;
|
|
|
|
//get light direction
|
|
o.lightDir = WorldSpaceLightDir(v.vertex);
|
|
|
|
//blur
|
|
o.taps[0] = o.uv + _MainTex_TexelSize * _BlurOffsets.xy;
|
|
o.taps[1] = o.uv - _MainTex_TexelSize * _BlurOffsets.xy;
|
|
o.taps[2] = o.uv + _MainTex_TexelSize * _BlurOffsets.xy * half2(1,-1);
|
|
o.taps[3] = o.uv - _MainTex_TexelSize * _BlurOffsets.xy * half2(1,-1);
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
|
|
|
|
float ComputeDepth(half2 dUV, float3 ray, bool distance, bool height, half dist)
|
|
{
|
|
half fFac = 0.0;
|
|
half rDepth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,dUV);
|
|
|
|
half dp = Linear01Depth(rDepth);
|
|
float3 wDir = dp * ray;
|
|
|
|
// Compute fog distance
|
|
half gd = dist;
|
|
if (distance)
|
|
gd += ComputeDistance (wDir, dp);
|
|
if (height)
|
|
gd += ComputeHalfSpace (wDir);
|
|
|
|
// Compute fog amount
|
|
fFac = ComputeFogFactor (max(0.0,gd));
|
|
fFac = 1.0-fFac;
|
|
|
|
if (rDepth >= 0.999999)
|
|
fFac = 1.0;
|
|
|
|
return saturate(fFac);
|
|
}
|
|
|
|
|
|
|
|
|
|
half4 ComputeFog (v2f i, bool distance, bool height) : SV_Target{
|
|
|
|
half2 uvs = i.uv;
|
|
half3 distortTex = UnpackNormal(tex2D(_underwaterDistort,uvs*_distortScale+float2(_Time.x*_distortSpeed,-_Time.x*0.5*_distortSpeed)));
|
|
|
|
half2 dUV = uvs;
|
|
//dUV.x = dUV.x + (distortTex.x * _distortAmt);
|
|
dUV.x = (dUV.x + (distortTex.x * _distortAmt ) + lerp(_distortAmt*1,-_distortAmt*0.5,dUV.x));
|
|
|
|
half2 dUV2 = dUV;
|
|
|
|
#if UNITY_UV_STARTS_AT_TOP
|
|
if (_MainTex_TexelSize.y < 0){
|
|
dUV2.y = 1 - dUV2.y;
|
|
}
|
|
#endif
|
|
|
|
half4 waterColor = tex2D(_suimono_TransTex, uvs);
|
|
half4 origColor = tex2D(_MainTex,uvs);
|
|
half4 sceneColor = tex2D(_MainTex, dUV);
|
|
half4 underwaterScene = tex2D(_suimono_TransTex,dUV);
|
|
half4 origSceneColor = tex2D(_MainTex, uvs);
|
|
|
|
|
|
//underwater MASK
|
|
half4 underwaterMask = half4(0,0,1,1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//original depth gen
|
|
float rawDepth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,dUV);
|
|
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));
|
|
half fogFac2 = 0;
|
|
|
|
fogFac = 1.0-fogFac;
|
|
|
|
if (rawDepth >= 0.999999)
|
|
fogFac = 1.0;
|
|
|
|
|
|
|
|
//reflected depth gen
|
|
rawDepth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,dUV);
|
|
dpth = Linear01Depth(rawDepth);
|
|
wsDir = dpth * i.interpolatedRay;
|
|
wsPos = _CameraWS + wsDir;
|
|
|
|
|
|
// Compute fog distance
|
|
g = _DistanceParams.x;
|
|
if (distance)
|
|
g += ComputeDistance (wsDir, dpth);
|
|
if (height)
|
|
g += ComputeHalfSpace (wsDir);
|
|
|
|
|
|
// Compute fog amount
|
|
fogFac2 = ComputeFogFactor (max(0.0,g));
|
|
fogFac2 = 1.0-fogFac2;
|
|
|
|
if (rawDepth >= 0.999999)
|
|
fogFac2 = 1.0;
|
|
|
|
|
|
|
|
|
|
//compute background fog color
|
|
_underwaterColor = _cameraBGColor;
|
|
_underwaterColor.rgb = _underwaterColor.rgb * lerp(float4(2.2,2.2,2.2,2.2),float4(1,1,1,1),_Suimono_isLinear);
|
|
half3 fogCola = _underwaterColor.rgb * 0.25;
|
|
|
|
//depth color influence
|
|
half depthFaca = saturate(lerp((half)0.3, (half)1.6,dot(normalize(half3(wsDir.x, wsDir.y, wsDir.z)), half3(0,-1,0))));
|
|
fogCola = lerp(fogCola, fogCola*half3(0.1,0.1,0.1), depthFaca);
|
|
|
|
//light color influence
|
|
half lightFaca = saturate(lerp((half)0.0, (half)0.8,dot(normalize(half3(wsDir.x, wsDir.y, wsDir.z)),i.lightDir))-depthFaca);
|
|
fogCola = lerp(fogCola, fogCola*(half)2, lightFaca);
|
|
half lightFac2a = saturate(lerp((half)-5.0, (half)0.5, dot(normalize(half3(wsDir.x, wsDir.y, wsDir.z)),i.lightDir))-depthFaca)*2;
|
|
fogCola = lerp(fogCola, fogCola * (half)1.4, lightFac2a);
|
|
|
|
half3 depthCol = fogCola.rgb*_suimono_lightColor*_lightFactor;
|
|
|
|
//darken underwater fog based on depth
|
|
depthCol = lerp(depthCol,depthCol*(half)0.05,_hDepth);
|
|
|
|
|
|
|
|
//Blur Distance
|
|
half fogFac3 = ComputeDepth(dUV2,i.interpolatedRay, distance,height,_DistanceParams.x);
|
|
_blur = lerp((float)0, (float)4, ComputeDepth(dUV,i.interpolatedRay, distance,height,-5));
|
|
|
|
half2 uUv = dUV + lerp(half2(0,0), (_MainTex_TexelSize * _BlurOffsets.xy), _blur);
|
|
half3 color = lerp((half3)tex2D(_MainTex,uUv).rgb, (half3)depthCol, ComputeDepth(uUv,i.interpolatedRay, distance,height,_DistanceParams.x) );
|
|
uUv = dUV - lerp(half2(0,0), (_MainTex_TexelSize * _BlurOffsets.xy), _blur);
|
|
color += lerp((half3)tex2D(_MainTex,uUv).rgb, (half3)depthCol, ComputeDepth(uUv,i.interpolatedRay, distance,height,_DistanceParams.x) );
|
|
|
|
uUv = dUV + lerp(half2(0,0),(_MainTex_TexelSize * _BlurOffsets.xy * half2(1,-1)),_blur);
|
|
color += lerp((half3)tex2D(_MainTex,uUv).rgb, (half3)depthCol, ComputeDepth(uUv,i.interpolatedRay, distance,height,_DistanceParams.x) );
|
|
uUv = dUV - lerp(half2(0,0),(_MainTex_TexelSize * _BlurOffsets.xy * half2(1,-1)),_blur);
|
|
color += lerp((half3)tex2D(_MainTex,uUv).rgb, (half3)depthCol, ComputeDepth(uUv,i.interpolatedRay, distance,height,_DistanceParams.x) );
|
|
|
|
uUv = dUV + lerp(half2(0,0),(_MainTex_TexelSize * _BlurOffsets.xy * half2(-1,1)),_blur);
|
|
color += lerp((half3)tex2D(_MainTex,uUv).rgb, (half3)depthCol, ComputeDepth(uUv,i.interpolatedRay, distance,height,_DistanceParams.x) );
|
|
uUv = dUV - lerp(half2(0,0),(_MainTex_TexelSize * _BlurOffsets.xy * half2(-1,1)),_blur);
|
|
color += lerp((half3)tex2D(_MainTex,uUv).rgb, (half3)depthCol, ComputeDepth(uUv,i.interpolatedRay, distance,height,_DistanceParams.x) );
|
|
|
|
uUv = dUV + lerp(half2(0,0),(_MainTex_TexelSize * (_BlurOffsets.xy*0.5)),_blur);
|
|
color += lerp((half3)tex2D(_MainTex,uUv).rgb, (half3)depthCol, ComputeDepth(uUv,i.interpolatedRay, distance,height,_DistanceParams.x) );
|
|
uUv = dUV - lerp(half2(0,0),(_MainTex_TexelSize * (_BlurOffsets.xy*0.5)),_blur);
|
|
color += lerp((half3)tex2D(_MainTex,uUv).rgb, (half3)depthCol, ComputeDepth(uUv,i.interpolatedRay, distance,height,_DistanceParams.x) );
|
|
uUv = dUV + lerp(half2(0,0),(_MainTex_TexelSize * (_BlurOffsets.xy*0.5) * half2(0.5,-0.5)),_blur);
|
|
color += lerp((half3)tex2D(_MainTex,uUv).rgb, (half3)depthCol, ComputeDepth(uUv,i.interpolatedRay, distance,height,_DistanceParams.x) );
|
|
uUv = dUV - lerp(half2(0,0),(_MainTex_TexelSize * (_BlurOffsets.xy*0.5) * half2(-0.5,0.5)),_blur);
|
|
color += lerp((half3)tex2D(_MainTex,uUv).rgb, (half3)depthCol, ComputeDepth(uUv,i.interpolatedRay, distance,height,_DistanceParams.x) );
|
|
|
|
sceneColor.rgb = color * 0.1;
|
|
|
|
|
|
|
|
//FINAL COLOR
|
|
half4 retCol;
|
|
retCol.a = 1.0;
|
|
|
|
|
|
|
|
|
|
half3 bgCol = underwaterScene.rgb;
|
|
if (_Suimono_IsUnderwater == 1.0){
|
|
bgCol = sceneColor;
|
|
}
|
|
|
|
|
|
bgCol = lerp((half3)underwaterScene.rgb, (half3)bgCol,underwaterMask.b);
|
|
|
|
|
|
|
|
|
|
//blend underwater fog
|
|
retCol.rgb = lerp((half3)bgCol.rgb, (half3)depthCol.rgb * (half3)_suimono_lightColor * (half3)_lightFactor, fogFac3);
|
|
|
|
half3 underCol = retCol.rgb;
|
|
|
|
retCol.rgb = lerp((half3)origSceneColor.rgb, (half3)retCol.rgb, saturate(underwaterMask.g+lerp(0,underwaterMask.b,_Suimono_IsUnderwater)));
|
|
|
|
|
|
|
|
//screen effects
|
|
half3 tCol = lerp(half3(1,1,1), half3(0.1,0.6,0.8), 0.2);
|
|
half2 sUV = uvs;
|
|
half3 baseTex = UnpackNormal(tex2D(_underwaterDistort,uvs*0.4-float2(_Time.x*1.3,_Time.x*1.3)));
|
|
half baseDis = uvs.x + (baseTex.x*0.05);
|
|
|
|
half3 screenTex = UnpackNormal(tex2D(_underwaterDistort,uvs*0.1+float2(sUV.x*0.1+baseDis,_Time.x*1)));
|
|
half distort1Mask = tex2D(_distort1Mask,uvs*0.1+float2(uvs.x*0.1+baseDis,_Time.x*1)).r;
|
|
//sUV.x = sUV.x-lerp((screenTex.x*(half)0.08), (half)0.0, 0.0);
|
|
sUV.x = (sUV.x + (screenTex.x * (half)0.08) + lerp(0.08,-0.04,sUV.x));
|
|
|
|
half4 distort1Color = tex2D(_MainTex, sUV);
|
|
|
|
half trans1Time = saturate(_trans1);
|
|
distort1Mask = saturate(lerp((half)0.1 - (half)trans1Time, (half)11 - ((half)11 * (half)trans1Time), distort1Mask));
|
|
|
|
retCol.rgb = lerp((half3)retCol.rgb, (half3)retCol.rgb*(half3)0.9*tCol, distort1Mask*_transStrength);
|
|
retCol.rgb = lerp((half3)retCol.rgb, (half3)distort1Color.rgb, distort1Mask*1.2*_transStrength);
|
|
|
|
|
|
//drops
|
|
half trans2Time = saturate(_trans2);
|
|
|
|
half2 rUV = uvs;
|
|
half distort2Mask = tex2D(_distort2Mask,uvs*float2(0.4,0.23)+float2(_dropOffx,_Time.x*0.11+_dropOffy)).r;
|
|
//rUV.x = rUV.x-(distort2Mask*0.1);
|
|
rUV.x = (rUV.x + (distort2Mask * 0.1) + lerp((distort2Mask * 0.1),(distort2Mask * -0.05),rUV.x));
|
|
|
|
half4 distort2Color = tex2D(_MainTex, rUV);
|
|
distort2Mask = saturate(lerp((half)0.2-(half)trans2Time, (half)2 - ((half)2 * (half)trans2Time), distort2Mask));
|
|
retCol.rgb = lerp((half3)retCol.rgb, (half3)retCol.rgb*(half3)0.9*(half3)tCol, distort2Mask*_transStrength);
|
|
retCol.rgb = lerp((half3)retCol.rgb, lerp((half3)distort2Color.rgb, lerp((half3)distort2Color.rgb, (half3)distort1Color.rgb, distort2Mask), half3(0.1,0.1,0.1)), distort2Mask*1.2*_transStrength);
|
|
|
|
half2 rUV2 = uvs;
|
|
half distort3Mask = tex2D(_distort2Mask,uvs*float2(0.8,0.6)+float2(_dropOffx,_Time.x*0.075+_dropOffy)).r;
|
|
//rUV2.x = rUV2.x-(distort3Mask*0.1);
|
|
rUV2.x = (rUV2.x + (distort3Mask * 0.1) + lerp((distort3Mask * 0.1),(distort3Mask * -0.05),rUV2.x));
|
|
|
|
half4 distort3Color = tex2D(_MainTex, rUV2);
|
|
distort3Mask = saturate(lerp((half)0.2-(half)trans2Time,(half)2 - ((half)2 * (half)trans2Time),distort3Mask));
|
|
retCol.rgb = lerp((half3)retCol.rgb, (half3)retCol.rgb*(half3)0.9*tCol, distort3Mask*_transStrength);
|
|
retCol.rgb = lerp((half3)retCol.rgb, lerp((half3)distort3Color.rgb, lerp((half3)distort3Color.rgb, (half3)distort1Color.rgb, distort3Mask),half3(0.1,0.1,0.1)), distort3Mask*1.2*_transStrength);
|
|
|
|
|
|
//blend effects based on underwater mask
|
|
half3 overCol = retCol.rgb;
|
|
overCol.rgb = lerp((half3)retCol.rgb, (half3)retCol.rgb, underwaterMask.g);
|
|
retCol.rgb = lerp((half3)overCol.rgb, (half3)underCol.rgb, saturate(underwaterMask.g));
|
|
|
|
retCol.rgb = lerp((half3)retCol.rgb, (half3)underwaterMask.rgb, _showScreenMask);
|
|
|
|
//set blank underwater
|
|
retCol.rgb = lerp((half3)origColor.rgb, (half3)retCol.rgb, _enableUnderwater);
|
|
|
|
return retCol;
|
|
}
|
|
|
|
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 "Diffuse"
|
|
|
|
}
|