You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
244 lines
9.7 KiB
244 lines
9.7 KiB
11 months ago
|
Shader "Azure[Sky]/Fog Scattering"
|
||
|
{
|
||
|
Properties
|
||
|
{
|
||
|
_MainTex ("Texture", 2D) = "white" {}
|
||
|
}
|
||
|
SubShader
|
||
|
{
|
||
|
// No culling or depth
|
||
|
Cull Off ZWrite Off ZTest Always
|
||
|
|
||
|
Pass
|
||
|
{
|
||
|
CGPROGRAM
|
||
|
#pragma vertex vert
|
||
|
#pragma fragment frag
|
||
|
#pragma target 3.0
|
||
|
#include "UnityCG.cginc"
|
||
|
|
||
|
// Start: LuxWater
|
||
|
#pragma multi_compile __ LUXWATER_DEFERREDFOG
|
||
|
|
||
|
#if defined(LUXWATER_DEFERREDFOG)
|
||
|
sampler2D _UnderWaterMask;
|
||
|
float4 _LuxUnderWaterDeferredFogParams; // x: IsInsideWatervolume?, y: BelowWaterSurface shift, z: EdgeBlend
|
||
|
#endif
|
||
|
// End: LuxWater
|
||
|
|
||
|
uniform sampler2D _MainTex;
|
||
|
uniform sampler2D_float _CameraDepthTexture;
|
||
|
uniform float4x4 _FrustumCorners;
|
||
|
uniform float4 _MainTex_TexelSize;
|
||
|
|
||
|
uniform int _Azure_SunsetColorMode;
|
||
|
uniform float _Azure_Pi316, _Azure_Pi14, _Azure_Scattering, _Azure_Pi, _Azure_Exposure, _Azure_NightIntensity, _Azure_LightSpeed, _Azure_MoonBrightRange, _Azure_MoonEmission,
|
||
|
_Azure_FogBlend, _Azure_FogDensity, _Azure_FogDistance, _Azure_FogScale, _Azure_HeightFogBlend, _Azure_HeightFogDensity, _Azure_HeightFogDistance, _Azure_HeightFogStart,
|
||
|
_Azure_HeightFogEnd, _Azure_MieDepth, _Azure_Kr, _Azure_Km;
|
||
|
uniform float3 _Azure_SunDirection, _Azure_MoonDirection, _Azure_Br, _Azure_Bm, _Azure_MieG;
|
||
|
uniform float4 _Azure_RayleighColor, _Azure_MieColor, _Azure_MoonColor, _Azure_MoonBrightColor;
|
||
|
uniform float4x4 _Azure_SunMatrix, _Azure_MoonMatrix, _Azure_StarMatrix, _Azure_NoiseMatrix, _Azure_UpMatrix;
|
||
|
|
||
|
struct appdata
|
||
|
{
|
||
|
float4 vertex : POSITION;
|
||
|
float4 texcoord : TEXCOORD0;
|
||
|
};
|
||
|
|
||
|
struct v2f
|
||
|
{
|
||
|
float4 Position : SV_POSITION;
|
||
|
float2 uv : TEXCOORD0;
|
||
|
float4 interpolatedRay : TEXCOORD1;
|
||
|
float2 uv_depth : TEXCOORD2;
|
||
|
};
|
||
|
|
||
|
v2f vert (appdata v)
|
||
|
{
|
||
|
v2f Output;
|
||
|
UNITY_INITIALIZE_OUTPUT(v2f, Output);
|
||
|
|
||
|
v.vertex.z = 0.1;
|
||
|
Output.Position = UnityObjectToClipPos(v.vertex);
|
||
|
Output.uv = v.texcoord.xy;
|
||
|
Output.uv_depth = v.texcoord.xy;
|
||
|
#if UNITY_UV_STARTS_AT_TOP
|
||
|
if (_MainTex_TexelSize.y < 0)
|
||
|
Output.uv.y = 1 - Output.uv.y;
|
||
|
#endif
|
||
|
|
||
|
//Based on Unity5.6 GlobalFog.
|
||
|
//--------------------------------
|
||
|
int index = v.texcoord.x + (2.0 * Output.uv.y);
|
||
|
Output.interpolatedRay = _FrustumCorners[index];
|
||
|
Output.interpolatedRay.xyz = mul((float3x3)_Azure_UpMatrix, Output.interpolatedRay.xyz);
|
||
|
Output.interpolatedRay.w = index;
|
||
|
|
||
|
return Output;
|
||
|
}
|
||
|
|
||
|
float4 frag (v2f IN) : SV_Target
|
||
|
{
|
||
|
//Initializations.
|
||
|
//--------------------------------
|
||
|
float3 inScatter = float3(0.0, 0.0, 0.0);
|
||
|
float3 nightSky = float3(0.0, 0.0, 0.0);
|
||
|
float3 fex = float3(0.0, 0.0, 0.0);
|
||
|
float r = length(float3(0.0, _Azure_LightSpeed, 0.0));
|
||
|
|
||
|
//Original scene.
|
||
|
//--------------------------------
|
||
|
float3 screen = tex2D(_MainTex, UnityStereoTransformScreenSpaceTex(IN.uv)).rgb;
|
||
|
|
||
|
//Reconstruct world space position and direction towards this screen pixel.
|
||
|
//--------------------------------
|
||
|
float depth = Linear01Depth(UNITY_SAMPLE_DEPTH(tex2D(_CameraDepthTexture,UnityStereoTransformScreenSpaceTex(IN.uv_depth))));
|
||
|
if(depth == 1.0) return float4(screen, 1.0);
|
||
|
float3 viewDir = normalize(depth * IN.interpolatedRay.xyz);
|
||
|
//float3 viewDir = normalize(mul((float3x3)_Azure_UpMatrix, depth * IN.interpolatedRay.xyz));
|
||
|
float sunCosTheta = dot(viewDir, _Azure_SunDirection);
|
||
|
|
||
|
float mieDepth = saturate(lerp(1.0, depth * 4, _Azure_MieDepth));
|
||
|
|
||
|
if(_Azure_SunsetColorMode == 0)
|
||
|
{
|
||
|
//Optical Depth.
|
||
|
//--------------------------------
|
||
|
//float zenith = acos(saturate(dot(float3(0.0, 1.0, 0.0), viewDir)));
|
||
|
float zenith = acos(saturate(dot(float3(-1.0, 1.0, -1.0), depth))) * _Azure_FogScale;
|
||
|
float z = cos(zenith) + 0.15 * pow(93.885 - ((zenith * 180.0) / _Azure_Pi), -1.253);
|
||
|
float SR = _Azure_Kr / z;
|
||
|
float SM = _Azure_Km / z;
|
||
|
|
||
|
//Total Extinction.
|
||
|
//--------------------------------
|
||
|
fex = exp(-(_Azure_Br*SR + _Azure_Bm*SM));
|
||
|
float sunset = clamp(dot(float3(0.0, 1.0, 0.0), _Azure_SunDirection), 0.0, 0.5);
|
||
|
float3 extinction = lerp(fex, (1.0 - fex), sunset);
|
||
|
|
||
|
//Scattering.
|
||
|
//--------------------------------
|
||
|
//float rayPhase = 1.0 + pow(sunCosTheta, 2.0); //Preetham rayleigh phase function.
|
||
|
float rayPhase = 2.0 + 0.5 * pow(sunCosTheta, 2.0); //Rayleigh phase function based on the Nielsen's paper.
|
||
|
float miePhase = _Azure_MieG.x / pow(_Azure_MieG.y - _Azure_MieG.z * sunCosTheta, 1.5); //The Henyey-Greenstein phase function.
|
||
|
|
||
|
float sunRise = saturate(dot(float3(0.0, 500.0, 0.0), _Azure_SunDirection) / r);
|
||
|
|
||
|
float3 BrTheta = _Azure_Pi316 * _Azure_Br * rayPhase * _Azure_RayleighColor.rgb * extinction;
|
||
|
float3 BmTheta = _Azure_Pi14 * _Azure_Bm * miePhase * _Azure_MieColor.rgb * extinction * sunRise;
|
||
|
BmTheta *= mieDepth;
|
||
|
float3 BrmTheta = (BrTheta + BmTheta) / (_Azure_Br + _Azure_Bm);
|
||
|
|
||
|
inScatter = BrmTheta * _Azure_Scattering * (1.0 - fex);
|
||
|
inScatter *= sunRise;
|
||
|
|
||
|
//Night Sky.
|
||
|
//--------------------------------
|
||
|
BrTheta = _Azure_Pi316 * _Azure_Br * rayPhase * _Azure_RayleighColor.rgb;
|
||
|
BrmTheta = (BrTheta) / (_Azure_Br + _Azure_Bm);
|
||
|
nightSky = BrmTheta * _Azure_NightIntensity * (1.0 - fex);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//Optical Depth
|
||
|
//--------------------------------
|
||
|
float zenith = acos(length(viewDir.y));
|
||
|
//float zenith = acos(saturate(dot(float3(-1.0, 1.0, -1.0), depth))) * _Azure_FogScale;
|
||
|
float z = cos(zenith) + 0.15 * pow(93.885 - ((zenith * 180.0) / _Azure_Pi), -1.253);
|
||
|
float SR = _Azure_Kr / z;
|
||
|
float SM = _Azure_Km / z;
|
||
|
|
||
|
//Total Extinction.
|
||
|
//--------------------------------
|
||
|
fex = exp(-(_Azure_Br*SR + _Azure_Bm*SM));
|
||
|
|
||
|
//Scattering.
|
||
|
//--------------------------------
|
||
|
float rayPhase = 2.0 + 0.5 * pow(sunCosTheta, 2.0);
|
||
|
float miePhase = _Azure_MieG.x / pow(_Azure_MieG.y - _Azure_MieG.z * sunCosTheta, 1.5);
|
||
|
|
||
|
float sunRise = saturate(dot(float3(0.0, 500.0, 0.0), _Azure_SunDirection) / r);
|
||
|
|
||
|
float3 BrTheta = _Azure_Pi316 * _Azure_Br * rayPhase * _Azure_RayleighColor.rgb;
|
||
|
float3 BmTheta = _Azure_Pi14 * _Azure_Bm * miePhase * _Azure_MieColor.rgb * sunRise;
|
||
|
BmTheta *= mieDepth;
|
||
|
float3 BrmTheta = (BrTheta + BmTheta) / (_Azure_Br + _Azure_Bm);
|
||
|
|
||
|
inScatter = BrmTheta * _Azure_Scattering * (1.0 - fex);
|
||
|
inScatter *= sunRise;
|
||
|
//inScatter *= pow(max(0.5, depth-0.5), 2.0);
|
||
|
|
||
|
//Night Sky.
|
||
|
//--------------------------------
|
||
|
BrmTheta = (BrTheta) / (_Azure_Br + _Azure_Bm);
|
||
|
nightSky = BrmTheta * _Azure_NightIntensity * (1.0 - fex);
|
||
|
}
|
||
|
|
||
|
//Moon Bright.
|
||
|
//--------------------------------
|
||
|
float moonRise = saturate(dot(float3(0.0, 500.0, 0.0), _Azure_MoonDirection) / r);
|
||
|
float bright = 1.0 + dot(viewDir, -_Azure_MoonDirection);
|
||
|
float3 moonBright = 1.0 / (1.0 + bright * _Azure_MoonBrightRange) * _Azure_MoonBrightColor.rgb;
|
||
|
moonBright += 1.0 / (_Azure_MoonEmission + bright * 200.0) * _Azure_MoonColor.rgb;
|
||
|
moonBright = moonBright * moonRise * mieDepth;
|
||
|
|
||
|
//Output.
|
||
|
//--------------------------------
|
||
|
float3 OutputColor = inScatter + nightSky + moonBright;
|
||
|
|
||
|
//Tonemapping.
|
||
|
OutputColor = saturate(1.0 - exp(-_Azure_Exposure * OutputColor));
|
||
|
|
||
|
//Color Correction.
|
||
|
OutputColor = pow(OutputColor, 2.2);
|
||
|
#ifdef UNITY_COLORSPACE_GAMMA
|
||
|
OutputColor = pow(OutputColor, 0.4545);
|
||
|
#else
|
||
|
OutputColor = OutputColor;
|
||
|
#endif
|
||
|
|
||
|
//return float4(OutputColor.rgb, 1.0);
|
||
|
|
||
|
//Calcule Fog Distance.
|
||
|
//float dpt = saturate(depth * (_ProjectionParams.z / 5000.0));
|
||
|
float fog = smoothstep(-_Azure_FogBlend, 1.25, depth * _ProjectionParams.z / _Azure_FogDistance) * _Azure_FogDensity;
|
||
|
float heightFogDistance = smoothstep(-_Azure_HeightFogBlend, 1.25, depth * _ProjectionParams.z / _Azure_HeightFogDistance);
|
||
|
|
||
|
//Calcule Height Fog.
|
||
|
float3 worldSpaceDirection = mul((float3x3)_Azure_UpMatrix, _WorldSpaceCameraPos) + depth * IN.interpolatedRay.xyz;
|
||
|
float heightFog = saturate((worldSpaceDirection.y - _Azure_HeightFogStart) / (_Azure_HeightFogEnd + _Azure_HeightFogStart));
|
||
|
heightFog = 1.0 - heightFog;
|
||
|
heightFog *= heightFog;
|
||
|
heightFog *= heightFogDistance;
|
||
|
fog = saturate(fog + heightFog * _Azure_HeightFogDensity);
|
||
|
|
||
|
// Start: LuxWater
|
||
|
#if defined(LUXWATER_DEFERREDFOG)
|
||
|
half4 fogMask = tex2D(_UnderWaterMask, UnityStereoTransformScreenSpaceTex(IN.uv));
|
||
|
float watersurfacefrombelow = DecodeFloatRG(fogMask.ba);
|
||
|
|
||
|
// Get distance and lower it a bit in order to handle edge blending artifacts (edge blended parts would not get ANY fog)
|
||
|
float dist = (watersurfacefrombelow - depth) + _LuxUnderWaterDeferredFogParams.y * _ProjectionParams.w;
|
||
|
// Fade fog from above water to below water
|
||
|
float fogFactor = saturate ( 1.0 + _ProjectionParams.z * _LuxUnderWaterDeferredFogParams.z * dist ); // 0.125
|
||
|
// Clamp above result to where water is actually rendered
|
||
|
fogFactor = (fogMask.r == 1) ? fogFactor : 1.0;
|
||
|
// Mask fog on underwarter parts - only if we are inside a volume (bool... :( )
|
||
|
if(_LuxUnderWaterDeferredFogParams.x) {
|
||
|
fogFactor *= saturate( 1.0 - fogMask.g * 8.0);
|
||
|
if (dist < -_ProjectionParams.w * 4 && fogMask.r == 0 && fogMask.g < 1.0) {
|
||
|
fogFactor = 1.0;
|
||
|
}
|
||
|
}
|
||
|
// Tweak fog factor
|
||
|
fog *= fogFactor;
|
||
|
#endif
|
||
|
// End: LuxWater
|
||
|
|
||
|
OutputColor.rgb = lerp(screen.rgb, OutputColor.rgb, fog);
|
||
|
return float4(OutputColor.rgb, 1.0);
|
||
|
}
|
||
|
ENDCG
|
||
|
}
|
||
|
}
|
||
|
}
|