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

// 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"
}