254 lines
9.8 KiB
HLSL
254 lines
9.8 KiB
HLSL
|
|
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
|
|||
|
|
|
|||
|
|
uniform float4 _HeightParams;
|
|||
|
|
uniform float4 _DistanceParams;
|
|||
|
|
uniform int4 _SceneFogMode;
|
|||
|
|
uniform float4 _SceneFogParams;
|
|||
|
|
uniform sampler2D _EnviroVolumeLightingTex;
|
|||
|
|
uniform float4 _FogNoiseData;// x: scale, y: intensity, z: intensity offset
|
|||
|
|
uniform float4 _FogNoiseVelocity; // x: x velocity, y: z velocity
|
|||
|
|
uniform float4 _EnviroParams; //gametime,distance,height,_hdr
|
|||
|
|
uniform float _EnviroVolumeDensity;
|
|||
|
|
uniform float3 _Br;
|
|||
|
|
uniform float3 _Bm;
|
|||
|
|
uniform float3 _BmScene;
|
|||
|
|
uniform float3 _mieG;
|
|||
|
|
uniform float3 _mieGScene;
|
|||
|
|
uniform float _FogExposure;
|
|||
|
|
uniform float _SkyLuminance;
|
|||
|
|
uniform float _scatteringPower;
|
|||
|
|
uniform float4 _SunParameters; //x = _SunIntensity, y = _SunDiskSize, z = _SunDiskIntensity;
|
|||
|
|
uniform float4 _scatteringColor;
|
|||
|
|
uniform float _SkyColorPower;
|
|||
|
|
uniform float3 _SunDir;
|
|||
|
|
uniform float _scatteringStrenght;
|
|||
|
|
uniform half _distanceFogIntensity;
|
|||
|
|
uniform float4 _EnviroSkyFog; // x = _SkyFogHeight, y = _SkyFogIntensity, z = _SkyFogStart, w = _HeightFogIntensity
|
|||
|
|
uniform float _maximumFogDensity;
|
|||
|
|
uniform float4 _weatherSkyMod;
|
|||
|
|
uniform float4 _weatherFogMod;
|
|||
|
|
uniform float _lightning;
|
|||
|
|
|
|||
|
|
|
|||
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|||
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|||
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|||
|
|
half3 tonemapACES(half3 color, float Exposure)
|
|||
|
|
{
|
|||
|
|
color *= Exposure;
|
|||
|
|
|
|||
|
|
// See https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/
|
|||
|
|
const half a = 2.51;
|
|||
|
|
const half b = 0.03;
|
|||
|
|
const half c = 2.43;
|
|||
|
|
const half d = 0.59;
|
|||
|
|
const half e = 0.14;
|
|||
|
|
return saturate((color * (a * color + b)) / (color * (c * color + d) + e));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
half ComputeFogFactorEnviro (float coord)
|
|||
|
|
{
|
|||
|
|
float fogFac = 0.0;
|
|||
|
|
|
|||
|
|
if (_SceneFogMode.x == 1) // linear
|
|||
|
|
{
|
|||
|
|
fogFac = coord * _SceneFogParams.z + _SceneFogParams.w;
|
|||
|
|
}
|
|||
|
|
if (_SceneFogMode.x == 2) // exp
|
|||
|
|
{
|
|||
|
|
fogFac = _SceneFogParams.y * coord; fogFac = exp2(-fogFac);
|
|||
|
|
}
|
|||
|
|
if (_SceneFogMode.x == 3) // exp2
|
|||
|
|
{
|
|||
|
|
fogFac = _SceneFogParams.x * coord; fogFac = exp2(-fogFac*fogFac);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return saturate(fogFac);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Distance fog
|
|||
|
|
float ComputeDistance (float3 camDir, float zdepth)
|
|||
|
|
{
|
|||
|
|
float dist;
|
|||
|
|
dist = length(camDir);
|
|||
|
|
// 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 height fog,
|
|||
|
|
float ComputeHalfSpace (float3 wsDir)
|
|||
|
|
{
|
|||
|
|
float3 wpos = _WorldSpaceCameraPos + wsDir;
|
|||
|
|
float FH = _HeightParams.x;
|
|||
|
|
float3 C = _WorldSpaceCameraPos;
|
|||
|
|
float3 V = wsDir;
|
|||
|
|
float3 P = wpos;
|
|||
|
|
float3 aV = (_HeightParams.w * _EnviroSkyFog.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;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
float4 ComputeScattering (float3 viewDir, float2 sunPos)
|
|||
|
|
{
|
|||
|
|
float cosTheta = dot(viewDir, _SunDir);
|
|||
|
|
viewDir = viewDir + float3(0.0, 0.1 ,0.0);
|
|||
|
|
|
|||
|
|
float zen = acos(saturate(viewDir.y));
|
|||
|
|
float alb = (cos(zen) + 0.5 * pow(93.885 - ((zen * 180.0) / 3.141592), - 0.253)); // pi
|
|||
|
|
float3 fex = exp(-(_Br * (4 / alb) + _Bm * (1.25 / alb)));
|
|||
|
|
float rayPhase = 2.5 + pow(cosTheta,1);
|
|||
|
|
float miePhase = _mieG.x / pow(_mieG.y - _mieG.z * cosTheta, 1);
|
|||
|
|
float3 BrTheta = 0.059683 * _Br * rayPhase;
|
|||
|
|
float3 BmTheta = 0.079577 * _Bm * miePhase;
|
|||
|
|
float3 BrmTheta = (BrTheta + BmTheta * 2.0) / ((_Bm + _Br) * 0.75);
|
|||
|
|
float3 scattering = BrmTheta * _SunParameters.x * (1.0 - fex);
|
|||
|
|
float3 skyFinalize = saturate((pow( 1.0 - fex, 2.0) * 0.234) * (1 - sunPos.x)) * _SkyLuminance;
|
|||
|
|
skyFinalize = saturate(lerp(float3(0.1,0.1,0.1), skyFinalize, saturate(dot(viewDir.y + 0.3, float3(0,1,0)))) * (1-fex));
|
|||
|
|
scattering *= saturate((lerp(float3(_scatteringPower, _scatteringPower, _scatteringPower), pow(2000.0f * BrmTheta * fex, 0.7), sunPos.y) * 0.05));
|
|||
|
|
scattering *= (_SkyLuminance * _scatteringColor.rgb * _scatteringStrenght) * pow((1.0 - fex), 1.0) * sunPos.x;
|
|||
|
|
|
|||
|
|
//skyFinalize = lerp(skyFinalize,lerp(skyFinalize,_weatherFogMod, clamp(cosTheta,0,1)), _weatherFogMod.a);
|
|||
|
|
float4 fogScattering = float4((scattering + skyFinalize), 1);
|
|||
|
|
|
|||
|
|
//Tonemapping
|
|||
|
|
if (_EnviroParams.w == 1)
|
|||
|
|
{
|
|||
|
|
fogScattering.rgb = tonemapACES(fogScattering.rgb, _FogExposure);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fogScattering = pow(fogScattering,_SkyColorPower);
|
|||
|
|
fogScattering = lerp(fogScattering,lerp(fogScattering,_weatherSkyMod, clamp(cosTheta,0,1)), _weatherSkyMod.a);
|
|||
|
|
fogScattering = lerp(fogScattering, lerp(fogScattering, _weatherFogMod, _weatherFogMod.a), _weatherFogMod.a);
|
|||
|
|
|
|||
|
|
if(_lightning > 1)
|
|||
|
|
fogScattering = fogScattering + (_lightning * 0.06);
|
|||
|
|
|
|||
|
|
return fogScattering;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
float4 ComputeScatteringClouds(float3 viewDir, float2 sunPos, float time)
|
|||
|
|
{
|
|||
|
|
float cosTheta = dot(viewDir, _SunDir);
|
|||
|
|
viewDir = viewDir + float3(0.0, 0.1, 0.0);
|
|||
|
|
|
|||
|
|
float zen = acos(saturate(viewDir.y));
|
|||
|
|
float alb = (cos(zen) + 0.5 * pow(93.885 - ((zen * 180.0) / 3.141592), -0.253)); // pi
|
|||
|
|
float3 fex = exp(-(_Br * (4 / alb) + _Bm * (1.25 / alb)));
|
|||
|
|
float rayPhase = 2.5 + pow(cosTheta, 1);
|
|||
|
|
float miePhase = _mieG.x / pow(_mieG.y - _mieG.z * cosTheta, 1);
|
|||
|
|
float3 BrTheta = 0.059683 * _Br * rayPhase;
|
|||
|
|
float3 BmTheta = 0.079577 * _Bm * miePhase;
|
|||
|
|
float3 BrmTheta = (BrTheta + BmTheta * 2.0) / ((_Bm + _Br) * 0.75);
|
|||
|
|
float3 scattering = BrmTheta * _SunParameters.x * (1.0 - fex);
|
|||
|
|
float3 skyFinalize = saturate((pow(1.0 - fex, 2.0) * 0.234) * (1 - sunPos.x)) * _SkyLuminance;
|
|||
|
|
skyFinalize = saturate(lerp(float3(0.1, 0.1, 0.1), skyFinalize, saturate(dot(viewDir.y + 0.3, float3(0, 1, 0)))) * (1 - fex));
|
|||
|
|
scattering *= saturate((lerp(float3(_scatteringPower, _scatteringPower, _scatteringPower), pow(2000.0f * BrmTheta * fex, 0.7), sunPos.y) * 0.05));
|
|||
|
|
scattering *= (_SkyLuminance * _scatteringColor.rgb * _scatteringStrenght) * pow((1.0 - fex), 1.0) * sunPos.x;
|
|||
|
|
//skyFinalize = lerp(skyFinalize, lerp(skyFinalize, _weatherFogMod, clamp(cosTheta, 0, 1)), _weatherFogMod.a);
|
|||
|
|
float4 fogScattering = float4((scattering + skyFinalize), 1);
|
|||
|
|
|
|||
|
|
//Tonemapping
|
|||
|
|
if (_EnviroParams.w == 1)
|
|||
|
|
{
|
|||
|
|
fogScattering.rgb = tonemapACES(fogScattering.rgb, _FogExposure);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fogScattering = pow(fogScattering, _SkyColorPower);
|
|||
|
|
fogScattering = lerp(fogScattering, lerp(fogScattering, _weatherSkyMod, clamp(cosTheta, 0, 1)), _weatherSkyMod.a);
|
|||
|
|
fogScattering = lerp(fogScattering, lerp(fogScattering, _weatherFogMod, _weatherFogMod.a), _weatherFogMod.a);
|
|||
|
|
|
|||
|
|
return fogScattering * time;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
float4 ComputeScatteringScene (float3 viewDir, float2 sunPos)
|
|||
|
|
{
|
|||
|
|
float cosTheta = dot(viewDir, _SunDir);
|
|||
|
|
viewDir = viewDir + float3(0.0, 0.1 ,0.0);
|
|||
|
|
float zen = acos(saturate(viewDir.y));
|
|||
|
|
float alb = (cos(zen) + 0.5 * pow(93.885 - ((zen * 180.0) / 3.141592), - 0.253)); // pi
|
|||
|
|
float3 fex = exp(-(_Br * (4 / alb) + _BmScene * (1.25 / alb)));
|
|||
|
|
float rayPhase = 2.5 + pow(cosTheta,1);
|
|||
|
|
float miePhase = _mieGScene.x / pow(_mieGScene.y - _mieGScene.z * cosTheta, 1);
|
|||
|
|
float3 BrTheta = 0.059683 * _Br * rayPhase;
|
|||
|
|
float3 BmTheta = 0.079577 * _BmScene * miePhase;
|
|||
|
|
float3 BrmTheta = (BrTheta + BmTheta * 2.0) / ((_BmScene + _Br) * 0.75);
|
|||
|
|
float3 scattering = BrmTheta * _SunParameters.x * (1.0 - fex);
|
|||
|
|
float3 skyFinalize = saturate((pow( 1.0 - fex, 2.0) * 0.234) * (1 - sunPos.x)) * _SkyLuminance;
|
|||
|
|
skyFinalize = saturate(lerp(float3(0.1,0.1,0.1), skyFinalize, saturate(dot(viewDir.y + 0.3, float3(0,1,0)))) * (1-fex));
|
|||
|
|
scattering *= saturate((lerp(float3(_scatteringPower, _scatteringPower, _scatteringPower), pow(2000.0f * BrmTheta * fex, 0.7), sunPos.y) * 0.05));
|
|||
|
|
scattering *= (_SkyLuminance * _scatteringColor.rgb * _scatteringStrenght) * pow((1.0 - fex), 1.0) * sunPos.x;
|
|||
|
|
|
|||
|
|
float4 fogScattering = float4((scattering + skyFinalize), 1);
|
|||
|
|
|
|||
|
|
//Tonemapping
|
|||
|
|
if (_EnviroParams.w == 1)
|
|||
|
|
{
|
|||
|
|
fogScattering.rgb = tonemapACES(fogScattering.rgb, _FogExposure);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fogScattering = pow(fogScattering,_SkyColorPower);
|
|||
|
|
fogScattering = lerp(fogScattering, lerp(fogScattering, _weatherSkyMod, clamp(cosTheta, 0, 1)), _weatherSkyMod.a);
|
|||
|
|
fogScattering = lerp(fogScattering, lerp(fogScattering, _weatherFogMod, _weatherFogMod.a), _weatherFogMod.a);
|
|||
|
|
|
|||
|
|
if(_lightning > 1)
|
|||
|
|
fogScattering = fogScattering + (_lightning * 0.06);
|
|||
|
|
|
|||
|
|
return fogScattering;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
float4 TransparentFog(float4 clr, float3 wPos,float2 uv, half depth)
|
|||
|
|
{
|
|||
|
|
float3 wsDir = wPos - _WorldSpaceCameraPos;
|
|||
|
|
float g = _DistanceParams.x;
|
|||
|
|
if (_EnviroParams.y > 0)
|
|||
|
|
{
|
|||
|
|
g += ComputeDistance (wsDir, depth);
|
|||
|
|
g *= _distanceFogIntensity ;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (_EnviroParams.z > 0)
|
|||
|
|
{
|
|||
|
|
//g += ComputeHalfSpaceWithNoise (wsDir);
|
|||
|
|
g += ComputeHalfSpace(wsDir);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
float fogFac = ComputeFogFactorEnviro(max(0.0,g));
|
|||
|
|
fogFac = lerp(_maximumFogDensity,1.0f,fogFac);
|
|||
|
|
float4 fogClr = float4(0, 0, 0, 0);
|
|||
|
|
|
|||
|
|
#ifdef UNITY_PASS_FORWARDADD
|
|||
|
|
float4 volumeLighting = float4(0, 0, 0, 0);
|
|||
|
|
#else
|
|||
|
|
|
|||
|
|
#if ENVIRO_SIMPLE_FOG
|
|||
|
|
fogClr = unity_FogColor;
|
|||
|
|
#else
|
|||
|
|
float2 sunDir;
|
|||
|
|
sunDir.x = saturate(_SunDir.y + 0.25);
|
|||
|
|
sunDir.y = saturate(clamp(1.0 - _SunDir.y, 0.0, 0.5));
|
|||
|
|
fogClr = ComputeScatteringScene(normalize(wsDir), sunDir);
|
|||
|
|
#endif
|
|||
|
|
|
|||
|
|
#if UNITY_SINGLE_PASS_STEREO
|
|||
|
|
float4 scaleOffset = unity_StereoScaleOffset[unity_StereoEyeIndex];
|
|||
|
|
uv = (uv - scaleOffset.zw) / scaleOffset.xy;
|
|||
|
|
#endif
|
|||
|
|
|
|||
|
|
float4 volumeLighting = tex2D(_EnviroVolumeLightingTex, uv) * _EnviroParams.x;
|
|||
|
|
#endif
|
|||
|
|
float4 final = lerp (lerp(fogClr, fogClr + volumeLighting, _EnviroVolumeDensity), lerp(clr, clr + volumeLighting, _EnviroVolumeDensity), fogFac);
|
|||
|
|
|
|||
|
|
return final;
|
|||
|
|
}
|